313 lines
11 KiB
JavaScript
313 lines
11 KiB
JavaScript
/**
|
|
* plugin.js
|
|
*
|
|
* Copyright, BuboBox
|
|
* Released under MIT License.
|
|
*
|
|
* License: https://www.bubobox.com
|
|
* Contributing: https://www.bubobox.com/contributing
|
|
*/
|
|
|
|
/*global tinymce:true */
|
|
|
|
$(document).ready(function () {
|
|
|
|
initPlugin();
|
|
|
|
function initPlugin() {
|
|
|
|
if (typeof tinymce === 'undefined') {
|
|
return setTimeout(function () {
|
|
initPlugin();
|
|
}, 200);
|
|
}
|
|
|
|
tinymce.PluginManager.add('variable', function (editor) {
|
|
var VK = tinymce.util.VK;
|
|
|
|
/**
|
|
* Object that is used to replace the variable string to be used
|
|
* in the HTML view
|
|
* @type {object}
|
|
*/
|
|
var mapper = editor.getParam("variable_mapper", {});
|
|
|
|
/**
|
|
* define a list of variables that are allowed
|
|
* if the variable is not in the list it will not be automatically converterd
|
|
* by default no validation is done
|
|
* @todo make it possible to pass in a function to be used a callback for validation
|
|
* @type {array}
|
|
*/
|
|
var valid = editor.getParam("variable_valid", null);
|
|
|
|
/**
|
|
* Get custom variable class name
|
|
* @type {string}
|
|
*/
|
|
var className = editor.getParam("variable_class", "variable");
|
|
|
|
/**
|
|
* Prefix and suffix to use to mark a variable
|
|
* @type {string}
|
|
*/
|
|
var prefix = editor.getParam("variable_prefix", "{");
|
|
var suffix = editor.getParam("variable_suffix", "}");
|
|
var stringVariableRegex = new RegExp(prefix + '([a-z. _]*)?' + suffix, 'g');
|
|
|
|
/**
|
|
* check if a certain variable is valid
|
|
* @param {string} name
|
|
* @return {bool}
|
|
*/
|
|
function isValid(name) {
|
|
|
|
if (!valid || valid.length === 0)
|
|
return true;
|
|
|
|
var validString = '|' + valid.join('|') + '|';
|
|
|
|
return validString.indexOf('|' + name + '|') > -1 ? true : false;
|
|
}
|
|
|
|
function getMappedValue(cleanValue) {
|
|
if (typeof mapper === 'function')
|
|
return mapper(cleanValue);
|
|
|
|
return mapper.hasOwnProperty(cleanValue) ? mapper[cleanValue] : cleanValue;
|
|
}
|
|
|
|
/**
|
|
* Strip variable to keep the plain variable string
|
|
* @example "{test}" => "test"
|
|
* @param {string} value
|
|
* @return {string}
|
|
*/
|
|
function cleanVariable(value) {
|
|
return value.replace(/[^a-zA-Z0-9._]/g, "");
|
|
}
|
|
|
|
/**
|
|
* convert a text variable "x" to a span with the needed
|
|
* attributes to style it with CSS
|
|
* @param {string} value
|
|
* @return {string}
|
|
*/
|
|
function createHTMLVariable(value) {
|
|
|
|
var cleanValue = cleanVariable(value);
|
|
|
|
// check if variable is valid
|
|
if (!isValid(cleanValue))
|
|
return value;
|
|
|
|
var cleanMappedValue = getMappedValue(cleanValue);
|
|
|
|
editor.fire('variableToHTML', {
|
|
value: value,
|
|
cleanValue: cleanValue
|
|
});
|
|
|
|
var variable = prefix + cleanValue + suffix;
|
|
return '<span class="' + className + '" data-original-variable="' + variable + '" contenteditable="false">' + cleanMappedValue + '</span>';
|
|
}
|
|
|
|
function createSrcHTMLVariable(value) {
|
|
var cleanValue = cleanVariable(value);
|
|
|
|
// check if variable is valid
|
|
if (!isValid(cleanValue))
|
|
return value;
|
|
|
|
var cleanMappedValue = getMappedValue(cleanValue);
|
|
|
|
editor.fire('variableToHTML', {
|
|
value: value,
|
|
cleanValue: cleanValue
|
|
});
|
|
|
|
return cleanMappedValue;
|
|
}
|
|
|
|
/**
|
|
* convert variable strings into html elements
|
|
* @return {void}
|
|
*/
|
|
function stringToHTML() {
|
|
var nodeList = [],
|
|
nodeValue,
|
|
node,
|
|
div,
|
|
src,
|
|
nodeAttrList = [];
|
|
|
|
// find nodes that contain a string variable
|
|
tinymce.walk(editor.getBody(), function (n) {
|
|
if (n.nodeType == 1) {
|
|
src = n.getAttribute('src');
|
|
if (src) {
|
|
if (stringVariableRegex.test(src)) {
|
|
nodeAttrList.push(n);
|
|
}
|
|
}
|
|
}
|
|
|
|
// disabled
|
|
// if (n.nodeType == 3 && n.nodeValue && stringVariableRegex.test(n.nodeValue)) {
|
|
// nodeList.push(n);
|
|
// }
|
|
}, 'childNodes');
|
|
|
|
// loop over all nodes that contain a string variable
|
|
// disabled
|
|
// for (var i = 0; i < nodeList.length; i++) {
|
|
// nodeValue = nodeList[i].nodeValue.replace(stringVariableRegex, createHTMLVariable);
|
|
// div = editor.dom.create('div', null, nodeValue);
|
|
// while ((node = div.lastChild)) {
|
|
// editor.dom.insertAfter(node, nodeList[i]);
|
|
|
|
// if (isVariable(node)) {
|
|
// var next = node.nextSibling;
|
|
// editor.selection.setCursorLocation(next);
|
|
// }
|
|
// }
|
|
|
|
// editor.dom.remove(nodeList[i]);
|
|
// }
|
|
|
|
for (var i = 0; i < nodeAttrList.length; i++) {
|
|
var oldVal = nodeAttrList[i].getAttribute('src'),
|
|
newVal = oldVal.replace(stringVariableRegex, createSrcHTMLVariable);
|
|
|
|
nodeAttrList[i].setAttribute('src', newVal);
|
|
|
|
var img = editor.dom.create('img', {
|
|
src: newVal,
|
|
'data-image-variable': oldVal
|
|
}, null);
|
|
|
|
editor.dom.insertAfter(img, nodeAttrList[i]);
|
|
editor.dom.remove(nodeAttrList[i]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* convert HTML variables back into their original string format
|
|
* for example when a user opens source view
|
|
* @return {void}
|
|
*/
|
|
function htmlToString() {
|
|
var nodeList = [],
|
|
nodeValue,
|
|
node,
|
|
div,
|
|
nodeAttrList = [];
|
|
|
|
// find nodes that contain a HTML variable
|
|
tinymce.walk(editor.getBody(), function (n) {
|
|
if (n.nodeType == 1) {
|
|
var original = n.getAttribute('data-original-variable');
|
|
if (original !== null) {
|
|
nodeList.push(n);
|
|
}
|
|
|
|
var originalAttr = n.getAttribute('data-image-variable');
|
|
if (originalAttr !== null) {
|
|
nodeAttrList.push(n);
|
|
}
|
|
|
|
}
|
|
}, 'childNodes');
|
|
|
|
// loop over all nodes that contain a HTML variable
|
|
// for (var i = 0; i < nodeList.length; i++) {
|
|
// nodeValue = nodeList[i].getAttribute('data-original-variable');
|
|
// div = editor.dom.create('div', null, nodeValue);
|
|
// while ((node = div.lastChild)) {
|
|
// editor.dom.insertAfter(node, nodeList[i]);
|
|
// }
|
|
|
|
// // remove HTML variable node
|
|
// // because we now have an text representation of the variable
|
|
// editor.dom.remove(nodeList[i]);
|
|
// }
|
|
// loop over all nodes that contain a HTML variable
|
|
for (var i = 0; i < nodeAttrList.length; i++) {
|
|
var oldVal = nodeAttrList[i].getAttribute('data-image-variable'),
|
|
newImg = editor.dom.create('img', {
|
|
src: oldVal
|
|
}, null);
|
|
|
|
editor.dom.insertAfter(newImg, nodeAttrList[i]);
|
|
editor.dom.remove(nodeAttrList[i]);
|
|
}
|
|
|
|
}
|
|
|
|
function setCursor(selector) {
|
|
var ell = editor.dom.select(selector)[0];
|
|
if (ell) {
|
|
var next = ell.nextSibling;
|
|
editor.selection.setCursorLocation(next);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* handle formatting the content of the editor based on
|
|
* the current format. For example if a user switches to source view and back
|
|
* @param {object} e
|
|
* @return {void}
|
|
*/
|
|
function handleContentRerender(e) {
|
|
// store cursor location
|
|
return e.format === 'raw' ? stringToHTML() : htmlToString();
|
|
// restore cursor location
|
|
}
|
|
|
|
/**
|
|
* insert a variable into the editor at the current cursor location
|
|
* @param {string} value
|
|
* @return {void}
|
|
*/
|
|
function addVariable(value) {
|
|
var htmlVariable = createHTMLVariable(value);
|
|
editor.execCommand('mceInsertContent', false, htmlVariable);
|
|
}
|
|
|
|
function isVariable(element) {
|
|
if (typeof element.getAttribute === 'function' && element.hasAttribute('data-original-variable'))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Trigger special event when user clicks on a variable
|
|
* @return {void}
|
|
*/
|
|
function handleClick(e) {
|
|
var target = e.target;
|
|
|
|
if (!isVariable(target))
|
|
return null;
|
|
|
|
var value = target.getAttribute('data-original-variable');
|
|
editor.fire('variableClick', {
|
|
value: cleanVariable(value),
|
|
target: target
|
|
});
|
|
}
|
|
|
|
editor.on('nodechange', stringToHTML);
|
|
editor.on('keyup', stringToHTML);
|
|
editor.on('beforegetcontent', handleContentRerender);
|
|
editor.on('click', handleClick);
|
|
|
|
this.addVariable = addVariable;
|
|
|
|
});
|
|
}
|
|
});
|
|
|
|
|