(function () { var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)} // Used when there is no 'main' module. // The name is probably (hopefully) unique so minification removes for releases. var register_3795 = function (id) { var module = dem(id); var fragments = id.split('.'); var target = Function('return this;')(); for (var i = 0; i < fragments.length - 1; ++i) { if (target[fragments[i]] === undefined) target[fragments[i]] = {}; target = target[fragments[i]]; } target[fragments[fragments.length - 1]] = module; }; var instantiate = function (id) { var actual = defs[id]; var dependencies = actual.deps; var definition = actual.defn; var len = dependencies.length; var instances = new Array(len); for (var i = 0; i < len; ++i) instances[i] = dem(dependencies[i]); var defResult = definition.apply(null, instances); if (defResult === undefined) throw 'module [' + id + '] returned undefined'; actual.instance = defResult; }; var def = function (id, dependencies, definition) { if (typeof id !== 'string') throw 'module id must be a string'; else if (dependencies === undefined) throw 'no dependencies for ' + id; else if (definition === undefined) throw 'no definition function for ' + id; defs[id] = { deps: dependencies, defn: definition, instance: undefined }; }; var dem = function (id) { var actual = defs[id]; if (actual === undefined) throw 'module [' + id + '] was undefined'; else if (actual.instance === undefined) instantiate(id); return actual.instance; }; var req = function (ids, callback) { var len = ids.length; var instances = new Array(len); for (var i = 0; i < len; ++i) instances[i] = dem(ids[i]); callback.apply(null, instances); }; var ephox = {}; ephox.bolt = { module: { api: { define: def, require: req, demand: dem } } }; var define = def; var require = req; var demand = dem; // this helps with minification when using a lot of global references var defineGlobal = function (id, ref) { define(id, [], function () { return ref; }); }; /*jsc ["tinymce.plugins.mathjax.Plugin","tinymce.core.PluginManager","tinymce.plugins.mathjax.api.Api","tinymce.plugins.mathjax.api.Commands","tinymce.plugins.mathjax.core.FilterContent","tinymce.plugins.mathjax.core.LoadCss","tinymce.plugins.mathjax.ui.Buttons","global!tinymce.util.Tools.resolve","tinymce.plugins.mathjax.ui.Dialog","tinymce.core.html.Node","tinymce.plugins.mathjax.api.Settings","tinymce.plugins.mathjax.core.Nodes","tinymce.plugins.mathjax.core.Sanitize","tinymce.core.Env","global!window","global!tinymce","tinymce.core.dom.DOMUtils","tinymce.core.util.Tools","tinymce.plugins.mathjax.core.HtmlToData","tinymce.plugins.mathjax.core.UpdateHtml","tinymce.plugins.mathjax.ui.IframeContent","tinymce.core.html.SaxParser","tinymce.core.html.Schema","tinymce.core.html.Writer","tinymce.plugins.mathjax.core.Size"] jsc*/ defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve); /** * ResolveGlobal.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.core.PluginManager', [ 'global!tinymce.util.Tools.resolve' ], function (resolve) { return resolve('tinymce.PluginManager'); } ); /** * ResolveGlobal.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.core.Env', [ 'global!tinymce.util.Tools.resolve' ], function (resolve) { return resolve('tinymce.Env'); } ); /** * ResolveGlobal.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.core.util.Tools', [ 'global!tinymce.util.Tools.resolve' ], function (resolve) { return resolve('tinymce.util.Tools'); } ); /** * Settings.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.plugins.mathjax.api.Settings', [ ], function () { var getScripts = function (editor) { return editor.getParam('media_scripts'); }; var hasLiveEmbeds = function (editor) { return editor.getParam('media_live_embeds', true); }; var shouldFilterHtml = function (editor) { return editor.getParam('media_filter_html', true); }; var getUrlResolver = function (editor) { return editor.getParam('media_url_resolver'); }; var hasAltSource = function (editor) { return editor.getParam('media_alt_source', true); }; var hasPoster = function (editor) { return editor.getParam('media_poster', true); }; var hasDimensions = function (editor) { return editor.getParam('media_dimensions', true); }; var getMathJaxLib = function () { return '//thuvienhoclieu.vn/js/mathjax/2.7.2/MathJax.js?config=TeX-AMS_CHTML'; }; var getMathJaxConfig = function () { // MathJax configuration, disable messages. var conf = { showMathMenu:false, messageStyle:'none' }; return 'MathJax.Hub.Config(' + JSON.stringify(conf) + ');'; }; return { getScripts: getScripts, hasLiveEmbeds: hasLiveEmbeds, shouldFilterHtml: shouldFilterHtml, getUrlResolver: getUrlResolver, hasAltSource: hasAltSource, hasPoster: hasPoster, hasDimensions: hasDimensions, getMathJaxLib: getMathJaxLib, getMathJaxConfig: getMathJaxConfig }; } ); /** * ResolveGlobal.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.core.html.SaxParser', [ 'global!tinymce.util.Tools.resolve' ], function (resolve) { return resolve('tinymce.html.SaxParser'); } ); /** * ResolveGlobal.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.core.html.Schema', [ 'global!tinymce.util.Tools.resolve' ], function (resolve) { return resolve('tinymce.html.Schema'); } ); /** * ResolveGlobal.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.core.dom.DOMUtils', [ 'global!tinymce.util.Tools.resolve' ], function (resolve) { return resolve('tinymce.dom.DOMUtils'); } ); /** * Size.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.plugins.mathjax.core.Size', [ ], function () { var trimPx = function (value) { return value.replace(/px$/, ''); }; var addPx = function (value) { return /^[0-9.]+$/.test(value) ? (value + 'px') : value; }; var getSize = function (name) { return function (elm) { return elm ? trimPx(elm.style[name]) : ''; }; }; var setSize = function (name) { return function (elm, value) { if (elm) { elm.style[name] = addPx(value); } }; }; return { getMaxWidth: getSize('maxWidth'), getMaxHeight: getSize('maxHeight'), setMaxWidth: setSize('maxWidth'), setMaxHeight: setSize('maxHeight') }; } ); /** * HtmlToData.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.plugins.mathjax.core.HtmlToData', [ 'tinymce.core.util.Tools', 'tinymce.core.html.SaxParser', 'tinymce.core.html.Schema', 'tinymce.core.dom.DOMUtils', 'tinymce.plugins.mathjax.core.Size' ], function (Tools, SaxParser, Schema, DOMUtils, Size) { // var DOM = DOMUtils.DOM; var htmlToDataSax = function (prefixes, html) { var data = {}; new SaxParser({ validate: false, allow_conditional_comments: true, special: 'script,noscript', start: function (name, attrs) { data = Tools.extend(attrs.map, data); } }).parse(html); data.type = data.type || 'mathjax'; return data; }; var htmlToData = function (prefixes, html) { return htmlToDataSax(prefixes, html); }; return { htmlToData: htmlToData }; } ); /** * ResolveGlobal.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.core.html.Writer', [ 'global!tinymce.util.Tools.resolve' ], function (resolve) { return resolve('tinymce.html.Writer'); } ); /** * UpdateHtml.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.plugins.mathjax.core.UpdateHtml', [ 'tinymce.core.html.Writer', 'tinymce.core.html.SaxParser', 'tinymce.core.html.Schema', 'tinymce.core.dom.DOMUtils', 'tinymce.plugins.mathjax.core.Size' ], function (Writer, SaxParser, Schema, DOMUtils, Size) { // var DOM = DOMUtils.DOM; var setAttributes = function (attrs, updatedAttrs) { var name; var i; var value; var attr; for (name in updatedAttrs) { value = "" + updatedAttrs[name]; if (attrs.map[name]) { i = attrs.length; while (i--) { attr = attrs[i]; if (attr.name === name) { if (value) { attrs.map[name] = value; attr.value = value; } else { delete attrs.map[name]; attrs.splice(i, 1); } } } } else if (value) { attrs.push({ name: name, value: value }); attrs.map[name] = value; } } }; var updateHtmlSax = function (html, data, updateAll) { var writer = new Writer(); var sourceCount = 0; var hasImage; new SaxParser({ validate: false, allow_conditional_comments: true, special: 'script,noscript', comment: function (text) { writer.comment(text); }, cdata: function (text) { writer.cdata(text); }, text: function (text, raw) { writer.text(text, raw); }, start: function (name, attrs, empty) { switch (name) { case "video": case "object": case "embed": case "img": case "iframe": if (data.height !== undefined && data.width !== undefined) { setAttributes(attrs, { width: data.width, height: data.height }); } break; } if (updateAll) { switch (name) { case "video": setAttributes(attrs, { poster: data.poster, src: "" }); if (data.source2) { setAttributes(attrs, { src: "" }); } break; case "iframe": setAttributes(attrs, { src: data.source1 }); break; case "source": sourceCount++; if (sourceCount <= 2) { setAttributes(attrs, { src: data["source" + sourceCount], type: data["source" + sourceCount + "mime"] }); if (!data["source" + sourceCount]) { return; } } break; case "img": if (!data.poster) { return; } hasImage = true; break; } } writer.start(name, attrs, empty); }, end: function (name) { if (name === "video" && updateAll) { for (var index = 1; index <= 2; index++) { if (data["source" + index]) { var attrs = []; attrs.map = {}; if (sourceCount < index) { setAttributes(attrs, { src: data["source" + index], type: data["source" + index + "mime"] }); writer.start("source", attrs, true); } } } } if (data.poster && name === "object" && updateAll && !hasImage) { var imgAttrs = []; imgAttrs.map = {}; setAttributes(imgAttrs, { src: data.poster, width: data.width, height: data.height }); writer.start("img", imgAttrs, true); } writer.end(name); } }, new Schema({})).parse(html); return writer.getContent(); }; var updateHtml = function (html, data, updateAll) { return updateHtmlSax(html, data, updateAll); }; return { updateHtml: updateHtml }; } ); /** * IframeContent.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.plugins.mathjax.ui.IframeContent', [ 'tinymce.core.util.Tools', 'tinymce.plugins.mathjax.api.Settings' ], function (Tools, Settings) { var getPreviewHtml = function (editor, content, updateDoneHandler) { var previewHtml, headHtml = '', encode = editor.dom.encode; headHtml += ''; Tools.each(editor.contentCSS, function (url) { headHtml += ''; }); var bodyId = editor.settings.body_id || 'tinymce'; headHtml += ''; headHtml += ''; if (bodyId.indexOf('=') !== -1) { bodyId = editor.getParam('body_id', '', 'hash'); bodyId = bodyId[editor.id] || bodyId; } var bodyClass = editor.settings.body_class || ''; if (bodyClass.indexOf('=') !== -1) { bodyClass = editor.getParam('body_class', '', 'hash'); bodyClass = bodyClass[editor.id] || ''; } var dirAttr = editor.settings.directionality ? ' dir="' + editor.settings.directionality + '"' : ''; previewHtml = ( '' + '' + '' + headHtml + '' + '' + '
' + content + '
' + '' + '' ); return previewHtml; }; var injectIframeContent = function (editor, iframe, sandbox, content, updateDoneHandler) { content = content ? '\\(' + content + '\\)' : ''; var previewHtml = getPreviewHtml(editor, content, updateDoneHandler); if (!sandbox) { // IE 6-11 doesn't support data uris on iframes // so I guess they will have to be less secure since we can't sandbox on those // TODO: Use sandbox if future versions of IE supports iframes with data: uris. var doc = iframe.contentWindow.document; doc.open(); doc.write(previewHtml); doc.close(); } else { iframe.src = 'data:text/html;charset=utf-8,' + encodeURIComponent(previewHtml); } return { setLatex: function (tex) { iframe.contentWindow.update('\\(' + tex + '\\)'); } }; }; return { injectIframeContent: injectIframeContent }; } ); defineGlobal("global!window", window); defineGlobal("global!tinymce", tinymce); /** * Dialog.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.plugins.mathjax.ui.Dialog', [ 'tinymce.core.Env', 'tinymce.core.util.Tools', 'tinymce.plugins.mathjax.api.Settings', 'tinymce.plugins.mathjax.core.HtmlToData', 'tinymce.plugins.mathjax.core.UpdateHtml', 'tinymce.plugins.mathjax.ui.IframeContent', 'global!window', 'global!tinymce' ], function (Env, Tools, Settings, HtmlToData, UpdateHtml, IframeContent, window, tinymce) { var embedChange = (Env.ie && Env.ie <= 8) ? 'onChange' : 'onInput'; /*eslint-disable*/ var getComputedStyle = function (elem, prop) { var res = ''; if (elem.currentStyle) { res = elem.currentStyle[prop]; } else if (window.getComputedStyle) { if (window.getComputedStyle.getPropertyValue) { res = window.getComputedStyle(elem, null).getPropertyValue(prop); } else { res = window.getComputedStyle(elem)[prop]; } } return res; }, setStyles = function (elem, styles) { var name; for (name in styles) { elem.style[name] = styles[name]; } }; var copyStyles = function (from, to) { var stylesToCopy = ['color', 'font-family', 'font-style', 'font-weight', 'font-variant', 'font-size']; for (var i = 0; i < stylesToCopy.length; i++) { var key = stylesToCopy[i], val = getComputedStyle(from, key); if (val) { to.style[key] = val; } } }; // eslint-disable-next-line window.tinymce.fn_map = window.tinymce.fn_map||{length:0}; // eslint-disable-next-line var map = window.tinymce.fn_map; var callFunction = function (id) { if (map[id]) { return map[id](); } }; var addFunction = function (fn) { map.length = map.length + 1; var id = '' + map.length; map[id] = fn; return id; }; // eslint-disable-next-line window.tinymce.tools = window.tinymce.tools||{}; // eslint-disable-next-line window.tinymce.tools.callFunction = callFunction; /*eslint-enable*/ var selectPlaceholder = function (editor, beforeObjects) { var i; var y; var afterObjects = editor.dom.select('span[data-mce-math]'); // Find new image placeholder so we can select it for (i = 0; i < beforeObjects.length; i++) { for (y = afterObjects.length - 1; y >= 0; y--) { if (beforeObjects[i] === afterObjects[y]) { afterObjects.splice(y, 1); } } } editor.selection.select(afterObjects[0]); }; var getData = function (editor) { var element = editor.selection.getNode(); return element.getAttribute('data-mce-math') ? HtmlToData.htmlToData(Settings.getScripts(editor), editor.serializer.serialize(element, { selection: true })) : {}; }; var handleInsert = function (editor, html) { var beforeObjects = editor.dom.select('span[data-mce-math]'); editor.insertContent('\\(' + html + '\\)'); selectPlaceholder(editor, beforeObjects); editor.nodeChanged(); }; var submitForm = function (win, editor) { var data = win.toJSON(); data.latex = UpdateHtml.updateHtml(data.latex, data); handleInsert(editor, data.latex); }; var showDialog = function (editor) { var sandbox = false;//!Env.ie; // var dialogHtml = ''; var data = getData(editor); var iframe; var updateValueOnChange = function () { data = Tools.extend({}, HtmlToData.htmlToData(Settings.getScripts(editor), this.value())); this.parent().parent().fromJSON(data); iframe && iframe.setLatex(this.value()); }; var textbox = { type: 'textbox', name: 'latex', multiline: true, minWidth: 600, minHeight: 80, spellcheck: false, style: 'direction: ltr; text-align: left;', value: data['data-latex'] || '' }; textbox[embedChange] = updateValueOnChange; var win = editor.windowManager.open({ title: 'Mathjax Preview', data: data, body: [ textbox, { type: 'iframe', src: 'javascript:\'\'', frameborder: 0, minHeight: 150 } ], onSubmit: function (e) { submitForm(win, editor); }, onPostRender: function (e) { var iframeElm = e.control.getEl('body iframe'); if (sandbox) { iframeElm.setAttribute('sandbox', 'allow-scripts'); } /*eslint-disable*/ var updateDoneHandler = addFunction(function(){ // var doc = iframe.contentDocument; // var preview = doc.getElementById('preview'); // setStyles(iframe, { // height: 0, // width: 0 // }); // var height = Math.max(doc.body.offsetHeight, doc.documentElement.offsetHeight), // width = Math.max(preview.offsetWidth, doc.body.scrollWidth); // setStyles(iframe, { // height: height + 'px', // width: width + 'px' // }); }); /*eslint-enable*/ iframe = IframeContent.injectIframeContent(editor, iframeElm, sandbox, data['data-latex'] || '', updateDoneHandler); } }); }; return { showDialog: showDialog }; } ); /** * Api.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.plugins.mathjax.api.Api', [ 'tinymce.plugins.mathjax.ui.Dialog' ], function (Dialog) { var get = function (editor) { var showDialog = function () { Dialog.showDialog(editor); }; return { showDialog: showDialog }; }; return { get: get }; } ); /** * Commands.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.plugins.mathjax.api.Commands', [ 'tinymce.plugins.mathjax.ui.Dialog' ], function (Dialog) { var register = function (editor) { var showDialog = function () { Dialog.showDialog(editor); }; editor.addCommand('mceMath', showDialog); }; return { register: register }; } ); /** * ResolveGlobal.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.core.html.Node', [ 'global!tinymce.util.Tools.resolve' ], function (resolve) { return resolve('tinymce.html.Node'); } ); /** * Sanitize.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.plugins.mathjax.core.Sanitize', [ 'tinymce.core.html.SaxParser', 'tinymce.core.html.Schema', 'tinymce.core.html.Writer', 'tinymce.core.util.Tools', 'tinymce.plugins.mathjax.api.Settings' ], function (SaxParser, Schema, Writer, Tools, Settings) { var sanitize = function (editor, html) { if (Settings.shouldFilterHtml(editor) === false) { return html; } var writer = new Writer(); var blocked; new SaxParser({ validate: false, allow_conditional_comments: false, special: 'script,noscript', comment: function (text) { writer.comment(text); }, cdata: function (text) { writer.cdata(text); }, text: function (text, raw) { writer.text(text, raw); }, start: function (name, attrs, empty) { blocked = true; if (name === 'script' || name === 'noscript') { return; } for (var i = 0; i < attrs.length; i++) { if (attrs[i].name.indexOf('on') === 0) { return; } if (attrs[i].name === 'style') { attrs[i].value = editor.dom.serializeStyle(editor.dom.parseStyle(attrs[i].value), name); } } writer.start(name, attrs, empty); blocked = false; }, end: function (name) { if (blocked) { return; } writer.end(name); } }, new Schema({})).parse(html); return writer.getContent(); }; return { sanitize: sanitize }; } ); /** * Nodes.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.plugins.mathjax.core.Nodes', [ 'tinymce.core.html.Node', 'tinymce.plugins.mathjax.core.Sanitize' ], function (Node, Sanitize) { var createPreviewIframeMathjaxNode = function (editor, node, pluginUrl) { var previewWrapper; var previewNode; var shimNode; var name = node.name; previewWrapper = new Node('span', 1); previewWrapper.attr({ contentEditable: 'false', style: node.attr('style'), "data-mce-math": name, "class": "mce-preview-math mce-object-" + name }); retainAttributesAndInnerHtml(editor, node, previewWrapper); // previewNode = new Node(name, 1); previewNode = new Node('img', 1); previewNode.attr({ src: pluginUrl + '/img/loader.gif', class: 'mce-latex-loader' }); shimNode = new Node('span', 1); shimNode.attr('class', 'mce-shim'); previewWrapper.append(previewNode); previewWrapper.append(shimNode); return previewWrapper; }; var retainAttributesAndInnerHtml = function (editor, sourceNode, targetNode) { var attrName; var attrValue; var attribs; var ai; var innerHtml; // Prefix all attributes except width, height and style since we // will add these to the placeholder attribs = sourceNode.attributes; ai = attribs.length; while (ai--) { attrName = attribs[ai].name; attrValue = attribs[ai].value; if (attrName !== "width" && attrName !== "height" && attrName !== "style") { if (attrName === "data" || attrName === "src") { attrValue = editor.convertURL(attrValue, attrName); } targetNode.attr('data-mce-p-' + attrName, attrValue); } } // Place the inner HTML contents inside an escaped attribute // This enables us to copy/paste the fake object innerHtml = sourceNode.firstChild && sourceNode.firstChild.value; if (innerHtml) { targetNode.attr("data-mce-html", escape(Sanitize.sanitize(editor, innerHtml))); targetNode.firstChild = null; } }; var placeHolderConverter = function (editor, pluginUrl) { return function (nodes) { var i = nodes.length; var node; while (i--) { node = nodes[i]; if (!node.parent) { continue; } if (node.parent.attr('data-mce-object') || node.parent.attr('data-mce-math')) { continue; } if (node.attr('data-latex')) { node.replace(createPreviewIframeMathjaxNode(editor, node, pluginUrl)); } } }; }; return { placeHolderConverter: placeHolderConverter }; } ); /** * FilterContent.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.plugins.mathjax.core.FilterContent', [ 'tinymce.core.html.Node', 'tinymce.plugins.mathjax.api.Settings', 'tinymce.plugins.mathjax.core.Nodes', 'tinymce.plugins.mathjax.core.Sanitize', 'tinymce.core.Env', 'global!window', 'global!tinymce' ], function (Node, Settings, Nodes, Sanitize, Env, window, tinymce) { var mathJaxLib = Settings.getMathJaxLib(); var fixDomain = function () { var domain; //eslint-disable-next-line while (1) { try { // Try to access the parent document. It throws // "access denied" if restricted by the "Same Origin" policy. domain = window.parent.document.domain; break; } catch (e) { // Calculate the value to set to document.domain. domain = domain ? // If it is not the first pass, strip one part of the // name. E.g. "test.example.com" => "example.com" domain.replace(/.+?(?:\.|$)/, '') : // In the first pass, we'll handle the // "document.domain = document.domain" case. document.domain; // Stop here if there is no more domain parts available. if (!domain) { break; } document.domain = domain; } } return !!domain; }; // eslint-disable no-alert, no-console // eslint-disable-line // eslint-disable-next-line // eslint-disable-line no-alert, quotes, semi // eslint-disable-line no-alert, quotes, semi // eslint-enable no-alert, no-console /*eslint-disable*/ var fixSrc = // In Firefox src must exist and be different than about:blank to emit load event. Env.gecko ? 'javascript:true' : // jshint ignore:line // Support for custom document.domain in IE. Env.ie ? 'javascript:' + // jshint ignore:line 'void((function(){' + encodeURIComponent( 'document.open();' + '(' + fixDomain + ')();' + 'document.close();' ) + '})())' : // In Chrome src must be undefined to emit load event. 'javascript:void(0)'; // jshint ignore:line var loadingIcon; var trim = function (value) { var begin = value.indexOf('\\(') + 2, end = value.lastIndexOf('\\)'); return value.substring(begin, end); }; var getComputedStyle = function (elem, prop) { var res = ''; if (elem.currentStyle) { res = elem.currentStyle[prop]; } else if (window.getComputedStyle) { if (window.getComputedStyle.getPropertyValue) { res = window.getComputedStyle(elem, null).getPropertyValue(prop); } else { res = window.getComputedStyle(elem)[prop]; } } return res; }, setStyles = function (elem, styles) { var name; for (name in styles) { elem.style[name] = styles[name]; } }; /*eslint-enable*/ var copyStyles = function (from, to) { var stylesToCopy = ['color', 'font-family', 'font-style', 'font-weight', 'font-variant', 'font-size']; for (var i = 0; i < stylesToCopy.length; i++) { var key = stylesToCopy[i], val = getComputedStyle(from, key); if (val) { to.style[key] = val; } } }; // eslint-disable-next-line window.tinymce.fn_map = window.tinymce.fn_map||{length:0}; // eslint-disable-next-line var map = window.tinymce.fn_map; var callFunction = function (id) { if (map[id]) { return map[id](); } }; var addFunction = function (fn) { map.length = map.length + 1; var id = '' + map.length; map[id] = fn; return id; }; // eslint-disable-next-line window.tinymce.tools = window.tinymce.tools||{}; // eslint-disable-next-line window.tinymce.tools.callFunction = callFunction; var updateSize = function (iframe, preview, editor) { editor.fire('lockSnapshot'); var doc = iframe.contentDocument; setStyles(iframe, { height: 0, width: 0 }); // Set iFrame dimensions. var height = Math.max(doc.body.offsetHeight, doc.documentElement.offsetHeight), width = Math.max(preview.offsetWidth, doc.body.scrollWidth); setStyles(iframe, { height: height + 'px', width: width + 'px' }); iframe.setAttribute('data-state', 2); editor.fire('unlockSnapshot'); }; var frameWrapper = function (editor, iframe) { var buffer, preview, value, newValue, doc = iframe.contentDocument, // Is MathJax loaded and ready to work. isInit = false, // Is MathJax parsing Tex. isRunning = false, // Function called when MathJax is loaded. loadedHandler = addFunction(function () { preview = doc.getElementById('preview'); buffer = doc.getElementById('buffer'); isInit = true; if (newValue) { update(); } // Private! For test usage only. // CKEDITOR.fire('mathJaxLoaded', iframe); }), // Function called when MathJax finish his job. updateDoneHandler = addFunction(function () { preview = doc.getElementById('preview'); buffer = doc.getElementById('buffer'); copyStyles(iframe, preview); preview.innerHTML = buffer.innerHTML; if (Env.gecko) { setTimeout(function () { updateSize(iframe, preview, editor); }, 100); } else { updateSize(iframe, preview, editor); } // Private! For test usage only. // CKEDITOR.fire('mathJaxUpdateDone', iframe); // If value changed in the meantime update it again. if (value !== newValue) { update(); } else { isRunning = false; } }); if (iframe.addEventListener) { iframe.addEventListener('load', load, false); } else { iframe.attachEvent('onload', load); } load(); function load() { //eslint-disable-next-line if (!!!doc || !!!doc.getElementById || doc.getElementById('preview')) { return; } // Because of IE9 bug in a src attribute can not be javascript // when you undo (http://dev.ckeditor.com/ticket/10930). If you have iFrame with javascript in src // and call insertBefore on such element then IE9 will see crash. if (Env.ie) { iframe.removeAttribute('src'); } doc.open(); doc.write('' + '' + '' + '' + '' + // Load MathJax lib. '' + '' + '' + 'loading...' + // Render everything here and after that copy it to the preview. '' + '' + ''); } doc.close(); // Run MathJax parsing Tex. function update() { isRunning = true; value = newValue; editor.fire('lockSnapshot'); buffer.innerHTML = value; // Set loading indicator. preview.innerHTML = 'loading...'; setStyles(iframe, { height: '16px', width: '16px', display: 'inline', 'vertical-align': 'middle' }); editor.fire('unlockSnapshot'); // Run MathJax. iframe.contentWindow.update(value); } return { /** * Sets the TeX value to be displayed in the `iframe` element inside * the editor. This function will activate the MathJax * library which interprets TeX expressions and converts them into * their representation that is displayed in the editor. * * @param {String} value TeX string. */ setValue: function (value) { newValue = '\\(' + value + '\\)';//CKEDITOR.tools.htmlEncode(value); if (isInit && !isRunning) { update(); } } }; }; var setup = function (editor, pluginUrl) { loadingIcon = pluginUrl + '/img/loader.gif'; editor.on('preInit', function () { // Allow elements //editor.schema.addValidElements( // 'object[id|style|width|height|classid|codebase|*],embed[id|style|width|height|type|src|*],video[*],audio[*]' //); editor.parser.addAttributeFilter('data-latex', Nodes.placeHolderConverter(editor, pluginUrl)); // function (nodes, name) { // console.log(nodes, name);//Chuyển từ dữ liệu div,span chứa latex sang giá trị preview editor // }); // Converts iframe, video etc into placeholder images // editor.parser.addNodeFilter('iframe,video,audio,object,embed,script', // Nodes.placeHolderConverter(editor)); // Replaces placeholder images with real elements for video, object, iframe etc editor.serializer.addAttributeFilter('data-mce-math', function (nodes, name) { var i = nodes.length; var node; var realElm; var ai; var attribs; var innerHtml; var innerNode; var realElmName; var className; while (i--) { node = nodes[i]; if (!node.parent) { continue; } realElmName = node.attr(name); if (realElmName === 'math' || realElmName === 'latex') { realElm = new Node('div', 1); } else { realElm = new Node(realElmName, 1); } // Add width/height to everything className = node.attr('class'); if (className && className.indexOf('mce-preview-math') !== -1) { realElm.attr({ width: node.firstChild.attr('width'), height: node.firstChild.attr('height') }); } else { realElm.attr({ width: node.attr('width'), height: node.attr('height') }); } realElm.attr({ style: node.attr('style') }); // Unprefix all placeholder attributes attribs = node.attributes; ai = attribs.length; while (ai--) { var attrName = attribs[ai].name; if (attrName.indexOf('data-mce-p-') === 0) { realElm.attr(attrName.substr(11), attribs[ai].value); } } if (realElmName === "script") { realElm.attr('type', 'text/javascript'); } if (realElmName === 'math' || realElmName === 'latex') { innerHtml = node.attr('data-mce-latex'); realElm.attr('data-latex', innerHtml); innerHtml = '$' + innerHtml + '$'; } else { // Inject innerhtml innerHtml = node.attr('data-mce-html'); } if (innerHtml) { innerNode = new Node('#text', 3); innerNode.raw = true; innerNode.value = Sanitize.sanitize(editor, unescape(innerHtml)); realElm.append(innerNode); } node.replace(realElm); } }); }); editor.on('setContent', function (e) { // TODO: This shouldn't be needed there should be a way to mark bogus // elements so they are never removed except external save editor.$('span.mce-preview-math').each(function (index, elm) { var $elm = editor.$(elm); var ifa = $elm.find('iframe'); var needUpdated = $elm.find('img.mce-latex-loader').length > 0; //validate element has created if (ifa.length > 0 && $elm.find('span.mce-object-iframe').length > 0) { $elm.html('loading...'); needUpdated = true; } if (!needUpdated) { return; } var iframe = editor.getDoc().createElement('iframe'); editor.$.each({ style: 'border:0;width:16px;height:16px', scrolling: 'no', frameborder: 0, allowTransparency: true, src: fixSrc, 'data-state': 1 }, function (i, v) { iframe.setAttribute(i, v); }); $elm.find('img.mce-latex-loader').replaceWith(iframe); var wrap = frameWrapper(editor, iframe); wrap.setValue($elm.attr('data-mce-p-data-latex')); if ($elm.find('span.mce-shim', elm).length === 0) { $elm.append(''); } }); }); }; return { setup: setup }; } ); /** * LoadCss.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.plugins.mathjax.core.LoadCss', [ 'tinymce.core.dom.DOMUtils', 'tinymce.core.util.Tools' ], function (DOMUtils, Tools) { var cssId = DOMUtils.DOM.uniqueId(); var load = function (doc, url) { var linkElements = Tools.toArray(doc.getElementsByTagName('link')); var matchingLinkElms = Tools.grep(linkElements, function (head) { return head.id === cssId; }); if (matchingLinkElms.length === 0) { var linkElm = DOMUtils.DOM.create('link', { id: cssId, rel: 'stylesheet', href: url }); doc.getElementsByTagName('head')[0].appendChild(linkElm); } }; return { load: load }; } ); /** * Buttons.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.plugins.mathjax.ui.Buttons', [ ], function () { var register = function (editor, pluginUrl) { editor.addButton('mathjax', { icon:'mathjax', // image: pluginUrl + '/img/mathjax.png', tooltip: 'Insert/edit math', cmd: 'mceMath', stateSelector: ['span[data-mce-math]'] }); editor.addMenuItem('mathjax', { icon: 'mathjax', // image: pluginUrl + '/img/mathjax.png', text: 'Math', cmd: 'mceMath', context: 'insert', prependToContext: true }); }; return { register: register }; } ); /** * Plugin.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.plugins.mathjax.Plugin', [ 'tinymce.core.PluginManager', 'tinymce.plugins.mathjax.api.Api', 'tinymce.plugins.mathjax.api.Commands', 'tinymce.plugins.mathjax.core.FilterContent', 'tinymce.plugins.mathjax.core.LoadCss', 'tinymce.plugins.mathjax.ui.Buttons' ], function (PluginManager, Api, Commands, FilterContent, LoadCss, Buttons) { var handleError = function (editor) { return function (error) { var errorMessage = error && error.msg ? 'Media embed handler error: ' + error.msg : 'Media embed handler threw unknown error.'; editor.notificationManager.open({ type: 'error', text: errorMessage }); }; }; PluginManager.add('mathjax', function (editor, pluginUrl) { editor.on('init', function () { setTimeout(function () { try { LoadCss.load(editor.editorContainer.ownerDocument, pluginUrl + '/css/mathjax-button.css'); } catch (e) { (handleError(editor))(e); } LoadCss.load(editor.getDoc(), pluginUrl + '/css/mathjax.css'); }, 200); }); Commands.register(editor, pluginUrl); Buttons.register(editor, pluginUrl); FilterContent.setup(editor, pluginUrl); return Api.get(editor, pluginUrl); }); return function () { }; } ); dem('tinymce.plugins.mathjax.Plugin')(); })();