first commit
This commit is contained in:
@@ -0,0 +1,297 @@
|
||||
/*globals vkbeautify, jQuery, wp */
|
||||
|
||||
var WPML = WPML || {};
|
||||
var WPML_TM = WPML_TM || {};
|
||||
|
||||
//Hack required for the core CodeMirror extensions to work
|
||||
var CodeMirror = wp.CodeMirror || CodeMirror;
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
//Make easier to deal with changing namespaces
|
||||
WPML.CodeMirror = WPML.CodeMirror || CodeMirror || null;
|
||||
|
||||
WPML_TM.Custom_XML_Editor = function (element) {
|
||||
this.container = element;
|
||||
this.content = this.container.getElementsByClassName('wpml-tm-custom-xml-content')[0];
|
||||
this.saveButton = this.container.getElementsByClassName('.button-primary')[0];
|
||||
this.editor = {};
|
||||
this.hightLightedLines = [];
|
||||
};
|
||||
|
||||
WPML_TM.Custom_XML_Editor.prototype = {
|
||||
init: function () {
|
||||
this.initCodeMirror();
|
||||
},
|
||||
initCodeMirror: function () {
|
||||
if (!WPML.CodeMirror) {
|
||||
return;
|
||||
}
|
||||
this.editor = WPML.CodeMirror.fromTextArea(this.content, {
|
||||
lineNumbers: true,
|
||||
mode: {
|
||||
name: 'xml',
|
||||
htmlMode: false
|
||||
},
|
||||
|
||||
matchBrackets: true,
|
||||
autoCloseBrackets: true,
|
||||
|
||||
matchTags: {bothTags: true},
|
||||
autoCloseTags: true,
|
||||
|
||||
indentUnit: 2,
|
||||
tabSize: 2,
|
||||
smartIndent: true,
|
||||
|
||||
extraKeys: this.getKeysMap(),
|
||||
|
||||
foldGutter: true,
|
||||
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
|
||||
|
||||
hintOptions: {
|
||||
schemaInfo: this.getXMLSchema()
|
||||
}
|
||||
});
|
||||
|
||||
var toolbar = this.container.getElementsByClassName('wpml-tm-custom-xml-toolbar')[0];
|
||||
this.editor.addPanel(toolbar, {
|
||||
position: 'top',
|
||||
stable: true
|
||||
});
|
||||
|
||||
this.editor.setOption('theme', 'dracula');
|
||||
this.editor.setCursor(0, 0);
|
||||
},
|
||||
highlightErrors: function (errors) {
|
||||
for (var index in errors) {
|
||||
if (errors.hasOwnProperty(index)) {
|
||||
var errorsGroup = errors[index];
|
||||
|
||||
if (errorsGroup.constructor === Array) {
|
||||
for (var errorGroupIndex in errorsGroup) {
|
||||
if (errorsGroup.hasOwnProperty(errorGroupIndex)) {
|
||||
var error = errorsGroup[errorGroupIndex];
|
||||
if (error.hasOwnProperty('line')) {
|
||||
this.highlightLine(error.line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
highlightLine: function (lineNumber) {
|
||||
if (lineNumber >= 1) {
|
||||
this.editor.addLineClass(lineNumber - 1, 'wrap', 'line-error');
|
||||
this.hightLightedLines.push(lineNumber - 1);
|
||||
}
|
||||
},
|
||||
resetHighlightedLines: function () {
|
||||
for (var index in this.hightLightedLines) {
|
||||
if (this.hightLightedLines.hasOwnProperty(index)) {
|
||||
this.editor.removeLineClass(this.hightLightedLines[index], 'wrap', 'line-error');
|
||||
}
|
||||
}
|
||||
this.hightLightedLines = [];
|
||||
},
|
||||
foldCode: function (cm) {
|
||||
cm.foldCode(cm.getCursor());
|
||||
},
|
||||
autoFormat: function (cm) {
|
||||
cm.save();
|
||||
cm.setValue(vkbeautify.xml(cm.getValue()));
|
||||
},
|
||||
prepareSave: function () {
|
||||
this.resetHighlightedLines();
|
||||
this.autoFormat(this.editor);
|
||||
this.editor.save();
|
||||
},
|
||||
onSaveRequest: function () {
|
||||
this.prepareSave();
|
||||
if ('undefined' !== this.onSave) {
|
||||
this.onSave();
|
||||
}
|
||||
},
|
||||
getXMLSchema: function () {
|
||||
var translateOptions = {
|
||||
attrs: {
|
||||
'translate': ['0', '1']
|
||||
}
|
||||
};
|
||||
|
||||
var translateActions = {
|
||||
attrs: {
|
||||
'action': ['copy', 'translate', 'ignore', 'copy-once'],
|
||||
'style': ['line', 'textarea', 'visual'],
|
||||
'translate_link_target': ['0', '1'],
|
||||
'convert_to_sticky': ['0', '1'],
|
||||
'label': null,
|
||||
'group': null
|
||||
}
|
||||
};
|
||||
|
||||
var genericKey = {
|
||||
attrs: {
|
||||
'name': null,
|
||||
children: ['key']
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
'!top': ['wpml-config'],
|
||||
'wpml-config': {
|
||||
children: [
|
||||
'language-switcher-settings',
|
||||
'custom-types',
|
||||
'taxonomies',
|
||||
'shortcodes',
|
||||
'custom-fields',
|
||||
'admin-texts',
|
||||
'elementor-widgets',
|
||||
'beaver-builder-widgets',
|
||||
'cornerstone-widgets'
|
||||
]
|
||||
},
|
||||
'language-switcher-settings': {
|
||||
children: ['key']
|
||||
},
|
||||
'custom-types': {
|
||||
children: ['custom-type']
|
||||
},
|
||||
'custom-type': translateOptions,
|
||||
'taxonomies': {
|
||||
children: ['taxonomy']
|
||||
},
|
||||
'taxonomy': translateOptions,
|
||||
'shortcodes': {
|
||||
children: ['shortcode']
|
||||
},
|
||||
'shortcode': {
|
||||
children: ['tag', 'attributes']
|
||||
},
|
||||
'tag': {
|
||||
attrs: {
|
||||
'encoding': null
|
||||
}
|
||||
},
|
||||
'attributes': {
|
||||
children: ['attribute']
|
||||
},
|
||||
'attribute': {},
|
||||
'custom-fields': {
|
||||
children: ['custom-field']
|
||||
},
|
||||
'custom-field': translateActions,
|
||||
'custom-term-field': {
|
||||
children: ['wpml-custom-term-field']
|
||||
},
|
||||
'wpml-custom-term-field': translateActions,
|
||||
'admin-texts': {
|
||||
children: ['key']
|
||||
},
|
||||
'key': genericKey,
|
||||
'elementor-widgets': {
|
||||
children: ['widget']
|
||||
},
|
||||
'beaver-builder-widgets': {
|
||||
children: ['widget']
|
||||
},
|
||||
'cornerstone-widgets': {
|
||||
children: ['widget']
|
||||
},
|
||||
'widget': {
|
||||
attrs: {
|
||||
name: null,
|
||||
},
|
||||
children: [
|
||||
'conditions',
|
||||
'fields',
|
||||
'fields-in-item',
|
||||
'integration-classes'
|
||||
]
|
||||
},
|
||||
'conditions': {
|
||||
children: ['condition']
|
||||
},
|
||||
'condition': {
|
||||
attrs: {
|
||||
key: null
|
||||
}
|
||||
},
|
||||
'fields': {
|
||||
children: ['field']
|
||||
},
|
||||
'fields-in-item': {
|
||||
children: ['field'],
|
||||
attrs: {
|
||||
items_of: null
|
||||
}
|
||||
},
|
||||
'field': {
|
||||
attrs: {
|
||||
type: null,
|
||||
editor_type: [
|
||||
'LINE',
|
||||
'AREA',
|
||||
'VISUAL',
|
||||
'LINK'
|
||||
],
|
||||
key_of: null,
|
||||
field_id: null
|
||||
}
|
||||
},
|
||||
'integration-classes': {
|
||||
children: ['integration-class']
|
||||
},
|
||||
'integration-class': {}
|
||||
};
|
||||
},
|
||||
getKeysMap: function () {
|
||||
var mac = WPML.CodeMirror.keyMap["default"] === WPML.CodeMirror.keyMap.macDefault;
|
||||
var ctrl = mac ? "Cmd-" : "Ctrl-";
|
||||
|
||||
var extraKeys = {
|
||||
"'<'": this.completeAfter.bind(this),
|
||||
"'/'": this.completeIfAfterLt.bind(this),
|
||||
"' '": this.completeIfInTag.bind(this),
|
||||
"'='": this.completeIfInTag.bind(this)
|
||||
};
|
||||
|
||||
extraKeys[ctrl + 'Space'] = 'autocomplete';
|
||||
extraKeys[ctrl + 'K'] = this.foldCode;
|
||||
extraKeys[ctrl + 'F'] = this.autoFormat;
|
||||
extraKeys[ctrl + 'S'] = this.onSaveRequest.bind(this);
|
||||
|
||||
return extraKeys;
|
||||
},
|
||||
completeAfter: function (cm, pred) {
|
||||
if (!pred || pred()) {
|
||||
setTimeout(function () {
|
||||
if (!cm.state.completionActive) {
|
||||
cm.showHint({completeSingle: false});
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
return WPML.CodeMirror.Pass;
|
||||
|
||||
},
|
||||
completeIfAfterLt: function (cm) {
|
||||
return this.completeAfter(cm, function () {
|
||||
var cur = cm.getCursor();
|
||||
return cm.getRange(WPML.CodeMirror.Pos(cur.line, cur.ch - 1), cur) === "<";
|
||||
});
|
||||
},
|
||||
completeIfInTag: function (cm) {
|
||||
return this.completeAfter(cm, function () {
|
||||
var tok = cm.getTokenAt(cm.getCursor());
|
||||
if (tok.type === "string" && (!/['"]/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length === 1)) {
|
||||
return false;
|
||||
}
|
||||
var inner = WPML.CodeMirror.innerMode(cm.getMode(), tok.state).state;
|
||||
return inner.tagName;
|
||||
});
|
||||
}
|
||||
};
|
||||
}());
|
||||
@@ -0,0 +1,173 @@
|
||||
/*globals jQuery, ajaxurl */
|
||||
|
||||
var WPML_TM = WPML_TM || {};
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
WPML_TM.Custom_XML = function (element, codeMirror) {
|
||||
this.container = element;
|
||||
this.spinner = this.container.find('.spinner');
|
||||
this.content = this.container.find('.wpml-tm-custom-xml-content');
|
||||
this.messages = this.container.find('.js-wpml-tm-messages');
|
||||
this.action = this.content.data('action');
|
||||
this.nonceValidate = this.content.data('nonce-validate');
|
||||
this.nonceSave = this.content.data('nonce-save');
|
||||
this.saveButton = this.container.find('.button-primary');
|
||||
this.editor = codeMirror;
|
||||
};
|
||||
|
||||
WPML_TM.Custom_XML.prototype = {
|
||||
init: function () {
|
||||
this.saveButton.on('click', jQuery.proxy(this.onSave, this));
|
||||
if (this.editor) {
|
||||
this.editor.init();
|
||||
this.editor.onSave = jQuery.proxy(function () {this.saveButton.trigger('click');}, this);
|
||||
}
|
||||
},
|
||||
onSave: function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
if (this.editor) {
|
||||
this.editor.prepareSave();
|
||||
}
|
||||
|
||||
var content = this.content.val();
|
||||
|
||||
this.messages.empty();
|
||||
this.showSpinner();
|
||||
this.validate(content);
|
||||
},
|
||||
validate: function (content) {
|
||||
jQuery.ajax({
|
||||
type: 'POST',
|
||||
url: ajaxurl,
|
||||
data: {
|
||||
action: this.action + '-validate',
|
||||
nonce: this.nonceValidate,
|
||||
content: content
|
||||
},
|
||||
context: this,
|
||||
success: jQuery.proxy(this.validated, this),
|
||||
error: jQuery.proxy(this.onError, this)
|
||||
});
|
||||
},
|
||||
validated: function (response) {
|
||||
this.addMessage(response);
|
||||
if (response.success) {
|
||||
this.save(this.content.val());
|
||||
} else {
|
||||
this.highlightErrors(response);
|
||||
this.hideSpinner();
|
||||
}
|
||||
},
|
||||
onError: function (response) {
|
||||
this.addMessage(response);
|
||||
this.highlightErrors(response);
|
||||
this.hideSpinner();
|
||||
},
|
||||
highlightErrors: function (response) {
|
||||
if (this.editor) {
|
||||
this.editor.highlightErrors(response.data);
|
||||
}
|
||||
},
|
||||
save: function (content) {
|
||||
jQuery.ajax({
|
||||
type: 'POST',
|
||||
url: ajaxurl,
|
||||
data: {
|
||||
action: this.action + '-save',
|
||||
nonce: this.nonceSave,
|
||||
content: content
|
||||
},
|
||||
context: this,
|
||||
success: jQuery.proxy(this.saved, this),
|
||||
error: jQuery.proxy(this.onError, this),
|
||||
complete: jQuery.proxy(this.hideSpinner, this)
|
||||
});
|
||||
},
|
||||
saved: function (response) {
|
||||
this.addMessage(response);
|
||||
},
|
||||
addMessage: function (response) {
|
||||
var message = '';
|
||||
var type = '';
|
||||
if ('undefined' !== response) {
|
||||
message = 'error';
|
||||
type = 'error';
|
||||
if (response.hasOwnProperty('success') && response.success) {
|
||||
type = 'info';
|
||||
message = 'success';
|
||||
}
|
||||
if (response.hasOwnProperty('data') && response.data) {
|
||||
if (typeof(response.data) === 'string' || response.data instanceof String) {
|
||||
message = response.data;
|
||||
} else if (response.data.constructor === Array) {
|
||||
message = this.convertArrayToUL(response.data);
|
||||
} else if (typeof response.data === 'object') {
|
||||
message = this.convertObjectToTable(response.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
var messageContainer = jQuery('<p></p>');
|
||||
messageContainer.addClass(type);
|
||||
messageContainer.html(message);
|
||||
this.messages.append(messageContainer);
|
||||
},
|
||||
showSpinner: function () {
|
||||
this.spinner.addClass('is-active');
|
||||
},
|
||||
hideSpinner: function () {
|
||||
this.spinner.removeClass('is-active');
|
||||
},
|
||||
convertObjectToTable: function (data) {
|
||||
var html = '<table>';
|
||||
for (var property in data) {
|
||||
if (data.hasOwnProperty(property)) {
|
||||
html += '<tr><th>' + property + '</th><td>' + data[property] + '</td></tr>';
|
||||
}
|
||||
}
|
||||
html += '</table>';
|
||||
return html;
|
||||
},
|
||||
convertArrayToUL: function (data) {
|
||||
var html = '<ul>';
|
||||
for (var property in data) {
|
||||
if (data.hasOwnProperty(property)) {
|
||||
html += '<li>';
|
||||
if (typeof(data[property]) === 'string' || data[property] instanceof String) {
|
||||
html += data[property];
|
||||
} else if (data[property].constructor === Array) {
|
||||
html += this.convertArrayToUL(data[property]);
|
||||
} else if (typeof data[property] === 'object') {
|
||||
if (data[property].hasOwnProperty('message') && data[property].message) {
|
||||
html += data[property].message;
|
||||
} else if (data[property].hasOwnProperty('error') && data[property].error) {
|
||||
html += data[property].error;
|
||||
} else {
|
||||
html += this.convertObjectToTable(data[property]);
|
||||
}
|
||||
}
|
||||
html += '</li>';
|
||||
}
|
||||
}
|
||||
html += '</ul>';
|
||||
return html;
|
||||
}
|
||||
};
|
||||
|
||||
jQuery(function () {
|
||||
var items = document.getElementsByClassName('js-wpml-tm-custom-xml');
|
||||
|
||||
var i;
|
||||
for (i = 0; i < items.length; i++) {
|
||||
var codeMirror;
|
||||
if (WPML_TM.Custom_XML_Editor) {
|
||||
codeMirror = new WPML_TM.Custom_XML_Editor(items[i]);
|
||||
}
|
||||
var customXML = new WPML_TM.Custom_XML(jQuery(items[i]), codeMirror);
|
||||
customXML.init();
|
||||
}
|
||||
});
|
||||
|
||||
}());
|
||||
Reference in New Issue
Block a user