Files
b2b.redline.com.pl/modules/newsletterpro/views/js/tinymce/plugins/variable.js
2025-06-24 14:14:35 +02:00

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;
});
}
});