You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
236 lines
7.9 KiB
JavaScript
236 lines
7.9 KiB
JavaScript
2 months ago
|
tinymce.PluginManager.add('mathjax', function(editor, url) {
|
||
|
|
||
|
// plugin configuration options
|
||
|
let mathjaxClassName = editor.settings.mathjax.className || "math-tex";
|
||
|
let mathjaxTempClassName = mathjaxClassName + '-original';
|
||
|
let mathjaxSymbols = editor.settings.mathjax.symbols || {start: '\\(', end: '\\)'};
|
||
|
let mathjaxUrl = editor.settings.mathjax.lib || null;
|
||
|
let mathjaxConfigUrl = (editor.settings.mathjax.configUrl || url + '/config.js') + '?class=' + mathjaxTempClassName;
|
||
|
let mathjaxScripts = [mathjaxConfigUrl];
|
||
|
if (mathjaxUrl) {
|
||
|
mathjaxScripts.push(mathjaxUrl);
|
||
|
}
|
||
|
|
||
|
// load mathjax and its config on editor init
|
||
|
editor.on('init', function () {
|
||
|
let scripts = editor.getDoc().getElementsByTagName('script');
|
||
|
for (let i = 0; i < mathjaxScripts.length; i++) {
|
||
|
// check if script have already loaded
|
||
|
let id = editor.dom.uniqueId();
|
||
|
let script = editor.dom.create('script', {id: id, type: 'text/javascript', src: mathjaxScripts[i]});
|
||
|
let found = false;
|
||
|
for (let j = 0; j < scripts.length; j++) {
|
||
|
if (scripts[j].src == script.src) {
|
||
|
found = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
// load script
|
||
|
if (!found) {
|
||
|
editor.getDoc().getElementsByTagName('head')[0].appendChild(script);
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// remove extra tags on get content
|
||
|
editor.on('GetContent', function (e) {
|
||
|
let div = editor.dom.create('div');
|
||
|
div.innerHTML = e.content;
|
||
|
let elements = div.querySelectorAll('.' + mathjaxClassName);
|
||
|
for (let i = 0; i < elements.length; i++) {
|
||
|
let children = elements[i].querySelectorAll('span');
|
||
|
for (let j = 0; j < children.length; j++) {
|
||
|
children[j].remove();
|
||
|
}
|
||
|
let latex = elements[i].getAttribute('data-latex');
|
||
|
elements[i].removeAttribute('contenteditable');
|
||
|
elements[i].removeAttribute('style');
|
||
|
elements[i].removeAttribute('data-latex');
|
||
|
elements[i].innerHTML = latex;
|
||
|
}
|
||
|
e.content = div.innerHTML;
|
||
|
});
|
||
|
|
||
|
let checkElement = function(element) {
|
||
|
if (element.childNodes.length != 2) {
|
||
|
element.setAttribute('contenteditable', false);
|
||
|
element.style.cursor = 'pointer';
|
||
|
let latex = element.getAttribute('data-latex') || element.innerHTML;
|
||
|
element.setAttribute('data-latex', latex);
|
||
|
element.innerHTML = '';
|
||
|
|
||
|
let math = editor.dom.create('span');
|
||
|
math.innerHTML = latex;
|
||
|
math.classList.add(mathjaxTempClassName);
|
||
|
element.appendChild(math);
|
||
|
|
||
|
let dummy = editor.dom.create('span');
|
||
|
dummy.classList.add('dummy');
|
||
|
dummy.innerHTML = 'dummy';
|
||
|
dummy.setAttribute('hidden', 'hidden');
|
||
|
element.appendChild(dummy);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// add dummy tag on set content
|
||
|
editor.on('BeforeSetContent', function (e) {
|
||
|
let div = editor.dom.create('div');
|
||
|
div.innerHTML = e.content;
|
||
|
let elements = div.querySelectorAll('.' + mathjaxClassName);
|
||
|
for (let i = 0 ; i < elements.length; i++) {
|
||
|
checkElement(elements[i]);
|
||
|
}
|
||
|
e.content = div.innerHTML;
|
||
|
});
|
||
|
|
||
|
// refresh mathjax on set content
|
||
|
editor.on('SetContent', function(e) {
|
||
|
if (editor.getDoc().defaultView.MathJax) {
|
||
|
editor.getDoc().defaultView.MathJax.startup.getComponents();
|
||
|
editor.getDoc().defaultView.MathJax.typeset();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// refresh mathjax on any content change
|
||
|
editor.on('Change', function(data) {
|
||
|
elements = editor.dom.getRoot().querySelectorAll('.' + mathjaxClassName);
|
||
|
if (elements.length) {
|
||
|
for (let i = 0 ; i < elements.length; i++) {
|
||
|
checkElement(elements[i]);
|
||
|
}
|
||
|
if (editor.getDoc().defaultView.MathJax) {
|
||
|
editor.getDoc().defaultView.MathJax.startup.getComponents();
|
||
|
editor.getDoc().defaultView.MathJax.typeset();
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// add button to tinimce
|
||
|
editor.ui.registry.addToggleButton('mathjax', {
|
||
|
text: 'Σ',
|
||
|
tooltip: 'Mathjax',
|
||
|
onAction: function() {
|
||
|
let selected = editor.selection.getNode();
|
||
|
let target = undefined;
|
||
|
if (selected.classList.contains(mathjaxClassName)) {
|
||
|
target = selected;
|
||
|
}
|
||
|
openMathjaxEditor(target);
|
||
|
},
|
||
|
onSetup: function (buttonApi) {
|
||
|
return editor.selection.selectorChangedWithUnbind('.' + mathjaxClassName, buttonApi.setActive).unbind;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// handle click on existing
|
||
|
editor.on("click", function (e) {
|
||
|
let closest = e.target.closest('.' + mathjaxClassName);
|
||
|
if (closest) {
|
||
|
openMathjaxEditor(closest);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// open window with editor
|
||
|
let openMathjaxEditor = function(target) {
|
||
|
|
||
|
let mathjaxId = editor.id + '_' + editor.dom.uniqueId();
|
||
|
|
||
|
let latex = '';
|
||
|
if (target) {
|
||
|
latex_attribute = target.getAttribute('data-latex');
|
||
|
if (latex_attribute.length >= (mathjaxSymbols.start + mathjaxSymbols.end).length) {
|
||
|
latex = latex_attribute.substr(mathjaxSymbols.start.length, latex_attribute.length - (mathjaxSymbols.start + mathjaxSymbols.end).length);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// show new window
|
||
|
editor.windowManager.open({
|
||
|
title: 'Mathjax',
|
||
|
width: 600,
|
||
|
height: 300,
|
||
|
body: {
|
||
|
type: 'panel',
|
||
|
items: [{
|
||
|
type: 'textarea',
|
||
|
name: 'title',
|
||
|
label: 'LaTex'
|
||
|
}, {
|
||
|
type: 'htmlpanel',
|
||
|
html: '<div style="text-align:right"><a href="https://wikibooks.org/wiki/LaTeX/Mathematics" target="_blank" style="font-size:small">LaTex</a></div>'
|
||
|
}, {
|
||
|
type: 'htmlpanel',
|
||
|
html: '<iframe id="' + mathjaxId + '" style="width: 100%; min-height: 50px;"></iframe>'
|
||
|
}]
|
||
|
},
|
||
|
buttons: [{type: 'submit', text: 'OK'}],
|
||
|
onSubmit: function onsubmit(api) {
|
||
|
let value = api.getData().title.trim();
|
||
|
if (target) {
|
||
|
target.innerHTML = '';
|
||
|
target.setAttribute('data-latex', getMathText(value));
|
||
|
checkElement(target);
|
||
|
} else {
|
||
|
let newElement = editor.getDoc().createElement('span');
|
||
|
newElement.innerHTML = getMathText(value);
|
||
|
newElement.classList.add(mathjaxClassName);
|
||
|
checkElement(newElement);
|
||
|
editor.insertContent(newElement.outerHTML);
|
||
|
}
|
||
|
editor.getDoc().defaultView.MathJax.startup.getComponents();
|
||
|
editor.getDoc().defaultView.MathJax.typeset();
|
||
|
api.close();
|
||
|
},
|
||
|
onChange: function(api) {
|
||
|
var value = api.getData().title.trim();
|
||
|
if (value != latex) {
|
||
|
refreshDialogMathjax(value, document.getElementById(mathjaxId));
|
||
|
latex = value;
|
||
|
}
|
||
|
},
|
||
|
initialData: {title: latex}
|
||
|
});
|
||
|
|
||
|
// add scripts to iframe
|
||
|
let iframe = document.getElementById(mathjaxId);
|
||
|
let iframeWindow = iframe.contentWindow || iframe.contentDocument.document || iframe.contentDocument;
|
||
|
let iframeDocument = iframeWindow.document;
|
||
|
let iframeHead = iframeDocument.getElementsByTagName('head')[0];
|
||
|
let iframeBody = iframeDocument.getElementsByTagName('body')[0];
|
||
|
|
||
|
// get latex for mathjax from simple text
|
||
|
let getMathText = function (value, symbols) {
|
||
|
if (!symbols) {
|
||
|
symbols = mathjaxSymbols;
|
||
|
}
|
||
|
return symbols.start + ' ' + value + ' ' + symbols.end;
|
||
|
};
|
||
|
|
||
|
// refresh latex in mathjax iframe
|
||
|
let refreshDialogMathjax = function(latex) {
|
||
|
let MathJax = iframeWindow.MathJax;
|
||
|
let div = iframeBody.querySelector('div');
|
||
|
if (!div) {
|
||
|
div = iframeDocument.createElement('div');
|
||
|
div.classList.add(mathjaxTempClassName);
|
||
|
iframeBody.appendChild(div);
|
||
|
}
|
||
|
div.innerHTML = getMathText(latex, {start: '$$', end: '$$'});
|
||
|
if (MathJax && MathJax.startup) {
|
||
|
MathJax.startup.getComponents();
|
||
|
MathJax.typeset();
|
||
|
}
|
||
|
};
|
||
|
refreshDialogMathjax(latex);
|
||
|
|
||
|
// add scripts for dialog iframe
|
||
|
for (let i = 0; i < mathjaxScripts.length; i++) {
|
||
|
let node = iframeWindow.document.createElement('script');
|
||
|
node.src = mathjaxScripts[i];
|
||
|
node.type = 'text/javascript';
|
||
|
node.async = false;
|
||
|
node.charset = 'utf-8';
|
||
|
iframeHead.appendChild(node);
|
||
|
}
|
||
|
|
||
|
};
|
||
|
});
|