diff --git a/.gitignore b/.gitignore index 040254cb..afa8f46a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ build *.swp .DS_Store .project +.idea node_modules diff --git a/demo/index.html b/demo/index.html index 0fbb962d..175391cb 100644 --- a/demo/index.html +++ b/demo/index.html @@ -1,9 +1,8 @@ -
- + @@ -182,15 +181,11 @@]*>( | |\s|\u00a0|)<\/p>[\r\n]*|
[\r\n]*)$/, '');
- });
- }
-
- self.load({initial: true, format: 'html'});
- self.startContent = self.getContent({format: 'raw'});
-
- /**
- * Is set to true after the editor instance has been initialized
- *
- * @property initialized
- * @type Boolean
- * @example
- * function isEditorInitialized(editor) {
- * return editor && editor.initialized;
- * }
- */
- self.initialized = true;
-
- each(self._pendingNativeEvents, function(name) {
- self.dom.bind(getEventTarget(self, name), name, function(e) {
- self.fire(e.type, e);
- });
- });
-
- self.fire('init');
- self.focus(true);
- self.nodeChanged({initial: true});
- self.execCallback('init_instance_callback', self);
-
- // Add editor specific CSS styles
- if (self.contentStyles.length > 0) {
- contentCssText = '';
-
- each(self.contentStyles, function(style) {
- contentCssText += style + "\r\n";
- });
-
- self.dom.addStyle(contentCssText);
- }
-
- // Load specified content CSS last
- each(self.contentCSS, function(url) {
- self.dom.loadCSS(url);
- });
-
- // Handle auto focus
- if (settings.auto_focus) {
- setTimeout(function () {
- var ed = self.editorManager.get(settings.auto_focus);
-
- ed.selection.select(ed.getBody(), 1);
- ed.selection.collapse(1);
- ed.getBody().focus();
- ed.getWin().focus();
- }, 100);
- }
-
- // Clean up references for IE
- targetElm = doc = body = null;
- },
-
- /**
- * Focuses/activates the editor. This will set this editor as the activeEditor in the tinymce collection
- * it will also place DOM focus inside the editor.
- *
- * @method focus
- * @param {Boolean} skip_focus Skip DOM focus. Just set is as the active editor.
- */
- focus: function(skip_focus) {
- var oed, self = this, selection = self.selection, contentEditable = self.settings.content_editable, rng;
- var controlElm, doc = self.getDoc(), body;
-
- if (!skip_focus) {
- if ((rng = selection.lastRng)) {
- selection.lastRng = null;
- selection.setRng(rng);
- self.nodeChanged();
- }
-
- // Get selected control element
- rng = selection.getRng();
- if (rng.item) {
- controlElm = rng.item(0);
- }
-
- self._refreshContentEditable();
-
- // Focus the window iframe
- if (!contentEditable) {
- self.getWin().focus();
- }
-
- // Focus the body as well since it's contentEditable
- if (isGecko || contentEditable) {
- body = self.getBody();
-
- // Check for setActive since it doesn't scroll to the element
- if (body.setActive) {
- body.setActive();
- } else {
- body.focus();
- }
-
- if (contentEditable) {
- selection.normalize();
- }
- }
-
- // Restore selected control element
- // This is needed when for example an image is selected within a
- // layer a call to focus will then remove the control selection
- if (controlElm && controlElm.ownerDocument == doc) {
- rng = doc.body.createControlRange();
- rng.addElement(controlElm);
- rng.select();
- }
- }
-
- if (self.editorManager.activeEditor != self) {
- if ((oed = self.editorManager.activeEditor)) {
- oed.fire('deactivate', {relatedTarget: self});
- }
-
- self.fire('activate', {relatedTarget: oed});
- }
-
- self.editorManager.activeEditor = self;
- },
-
- /**
- * Executes a legacy callback. This method is useful to call old 2.x option callbacks.
- * There new event model is a better way to add callback so this method might be removed in the future.
- *
- * @method execCallback
- * @param {String} name Name of the callback to execute.
- * @return {Object} Return value passed from callback function.
- */
- execCallback: function(name) {
- var self = this, callback = self.settings[name], scope;
-
- if (!callback) {
- return;
- }
-
- // Look through lookup
- if (self.callbackLookup && (scope = self.callbackLookup[name])) {
- callback = scope.func;
- scope = scope.scope;
- }
-
- if (typeof(callback) === 'string') {
- scope = callback.replace(/\.\w+$/, '');
- scope = scope ? resolve(scope) : 0;
- callback = resolve(callback);
- self.callbackLookup = self.callbackLookup || {};
- self.callbackLookup[name] = {func: callback, scope: scope};
- }
-
- return callback.apply(scope || self, Array.prototype.slice.call(arguments, 1));
- },
-
- /**
- * Translates the specified string by replacing variables with language pack items it will also check if there is
- * a key mathcin the input.
- *
- * @method translate
- * @param {String} text String to translate by the language pack data.
- * @return {String} Translated string.
- */
- translate: function(text) {
- var lang = this.settings.language || 'en', i18n = this.editorManager.i18n;
-
- if (!text) {
- return '';
- }
-
- return i18n[lang + '.' + text] || text.replace(/\{\#([^\}]+)\}/g, function(a, b) {
- return i18n[lang + '.' + b] || '{#' + b + '}';
- });
- },
-
- /**
- * Returns a language pack item by name/key.
- *
- * @method getLang
- * @param {String} name Name/key to get from the language pack.
- * @param {String} defaultVal Optional default value to retrive.
- */
- getLang: function(name, defaultVal) {
- return (
- this.editorManager.i18n[(this.settings.language || 'en') + '.' + name] ||
- (defaultVal !== undefined ? defaultVal : '{#' + name + '}')
- );
- },
-
- /**
- * Returns a configuration parameter by name.
- *
- * @method getParam
- * @param {String} name Configruation parameter to retrive.
- * @param {String} defaultVal Optional default value to return.
- * @param {String} type Optional type parameter.
- * @return {String} Configuration parameter value or default value.
- * @example
- * // Returns a specific config value from the currently active editor
- * var someval = tinymce.activeEditor.getParam('myvalue');
- *
- * // Returns a specific config value from a specific editor instance by id
- * var someval2 = tinymce.get('my_editor').getParam('myvalue');
- */
- getParam: function(name, defaultVal, type) {
- var value = name in this.settings ? this.settings[name] : defaultVal, output;
-
- if (type === 'hash') {
- output = {};
-
- if (typeof(value) === 'string') {
- each(value.indexOf('=') > 0 ? value.split(/[;,](?![^=;,]*(?:[;,]|$))/) : value.split(','), function(value) {
- value = value.split('=');
-
- if (value.length > 1) {
- output[trim(value[0])] = trim(value[1]);
- } else {
- output[trim(value[0])] = trim(value);
- }
- });
- } else {
- output = value;
- }
-
- return output;
- }
-
- return value;
- },
-
- /**
- * Distpaches out a onNodeChange event to all observers. This method should be called when you
- * need to update the UI states or element path etc.
- *
- * @method nodeChanged
- */
- nodeChanged: function() {
- var self = this, selection = self.selection, node, parents, root;
-
- // Fix for bug #1896577 it seems that this can not be fired while the editor is loading
- if (self.initialized && !self.settings.disable_nodechange) {
- // Get start node
- root = self.getBody();
- node = selection.getStart() || root;
- node = isIE && node.ownerDocument != self.getDoc() ? self.getBody() : node; // Fix for IE initial state
-
- // Edge case for
|
x
becomes this:x
- function trimInlineElementsOnLeftSideOfBlock(block) { - var node = block, firstChilds = [], i; - - // Find inner most first child ex:*
- while ((node = node.firstChild)) { - if (dom.isBlock(node)) { - return; - } - - if (node.nodeType == 1 && !nonEmptyElementsMap[node.nodeName.toLowerCase()]) { - firstChilds.push(node); - } - } - - i = firstChilds.length; - while (i--) { - node = firstChilds[i]; - if (!node.hasChildNodes() || (node.firstChild == node.lastChild && node.firstChild.nodeValue === '')) { - dom.remove(node); - } else { - // Remove see #5381 - if (node.nodeName == "A" && (node.innerText || node.textContent) === ' ') { - dom.remove(node); - } - } - } - } - - // Moves the caret to a suitable position within the root for example in the first non - // pure whitespace text node or before an image - function moveToCaretPosition(root) { - var walker, node, rng, lastNode = root, tempElm; - - rng = dom.createRng(); - - if (root.hasChildNodes()) { - walker = new TreeWalker(root, root); - - while ((node = walker.current())) { - if (node.nodeType == 3) { - rng.setStart(node, 0); - rng.setEnd(node, 0); - break; - } - - if (nonEmptyElementsMap[node.nodeName.toLowerCase()]) { - rng.setStartBefore(node); - rng.setEndBefore(node); - break; - } - - lastNode = node; - node = walker.next(); - } - - if (!node) { - rng.setStart(lastNode, 0); - rng.setEnd(lastNode, 0); - } - } else { - if (root.nodeName == 'BR') { - if (root.nextSibling && dom.isBlock(root.nextSibling)) { - // Trick on older IE versions to render the caret before the BR between two lists - if (!documentMode || documentMode < 9) { - tempElm = dom.create('br'); - root.parentNode.insertBefore(tempElm, root); - } - - rng.setStartBefore(root); - rng.setEndBefore(root); - } else { - rng.setStartAfter(root); - rng.setEndAfter(root); - } - } else { - rng.setStart(root, 0); - rng.setEnd(root, 0); - } - } - - selection.setRng(rng); - - // Remove tempElm created for old IE:s - dom.remove(tempElm); - selection.scrollIntoView(root); - } - - // Creates a new block element by cloning the current one or creating a new one if the name is specified - // This function will also copy any text formatting from the parent block and add it to the new one - function createNewBlock(name) { - var node = container, block, clonedNode, caretNode; - - block = name || parentBlockName == "TABLE" ? dom.create(name || newBlockName) : parentBlock.cloneNode(false); - caretNode = block; - - // Clone any parent styles - if (settings.keep_styles !== false) { - do { - if (/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(node.nodeName)) { - // Never clone a caret containers - if (node.id == '_mce_caret') { - continue; - } - - clonedNode = node.cloneNode(false); - dom.setAttrib(clonedNode, 'id', ''); // Remove ID since it needs to be document unique - - if (block.hasChildNodes()) { - clonedNode.appendChild(block.firstChild); - block.appendChild(clonedNode); - } else { - caretNode = clonedNode; - block.appendChild(clonedNode); - } - } - } while ((node = node.parentNode)); - } - - // BR is needed in empty blocks on non IE browsers - if (!isIE) { - caretNode.innerHTML = 'text|
text|text2
*texttext*
! - // This will reduce the number of wrapper elements that needs to be created - // Move start point up the tree - if (format[0].inline || format[0].block_expand) { - if (!format[0].inline || (startContainer.nodeType != 3 || startOffset === 0)) { - startContainer = findParentContainer(true); - } - - if (!format[0].inline || (endContainer.nodeType != 3 || endOffset === endContainer.nodeValue.length)) { - endContainer = findParentContainer(); - } - } - - // Expand start/end container to matching selector - if (format[0].selector && format[0].expand !== FALSE && !format[0].inline) { - // Find new startContainer/endContainer if there is better one - startContainer = findSelectorEndPoint(startContainer, 'previousSibling'); - endContainer = findSelectorEndPoint(endContainer, 'nextSibling'); - } - - // Expand start/end container to matching block element or text node - if (format[0].block || format[0].selector) { - // Find new startContainer/endContainer if there is better one - startContainer = findBlockEndPoint(startContainer, 'previousSibling'); - endContainer = findBlockEndPoint(endContainer, 'nextSibling'); - - // Non block element then try to expand up the leaf - if (format[0].block) { - if (!isBlock(startContainer)) { - startContainer = findParentContainer(true); - } - - if (!isBlock(endContainer)) { - endContainer = findParentContainer(); - } - } - } - - // Setup index for startContainer - if (startContainer.nodeType == 1) { - startOffset = nodeIndex(startContainer); - startContainer = startContainer.parentNode; - } - - // Setup index for endContainer - if (endContainer.nodeType == 1) { - endOffset = nodeIndex(endContainer) + 1; - endContainer = endContainer.parentNode; - } - - // Return new range like object - return { - startContainer: startContainer, - startOffset: startOffset, - endContainer: endContainer, - endOffset: endOffset - }; - } - - /** - * Removes the specified format for the specified node. It will also remove the node if it doesn't have - * any attributes if the format specifies it to do so. - * - * @private - * @param {Object} format Format object with items to remove from node. - * @param {Object} vars Name/value object with variables to apply to format. - * @param {Node} node Node to remove the format styles on. - * @param {Node} compare_node Optional compare node, if specified the styles will be compared to that node. - * @return {Boolean} True/false if the node was removed or not. - */ - function removeFormat(format, vars, node, compare_node) { - var i, attrs, stylesModified; - - // Check if node matches format - if (!matchName(node, format)) { - return FALSE; - } - - // Should we compare with format attribs and styles - if (format.remove != 'all') { - // Remove styles - each(format.styles, function(value, name) { - value = replaceVars(value, vars); - - // Indexed array - if (typeof(name) === 'number') { - name = value; - compare_node = 0; - } - - if (!compare_node || isEq(getStyle(compare_node, name), value)) { - dom.setStyle(node, name, ''); - } - - stylesModified = 1; - }); - - // Remove style attribute if it's empty - if (stylesModified && dom.getAttrib(node, 'style') === '') { - node.removeAttribute('style'); - node.removeAttribute('data-mce-style'); - } - - // Remove attributes - each(format.attributes, function(value, name) { - var valueOut; - - value = replaceVars(value, vars); - - // Indexed array - if (typeof(name) === 'number') { - name = value; - compare_node = 0; - } - - if (!compare_node || isEq(dom.getAttrib(compare_node, name), value)) { - // Keep internal classes - if (name == 'class') { - value = dom.getAttrib(node, name); - if (value) { - // Build new class value where everything is removed except the internal prefixed classes - valueOut = ''; - each(value.split(/\s+/), function(cls) { - if (/mce\w+/.test(cls)) { - valueOut += (valueOut ? ' ' : '') + cls; - } - }); - - // We got some internal classes left - if (valueOut) { - dom.setAttrib(node, name, valueOut); - return; - } - } - } - - // IE6 has a bug where the attribute doesn't get removed correctly - if (name == "class") { - node.removeAttribute('className'); - } - - // Remove mce prefixed attributes - if (MCE_ATTR_RE.test(name)) { - node.removeAttribute('data-mce-' + name); - } - - node.removeAttribute(name); - } - }); - - // Remove classes - each(format.classes, function(value) { - value = replaceVars(value, vars); - - if (!compare_node || dom.hasClass(compare_node, value)) { - dom.removeClass(node, value); - } - }); - - // Check for non internal attributes - attrs = dom.getAttribs(node); - for (i = 0; i < attrs.length; i++) { - if (attrs[i].nodeName.indexOf('_') !== 0) { - return FALSE; - } - } - } - - // Remove the inline child if it's empty for example or - if (format.remove != 'none') { - removeNode(node, format); - return TRUE; - } - } - - /** - * Removes the node and wrap it's children in paragraphs before doing so or - * appends BR elements to the beginning/end of the block element if forcedRootBlocks is disabled. - * - * If the div in the node below gets removed: - * textabcabc123
would produceabc
abc123
. - * - * @method split - * @param {Element} parentElm Parent element to split. - * @param {Element} splitElm Element to split at. - * @param {Element} replacementElm Optional replacement element to replace the split element by. - * @return {Element} Returns the split element or the replacement element if that is specified. - */ - split: function(parentElm, splitElm, replacementElm) { - var self = this, r = self.createRng(), bef, aft, pa; - - // W3C valid browsers tend to leave empty nodes to the left/right side of the contents, this makes sense - // but we don't want that in our code since it serves no purpose for the end user - // For example if this is chopped: - //text 1CHOPtext 2
- // would produce: - //text 1
CHOPtext 2
- // this function will then trim of empty edges and produce: - //text 1
CHOPtext 2
- function trimNode(node) { - var i, children = node.childNodes, type = node.nodeType; - - function surroundedBySpans(node) { - var previousIsSpan = node.previousSibling && node.previousSibling.nodeName == 'SPAN'; - var nextIsSpan = node.nextSibling && node.nextSibling.nodeName == 'SPAN'; - return previousIsSpan && nextIsSpan; - } - - if (type == 1 && node.getAttribute('data-mce-type') == 'bookmark') { - return; - } - - for (i = children.length - 1; i >= 0; i--) { - trimNode(children[i]); - } - - if (type != 9) { - // Keep non whitespace text nodes - if (type == 3 && node.nodeValue.length > 0) { - // If parent element isn't a block or there isn't any useful contents for example "" - // Also keep text nodes with only spaces if surrounded by spans. - // eg. "
a b
" should keep space between a and b - var trimmedLength = trim(node.nodeValue).length; - if (!self.isBlock(node.parentNode) || trimmedLength > 0 || trimmedLength === 0 && surroundedBySpans(node)) { - return; - } - } else if (type == 1) { - // If the only child is a bookmark then move it up - children = node.childNodes; - - // TODO fix this complex if - if (children.length == 1 && children[0] && children[0].nodeType == 1 && - children[0].getAttribute('data-mce-type') == 'bookmark') { - node.parentNode.insertBefore(children[0], node); - } - - // Keep non empty elements or img, hr etc - if (children.length || /^(br|hr|input|img)$/i.test(node.nodeName)) { - return; - } - } - - self.remove(node); - } - - return node; - } - - if (parentElm && splitElm) { - // Get before chunk - r.setStart(parentElm.parentNode, self.nodeIndex(parentElm)); - r.setEnd(splitElm.parentNode, self.nodeIndex(splitElm)); - bef = r.extractContents(); - - // Get after chunk - r = self.createRng(); - r.setStart(splitElm.parentNode, self.nodeIndex(splitElm) + 1); - r.setEnd(parentElm.parentNode, self.nodeIndex(parentElm) + 1); - aft = r.extractContents(); - - // Insert before chunk - pa = parentElm.parentNode; - pa.insertBefore(trimNode(bef), parentElm); - - // Insert middle chunk - if (replacementElm) { - pa.replaceChild(replacementElm, splitElm); - } else { - pa.insertBefore(splitElm, parentElm); - } - - // Insert after chunk - pa.insertBefore(trimNode(aft), parentElm); - self.remove(parentElm); - - return replacementElm || splitElm; - } - }, - - /** - * Adds an event handler to the specified object. - * - * @method bind - * @param {Element/Document/Window/Array/String} o Object or element id string to add event - * handler to or an array of elements/ids/documents. - * @param {String} n Name of event handler to add for example: click. - * @param {function} f Function to execute when the event occurs. - * @param {Object} s Optional scope to execute the function in. - * @return {function} Function callback handler the same as the one passed in. - */ - bind: function(target, name, func, scope) { - return this.events.bind(target, name, func, scope || this); - }, - - /** - * Removes the specified event handler by name and function from a element or collection of elements. - * - * @method unbind - * @param {String/Element/Array} o Element ID string or HTML element or an array of elements or ids to remove handler from. - * @param {String} n Event handler name like for example: "click" - * @param {function} f Function to remove. - * @return {bool/Array} Bool state if true if the handler was removed or an array with states if multiple elements where passed in. - */ - unbind: function(target, name, func) { - return this.events.unbind(target, name, func); - }, - - /** - * Fires the specified event name with object on target. - * - * @method fire - * @param {Node/Document/Window} target Target element or object to fire event on. - * @param {String} name Name of the event to fire. - * @param {Object} evt Event object to send. - * @return {Event} Event object. - */ - fire: function(target, name, evt) { - return this.events.fire(target, name, evt); - }, - - // Returns the content editable state of a node - getContentEditable: function(node) { - var contentEditable; - - // Check type - if (node.nodeType != 1) { - return null; - } - - // Check for fake content editable - contentEditable = node.getAttribute("data-mce-contenteditable"); - if (contentEditable && contentEditable !== "inherit") { - return contentEditable; - } - - // Check for real content editable - return node.contentEditable !== "inherit" ? node.contentEditable : null; - }, - - /** - * Destroys all internal references to the DOM to solve IE leak issues. - * - * @method destroy - */ - destroy: function() { - var self = this; - - self.win = self.doc = self.root = self.events = self.frag = null; - }, - - // #ifdef debug - - dumpRng: function(r) { - return ( - 'startContainer: ' + r.startContainer.nodeName + - ', startOffset: ' + r.startOffset + - ', endContainer: ' + r.endContainer.nodeName + - ', endOffset: ' + r.endOffset - ); - }, - - // #endif - - _findSib: function(node, selector, name) { - var self = this, func = selector; - - if (node) { - // If expression make a function of it using is - if (typeof(func) == 'string') { - func = function(node) { - return self.is(node, selector); - }; - } - - // Loop all siblings - for (node = node[name]; node; node = node[name]) { - if (func(node)) { - return node; - } - } - } - - return null; - } - }; - - /** - * Instance of DOMUtils for the current document. - * - * @property DOM - * @member tinymce - * @type tinymce.dom.DOMUtils - * @example - * // Example of how to add a class to some element by id - * tinymce.DOM.addClass('someid', 'someclass'); - */ - DOMUtils.DOM = new DOMUtils(document); - - return DOMUtils; -}); diff --git a/lib/tinymce/js/tinymce/classes/dom/DomQuery.js b/lib/tinymce/js/tinymce/classes/dom/DomQuery.js deleted file mode 100644 index fae010cb..00000000 --- a/lib/tinymce/js/tinymce/classes/dom/DomQuery.js +++ /dev/null @@ -1,719 +0,0 @@ -/** - * DomQuery.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - * - * Some of this logic is based on jQuery code that is released under - * MIT license that grants us to sublicense it under LGPL. - */ - -define("tinymce/dom/DomQuery", [ - "tinymce/dom/EventUtils", - "tinymce/dom/Sizzle" -], function(EventUtils, Sizzle) { - var doc = document, push = Array.prototype.push, slice = Array.prototype.slice; - var rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/; - var Event = EventUtils.Event; - - function isDefined(obj) { - return typeof obj !== "undefined"; - } - - function isString(obj) { - return typeof obj === "string"; - } - - function createFragment(html) { - var frag, node, container; - - container = doc.createElement("div"); - frag = doc.createDocumentFragment(); - container.innerHTML = html; - - while ((node = container.firstChild)) { - frag.appendChild(node); - } - - return frag; - } - - function domManipulate(targetNodes, sourceItem, callback) { - var i; - - if (typeof sourceItem === "string") { - sourceItem = createFragment(sourceItem); - } else if (sourceItem.length) { - for (i = 0; i < sourceItem.length; i++) { - domManipulate(targetNodes, sourceItem[i], callback); - } - - return targetNodes; - } - - i = targetNodes.length; - while (i--) { - callback.call(targetNodes[i], sourceItem.parentNode ? sourceItem : sourceItem); - } - - return targetNodes; - } - - function hasClass(node, className) { - return node && className && (' ' + node.className + ' ').indexOf(' ' + className + ' ') !== -1; - } - - /** - * Makes a map object out of a string that gets separated by a delimiter. - * - * @method makeMap - * @param {String} items Item string to split. - * @param {Object} map Optional object to add items to. - * @return {Object} name/value object with items as keys. - */ - function makeMap(items, map) { - var i; - - items = items || []; - - if (typeof(items) == "string") { - items = items.split(' '); - } - - map = map || {}; - - i = items.length; - while (i--) { - map[items[i]] = {}; - } - - return map; - } - - var numericCssMap = makeMap('fillOpacity fontWeight lineHeight opacity orphans widows zIndex zoom'); - - function DomQuery(selector, context) { - return new DomQuery.fn.init(selector, context); - } - - /** - * Extends the specified object with another object. - * - * @method extend - * @param {Object} target Object to extend. - * @param {Object..} obj Multiple objects to extend with. - * @return {Object} Same as target, the extended object. - */ - function extend(target) { - var args = arguments, arg, i, key; - - for (i = 1; i < args.length; i++) { - arg = args[i]; - - for (key in arg) { - target[key] = arg[key]; - } - } - - return target; - } - - /** - * Converts the specified object into a real JavaScript array. - * - * @method toArray - * @param {Object} obj Object to convert into array. - * @return {Array} Array object based in input. - */ - function toArray(obj) { - var array = [], i, l; - - for (i = 0, l = obj.length; i < l; i++) { - array[i] = obj[i]; - } - - return array; - } - - /** - * Returns the index of the specified item inside the array. - * - * @method inArray - * @param {Object} item Item to look for. - * @param {Array} array Array to look for item in. - * @return {Number} Index of the item or -1. - */ - function inArray(item, array) { - var i; - - if (array.indexOf) { - return array.indexOf(item); - } - - i = array.length; - while (i--) { - if (array[i] === item) { - return i; - } - } - - return -1; - } - - /** - * Returns true/false if the specified object is an array. - * - * @method isArray - * @param {Object} obj Object to check if it's an array. - * @return {Boolean} true/false if the input object is array or not. - */ - var isArray = Array.isArray || function(obj) { - return Object.prototype.toString.call(obj) === "[object Array]"; - }; - - var whiteSpaceRegExp = /^\s*|\s*$/g; - var trim = function(str) { - return (str === null || str === undefined) ? '' : ("" + str).replace(whiteSpaceRegExp, ''); - }; - - /** - * Executes the callback function for each item in array/object. If you return false in the - * callback it will break the loop. - * - * @method each - * @param {Object} obj Object to iterate. - * @param {function} callback Callback function to execute for each item. - */ - function each(obj, callback) { - var length, key, i, undef, value; - - if (obj) { - length = obj.length; - - if (length === undef) { - // Loop object items - for (key in obj) { - if (obj.hasOwnProperty(key)) { - value = obj[key]; - if (callback.call(value, value, key) === false) { - break; - } - } - } - } else { - // Loop array items - for (i = 0; i < length; i++) { - value = obj[i]; - if (callback.call(value, value, key) === false) { - break; - } - } - } - } - - return obj; - } - - DomQuery.fn = DomQuery.prototype = { - constructor: DomQuery, - selector: "", - length: 0, - - init: function(selector, context) { - var self = this, match, node; - - if (!selector) { - return self; - } - - if (selector.nodeType) { - self.context = self[0] = selector; - self.length = 1; - - return self; - } - - if (isString(selector)) { - if (selector.charAt(0) === "<" && selector.charAt(selector.length - 1) === ">" && selector.length >= 3) { - match = [null, selector, null]; - } else { - match = rquickExpr.exec(selector); - } - - if (match) { - if (match[1]) { - node = createFragment(selector).firstChild; - while (node) { - this.add(node); - node = node.nextSibling; - } - } else { - node = doc.getElementById(match[2]); - - if (node.id !== match[2]) { - return self.find(selector); - } - - self.length = 1; - self[0] = node; - } - } else { - return DomQuery(context || document).find(selector); - } - } else { - this.add(selector); - } - - return self; - }, - - toArray: function() { - return toArray(this); - }, - - add: function(items) { - var self = this; - - // Force single item into array - if (!isArray(items)) { - if (items instanceof DomQuery) { - self.add(items.toArray()); - } else { - push.call(self, items); - } - } else { - push.apply(self, items); - } - - return self; - }, - - attr: function(name, value) { - var self = this; - - if (typeof name === "object") { - each(name, function(value, name) { - self.attr(name, value); - }); - } else if (isDefined(value)) { - this.each(function() { - if (this.nodeType === 1) { - this.setAttribute(name, value); - } - }); - } else { - return self[0] && self[0].nodeType === 1 ? self[0].getAttribute(name) : undefined; - } - - return self; - }, - - css: function(name, value) { - var self = this; - - if (typeof name === "object") { - each(name, function(value, name) { - self.css(name, value); - }); - } else { - // Camelcase it, if needed - name = name.replace(/-(\D)/g, function(a, b) { - return b.toUpperCase(); - }); - - if (isDefined(value)) { - // Default px suffix on these - if (typeof(value) === 'number' && !numericCssMap[name]) { - value += 'px'; - } - - self.each(function() { - var style = this.style; - - // IE specific opacity - if (name === "opacity" && this.runtimeStyle && typeof(this.runtimeStyle.opacity) === "undefined") { - style.filter = value === '' ? '' : "alpha(opacity=" + (value * 100) + ")"; - } - - try { - style[name] = value; - } catch (ex) { - // Ignore - } - }); - } else { - return self[0] ? self[0].style[name] : undefined; - } - } - - return self; - }, - - remove: function() { - var self = this, node, i = this.length; - - while (i--) { - node = self[i]; - Event.clean(node); - - if (node.parentNode) { - node.parentNode.removeChild(node); - } - } - - return this; - }, - - empty: function() { - var self = this, node, i = this.length; - - while (i--) { - node = self[i]; - while (node.firstChild) { - node.removeChild(node.firstChild); - } - } - - return this; - }, - - html: function(value) { - var self = this, i; - - if (isDefined(value)) { - i = self.length; - while (i--) { - self[i].innerHTML = value; - } - - return self; - } - - return self[0] ? self[0].innerHTML : ''; - }, - - text: function(value) { - var self = this, i; - - if (isDefined(value)) { - i = self.length; - while (i--) { - self[i].innerText = self[0].textContent = value; - } - - return self; - } - - return self[0] ? self[0].innerText || self[0].textContent : ''; - }, - - append: function() { - return domManipulate(this, arguments, function(node) { - if (this.nodeType === 1) { - this.appendChild(node); - } - }); - }, - - prepend: function() { - return domManipulate(this, arguments, function(node) { - if (this.nodeType === 1) { - this.insertBefore(node, this.firstChild); - } - }); - }, - - before: function() { - var self = this; - - if (self[0] && self[0].parentNode) { - return domManipulate(self, arguments, function(node) { - this.parentNode.insertBefore(node, this.nextSibling); - }); - } - - return self; - }, - - after: function() { - var self = this; - - if (self[0] && self[0].parentNode) { - return domManipulate(self, arguments, function(node) { - this.parentNode.insertBefore(node, this); - }); - } - - return self; - }, - - appendTo: function(val) { - DomQuery(val).append(this); - - return this; - }, - - addClass: function(className) { - return this.toggleClass(className, true); - }, - - removeClass: function(className) { - return this.toggleClass(className, false); - }, - - toggleClass: function(className, state) { - var self = this; - - if (className.indexOf(' ') !== -1) { - each(className.split(' '), function() { - self.toggleClass(this, state); - }); - } else { - self.each(function() { - var node = this, existingClassName; - - if (hasClass(node, className) !== state) { - existingClassName = node.className; - - if (state) { - node.className += existingClassName ? ' ' + className : className; - } else { - node.className = trim((" " + existingClassName + " ").replace(' ' + className + ' ', ' ')); - } - } - }); - } - - return self; - }, - - hasClass: function(className) { - return hasClass(this[0], className); - }, - - each: function(callback) { - return each(this, callback); - }, - - on: function(name, callback) { - return this.each(function() { - Event.bind(this, name, callback); - }); - }, - - off: function(name, callback) { - return this.each(function() { - Event.unbind(this, name, callback); - }); - }, - - show: function() { - return this.css('display', ''); - }, - - hide: function() { - return this.css('display', 'none'); - }, - - slice: function() { - return new DomQuery(slice.apply(this, arguments)); - }, - - eq: function(index) { - return index === -1 ? this.slice(index) : this.slice(index, +index + 1); - }, - - first: function() { - return this.eq(0); - }, - - last: function() { - return this.eq(-1); - }, - - replaceWith: function(content) { - var self = this; - - if (self[0]) { - self[0].parentNode.replaceChild(DomQuery(content)[0], self[0]); - } - - return self; - }, - - wrap: function(wrapper) { - wrapper = DomQuery(wrapper)[0]; - - return this.each(function() { - var self = this, newWrapper = wrapper.cloneNode(false); - self.parentNode.insertBefore(newWrapper, self); - newWrapper.appendChild(self); - }); - }, - - unwrap: function() { - return this.each(function() { - var self = this, node = self.firstChild, currentNode; - - while (node) { - currentNode = node; - node = node.nextSibling; - self.parentNode.insertBefore(currentNode, self); - } - }); - }, - - clone: function() { - var result = []; - - this.each(function() { - result.push(this.cloneNode(true)); - }); - - return DomQuery(result); - }, - - find: function(selector) { - var i, l, ret = []; - - for (i = 0, l = this.length; i < l; i++) { - DomQuery.find(selector, this[i], ret); - } - - return DomQuery(ret); - }, - - push: push, - sort: [].sort, - splice: [].splice - }; - - // Static members - extend(DomQuery, { - extend: extend, - toArray: toArray, - inArray: inArray, - isArray: isArray, - each: each, - trim: trim, - makeMap: makeMap, - - // Sizzle - find: Sizzle, - expr: Sizzle.selectors, - unique: Sizzle.uniqueSort, - text: Sizzle.getText, - isXMLDoc: Sizzle.isXML, - contains: Sizzle.contains, - filter: function(expr, elems, not) { - if (not) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 ? - DomQuery.find.matchesSelector(elems[0], expr) ? [elems[0]] : [] : - DomQuery.find.matches(expr, elems); - } - }); - - function dir(el, prop, until) { - var matched = [], cur = el[prop]; - - while (cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !DomQuery(cur).is(until))) { - if (cur.nodeType === 1) { - matched.push(cur); - } - - cur = cur[prop]; - } - - return matched; - } - - function sibling(n, el, siblingName, nodeType) { - var r = []; - - for(; n; n = n[siblingName]) { - if ((!nodeType || n.nodeType === nodeType) && n !== el) { - r.push(n); - } - } - - return r; - } - - each({ - parent: function(node) { - var parent = node.parentNode; - - return parent && parent.nodeType !== 11 ? parent : null; - }, - - parents: function(node) { - return dir(node, "parentNode"); - }, - - parentsUntil: function(node, until) { - return dir(node, "parentNode", until); - }, - - next: function(node) { - return sibling(node, 'nextSibling', 1); - }, - - prev: function(node) { - return sibling(node, 'previousSibling', 1); - }, - - nextNodes: function(node) { - return sibling(node, 'nextSibling'); - }, - - prevNodes: function(node) { - return sibling(node, 'previousSibling'); - }, - - children: function(node) { - return sibling(node.firstChild, 'nextSibling', 1); - }, - - contents: function(node) { - return toArray((node.nodeName === "iframe" ? node.contentDocument || node.contentWindow.document : node).childNodes); - } - }, function(name, fn){ - DomQuery.fn[name] = function(selector) { - var self = this, result; - - if (self.length > 1) { - throw new Error("DomQuery only supports traverse functions on a single node."); - } - - if (self[0]) { - result = fn(self[0], selector); - } - - result = DomQuery(result); - - if (selector && name !== "parentsUntil") { - return result.filter(selector); - } - - return result; - }; - }); - - DomQuery.fn.filter = function(selector) { - return DomQuery.filter(selector); - }; - - DomQuery.fn.is = function(selector) { - return !!selector && this.filter(selector).length > 0; - }; - - DomQuery.fn.init.prototype = DomQuery.fn; - - return DomQuery; -}); \ No newline at end of file diff --git a/lib/tinymce/js/tinymce/classes/dom/EventUtils.js b/lib/tinymce/js/tinymce/classes/dom/EventUtils.js deleted file mode 100644 index 5e16af28..00000000 --- a/lib/tinymce/js/tinymce/classes/dom/EventUtils.js +++ /dev/null @@ -1,525 +0,0 @@ -/** - * EventUtils.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -/*jshint loopfunc:true*/ - -define("tinymce/dom/EventUtils", [], function() { - "use strict"; - - var eventExpandoPrefix = "mce-data-"; - - /** - * Binds a native event to a callback on the speified target. - */ - function addEvent(target, name, callback, capture) { - if (target.addEventListener) { - target.addEventListener(name, callback, capture || false); - } else if (target.attachEvent) { - target.attachEvent('on' + name, callback); - } - } - - /** - * Unbinds a native event callback on the specified target. - */ - function removeEvent(target, name, callback, capture) { - if (target.removeEventListener) { - target.removeEventListener(name, callback, capture || false); - } else if (target.detachEvent) { - target.detachEvent('on' + name, callback); - } - } - - /** - * Normalizes a native event object or just adds the event specific methods on a custom event. - */ - function fix(originalEvent, data) { - var name, event = data || {}; - - // Dummy function that gets replaced on the delegation state functions - function returnFalse() { - return false; - } - - // Dummy function that gets replaced on the delegation state functions - function returnTrue() { - return true; - } - - // Copy all properties from the original event - for (name in originalEvent) { - // layerX/layerY is deprecated in Chrome and produces a warning - if (name !== "layerX" && name !== "layerY") { - event[name] = originalEvent[name]; - } - } - - // Normalize target IE uses srcElement - if (!event.target) { - event.target = event.srcElement || document; - } - - // Add preventDefault method - event.preventDefault = function() { - event.isDefaultPrevented = returnTrue; - - // Execute preventDefault on the original event object - if (originalEvent) { - if (originalEvent.preventDefault) { - originalEvent.preventDefault(); - } else { - originalEvent.returnValue = false; // IE - } - } - }; - - // Add stopPropagation - event.stopPropagation = function() { - event.isPropagationStopped = returnTrue; - - // Execute stopPropagation on the original event object - if (originalEvent) { - if (originalEvent.stopPropagation) { - originalEvent.stopPropagation(); - } else { - originalEvent.cancelBubble = true; // IE - } - } - }; - - // Add stopImmediatePropagation - event.stopImmediatePropagation = function() { - event.isImmediatePropagationStopped = returnTrue; - event.stopPropagation(); - }; - - // Add event delegation states - if (!event.isDefaultPrevented) { - event.isDefaultPrevented = returnFalse; - event.isPropagationStopped = returnFalse; - event.isImmediatePropagationStopped = returnFalse; - } - - return event; - } - - /** - * Bind a DOMContentLoaded event across browsers and executes the callback once the page DOM is initialized. - * It will also set/check the domLoaded state of the event_utils instance so ready isn't called multiple times. - */ - function bindOnReady(win, callback, eventUtils) { - var doc = win.document, event = {type: 'ready'}; - - if (eventUtils.domLoaded) { - callback(event); - return; - } - - // Gets called when the DOM is ready - function readyHandler() { - if (!eventUtils.domLoaded) { - eventUtils.domLoaded = true; - callback(event); - } - } - - function waitForDomLoaded() { - if (doc.readyState === "complete") { - removeEvent(doc, "readystatechange", waitForDomLoaded); - readyHandler(); - } - } - - function tryScroll() { - try { - // If IE is used, use the trick by Diego Perini licensed under MIT by request to the author. - // http://javascript.nwbox.com/IEContentLoaded/ - doc.documentElement.doScroll("left"); - } catch (ex) { - setTimeout(tryScroll, 0); - return; - } - - readyHandler(); - } - - // Use W3C method - if (doc.addEventListener) { - addEvent(win, 'DOMContentLoaded', readyHandler); - } else { - // Use IE method - addEvent(doc, "readystatechange", waitForDomLoaded); - - // Wait until we can scroll, when we can the DOM is initialized - if (doc.documentElement.doScroll && win === win.top) { - tryScroll(); - } - } - - // Fallback if any of the above methods should fail for some odd reason - addEvent(win, 'load', readyHandler); - } - - /** - * This class enables you to bind/unbind native events to elements and normalize it's behavior across browsers. - */ - function EventUtils() { - var self = this, events = {}, count, expando, hasFocusIn, hasMouseEnterLeave, mouseEnterLeave; - - expando = eventExpandoPrefix + (+new Date()).toString(32); - hasMouseEnterLeave = "onmouseenter" in document.documentElement; - hasFocusIn = "onfocusin" in document.documentElement; - mouseEnterLeave = {mouseenter: 'mouseover', mouseleave: 'mouseout'}; - count = 1; - - // State if the DOMContentLoaded was executed or not - self.domLoaded = false; - self.events = events; - - /** - * Executes all event handler callbacks for a specific event. - * - * @param {Event} evt Event object. - * @param {String} id Expando id value to look for. - */ - function executeHandlers(evt, id) { - var callbackList, i, l, callback; - - callbackList = events[id][evt.type]; - if (callbackList) { - for (i = 0, l = callbackList.length; i < l; i++) { - callback = callbackList[i]; - - // Check if callback exists might be removed if a unbind is called inside the callback - if (callback && callback.func.call(callback.scope, evt) === false) { - evt.preventDefault(); - } - - // Should we stop propagation to immediate listeners - if (evt.isImmediatePropagationStopped()) { - return; - } - } - } - } - - /** - * Binds a callback to an event on the specified target. - * - * @method bind - * @param {Object} target Target node/window or custom object. - * @param {String} names Name of the event to bind. - * @param {function} callback Callback function to execute when the event occurs. - * @param {Object} scope Scope to call the callback function on, defaults to target. - * @return {function} Callback function that got bound. - */ - self.bind = function(target, names, callback, scope) { - var id, callbackList, i, name, fakeName, nativeHandler, capture, win = window; - - // Native event handler function patches the event and executes the callbacks for the expando - function defaultNativeHandler(evt) { - executeHandlers(fix(evt || win.event), id); - } - - // Don't bind to text nodes or comments - if (!target || target.nodeType === 3 || target.nodeType === 8) { - return; - } - - // Create or get events id for the target - if (!target[expando]) { - id = count++; - target[expando] = id; - events[id] = {}; - } else { - id = target[expando]; - } - - // Setup the specified scope or use the target as a default - scope = scope || target; - - // Split names and bind each event, enables you to bind multiple events with one call - names = names.split(' '); - i = names.length; - while (i--) { - name = names[i]; - nativeHandler = defaultNativeHandler; - fakeName = capture = false; - - // Use ready instead of DOMContentLoaded - if (name === "DOMContentLoaded") { - name = "ready"; - } - - // DOM is already ready - if (self.domLoaded && name === "ready" && target.readyState == 'complete') { - callback.call(scope, fix({type: name})); - continue; - } - - // Handle mouseenter/mouseleaver - if (!hasMouseEnterLeave) { - fakeName = mouseEnterLeave[name]; - - if (fakeName) { - nativeHandler = function(evt) { - var current, related; - - current = evt.currentTarget; - related = evt.relatedTarget; - - // Check if related is inside the current target if it's not then the event should - // be ignored since it's a mouseover/mouseout inside the element - if (related && current.contains) { - // Use contains for performance - related = current.contains(related); - } else { - while (related && related !== current) { - related = related.parentNode; - } - } - - // Fire fake event - if (!related) { - evt = fix(evt || win.event); - evt.type = evt.type === 'mouseout' ? 'mouseleave' : 'mouseenter'; - evt.target = current; - executeHandlers(evt, id); - } - }; - } - } - - // Fake bubbeling of focusin/focusout - if (!hasFocusIn && (name === "focusin" || name === "focusout")) { - capture = true; - fakeName = name === "focusin" ? "focus" : "blur"; - nativeHandler = function(evt) { - evt = fix(evt || win.event); - evt.type = evt.type === 'focus' ? 'focusin' : 'focusout'; - executeHandlers(evt, id); - }; - } - - // Setup callback list and bind native event - callbackList = events[id][name]; - if (!callbackList) { - events[id][name] = callbackList = [{func: callback, scope: scope}]; - callbackList.fakeName = fakeName; - callbackList.capture = capture; - - // Add the nativeHandler to the callback list so that we can later unbind it - callbackList.nativeHandler = nativeHandler; - - // Check if the target has native events support - - if (name === "ready") { - bindOnReady(target, nativeHandler, self); - } else { - addEvent(target, fakeName || name, nativeHandler, capture); - } - } else { - if (name === "ready" && self.domLoaded) { - callback({type: name}); - } else { - // If it already has an native handler then just push the callback - callbackList.push({func: callback, scope: scope}); - } - } - } - - target = callbackList = 0; // Clean memory for IE - - return callback; - }; - - /** - * Unbinds the specified event by name, name and callback or all events on the target. - * - * @method unbind - * @param {Object} target Target node/window or custom object. - * @param {String} names Optional event name to unbind. - * @param {function} callback Optional callback function to unbind. - * @return {EventUtils} Event utils instance. - */ - self.unbind = function(target, names, callback) { - var id, callbackList, i, ci, name, eventMap; - - // Don't bind to text nodes or comments - if (!target || target.nodeType === 3 || target.nodeType === 8) { - return self; - } - - // Unbind event or events if the target has the expando - id = target[expando]; - if (id) { - eventMap = events[id]; - - // Specific callback - if (names) { - names = names.split(' '); - i = names.length; - while (i--) { - name = names[i]; - callbackList = eventMap[name]; - - // Unbind the event if it exists in the map - if (callbackList) { - // Remove specified callback - if (callback) { - ci = callbackList.length; - while (ci--) { - if (callbackList[ci].func === callback) { - callbackList.splice(ci, 1); - } - } - } - - // Remove all callbacks if there isn't a specified callback or there is no callbacks left - if (!callback || callbackList.length === 0) { - delete eventMap[name]; - removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture); - } - } - } - } else { - // All events for a specific element - for (name in eventMap) { - callbackList = eventMap[name]; - removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture); - } - - eventMap = {}; - } - - // Check if object is empty, if it isn't then we won't remove the expando map - for (name in eventMap) { - return self; - } - - // Delete event object - delete events[id]; - - // Remove expando from target - try { - // IE will fail here since it can't delete properties from window - delete target[expando]; - } catch (ex) { - // IE will set it to null - target[expando] = null; - } - } - - return self; - }; - - /** - * Fires the specified event on the specified target. - * - * @method fire - * @param {Object} target Target node/window or custom object. - * @param {String} name Event name to fire. - * @param {Object} args Optional arguments to send to the observers. - * @return {EventUtils} Event utils instance. - */ - self.fire = function(target, name, args) { - var id; - - // Don't bind to text nodes or comments - if (!target || target.nodeType === 3 || target.nodeType === 8) { - return self; - } - - // Build event object by patching the args - args = fix(null, args); - args.type = name; - args.target = target; - - do { - // Found an expando that means there is listeners to execute - id = target[expando]; - if (id) { - executeHandlers(args, id); - } - - // Walk up the DOM - target = target.parentNode || target.ownerDocument || target.defaultView || target.parentWindow; - } while (target && !args.isPropagationStopped()); - - return self; - }; - - /** - * Removes all bound event listeners for the specified target. This will also remove any bound - * listeners to child nodes within that target. - * - * @method clean - * @param {Object} target Target node/window object. - * @return {EventUtils} Event utils instance. - */ - self.clean = function(target) { - var i, children, unbind = self.unbind; - - // Don't bind to text nodes or comments - if (!target || target.nodeType === 3 || target.nodeType === 8) { - return self; - } - - // Unbind any element on the specificed target - if (target[expando]) { - unbind(target); - } - - // Target doesn't have getElementsByTagName it's probably a window object then use it's document to find the children - if (!target.getElementsByTagName) { - target = target.document; - } - - // Remove events from each child element - if (target && target.getElementsByTagName) { - unbind(target); - - children = target.getElementsByTagName('*'); - i = children.length; - while (i--) { - target = children[i]; - - if (target[expando]) { - unbind(target); - } - } - } - - return self; - }; - - /** - * Destroys the event object. Call this on IE to remove memory leaks. - */ - self.destory = function() { - events = {}; - }; - - // Legacy function for canceling events - self.cancel = function(e) { - if (e) { - e.preventDefault(); - e.stopImmediatePropagation(); - } - - return false; - }; - } - - EventUtils.Event = new EventUtils(); - EventUtils.Event.bind(window, 'ready', function() {}); - - return EventUtils; -}); \ No newline at end of file diff --git a/lib/tinymce/js/tinymce/classes/dom/Range.js b/lib/tinymce/js/tinymce/classes/dom/Range.js deleted file mode 100644 index 5fb52ea7..00000000 --- a/lib/tinymce/js/tinymce/classes/dom/Range.js +++ /dev/null @@ -1,774 +0,0 @@ -/** - * Range.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -define("tinymce/dom/Range", [ - "tinymce/util/Tools" -], function(Tools) { - // Range constructor - function Range(dom) { - var t = this, - doc = dom.doc, - EXTRACT = 0, - CLONE = 1, - DELETE = 2, - TRUE = true, - FALSE = false, - START_OFFSET = 'startOffset', - START_CONTAINER = 'startContainer', - END_CONTAINER = 'endContainer', - END_OFFSET = 'endOffset', - extend = Tools.extend, - nodeIndex = dom.nodeIndex; - - function createDocumentFragment() { - return doc.createDocumentFragment(); - } - - function setStart(n, o) { - _setEndPoint(TRUE, n, o); - } - - function setEnd(n, o) { - _setEndPoint(FALSE, n, o); - } - - function setStartBefore(n) { - setStart(n.parentNode, nodeIndex(n)); - } - - function setStartAfter(n) { - setStart(n.parentNode, nodeIndex(n) + 1); - } - - function setEndBefore(n) { - setEnd(n.parentNode, nodeIndex(n)); - } - - function setEndAfter(n) { - setEnd(n.parentNode, nodeIndex(n) + 1); - } - - function collapse(ts) { - if (ts) { - t[END_CONTAINER] = t[START_CONTAINER]; - t[END_OFFSET] = t[START_OFFSET]; - } else { - t[START_CONTAINER] = t[END_CONTAINER]; - t[START_OFFSET] = t[END_OFFSET]; - } - - t.collapsed = TRUE; - } - - function selectNode(n) { - setStartBefore(n); - setEndAfter(n); - } - - function selectNodeContents(n) { - setStart(n, 0); - setEnd(n, n.nodeType === 1 ? n.childNodes.length : n.nodeValue.length); - } - - function compareBoundaryPoints(h, r) { - var sc = t[START_CONTAINER], so = t[START_OFFSET], ec = t[END_CONTAINER], eo = t[END_OFFSET], - rsc = r.startContainer, rso = r.startOffset, rec = r.endContainer, reo = r.endOffset; - - // Check START_TO_START - if (h === 0) { - return _compareBoundaryPoints(sc, so, rsc, rso); - } - - // Check START_TO_END - if (h === 1) { - return _compareBoundaryPoints(ec, eo, rsc, rso); - } - - // Check END_TO_END - if (h === 2) { - return _compareBoundaryPoints(ec, eo, rec, reo); - } - - // Check END_TO_START - if (h === 3) { - return _compareBoundaryPoints(sc, so, rec, reo); - } - } - - function deleteContents() { - _traverse(DELETE); - } - - function extractContents() { - return _traverse(EXTRACT); - } - - function cloneContents() { - return _traverse(CLONE); - } - - function insertNode(n) { - var startContainer = this[START_CONTAINER], - startOffset = this[START_OFFSET], nn, o; - - // Node is TEXT_NODE or CDATA - if ((startContainer.nodeType === 3 || startContainer.nodeType === 4) && startContainer.nodeValue) { - if (!startOffset) { - // At the start of text - startContainer.parentNode.insertBefore(n, startContainer); - } else if (startOffset >= startContainer.nodeValue.length) { - // At the end of text - dom.insertAfter(n, startContainer); - } else { - // Middle, need to split - nn = startContainer.splitText(startOffset); - startContainer.parentNode.insertBefore(n, nn); - } - } else { - // Insert element node - if (startContainer.childNodes.length > 0) { - o = startContainer.childNodes[startOffset]; - } - - if (o) { - startContainer.insertBefore(n, o); - } else { - startContainer.appendChild(n); - } - } - } - - function surroundContents(n) { - var f = t.extractContents(); - - t.insertNode(n); - n.appendChild(f); - t.selectNode(n); - } - - function cloneRange() { - return extend(new Range(dom), { - startContainer: t[START_CONTAINER], - startOffset: t[START_OFFSET], - endContainer: t[END_CONTAINER], - endOffset: t[END_OFFSET], - collapsed: t.collapsed, - commonAncestorContainer: t.commonAncestorContainer - }); - } - - // Private methods - - function _getSelectedNode(container, offset) { - var child; - - if (container.nodeType == 3 /* TEXT_NODE */) { - return container; - } - - if (offset < 0) { - return container; - } - - child = container.firstChild; - while (child && offset > 0) { - --offset; - child = child.nextSibling; - } - - if (child) { - return child; - } - - return container; - } - - function _isCollapsed() { - return (t[START_CONTAINER] == t[END_CONTAINER] && t[START_OFFSET] == t[END_OFFSET]); - } - - function _compareBoundaryPoints(containerA, offsetA, containerB, offsetB) { - var c, offsetC, n, cmnRoot, childA, childB; - - // In the first case the boundary-points have the same container. A is before B - // if its offset is less than the offset of B, A is equal to B if its offset is - // equal to the offset of B, and A is after B if its offset is greater than the - // offset of B. - if (containerA == containerB) { - if (offsetA == offsetB) { - return 0; // equal - } - - if (offsetA < offsetB) { - return -1; // before - } - - return 1; // after - } - - // In the second case a child node C of the container of A is an ancestor - // container of B. In this case, A is before B if the offset of A is less than or - // equal to the index of the child node C and A is after B otherwise. - c = containerB; - while (c && c.parentNode != containerA) { - c = c.parentNode; - } - - if (c) { - offsetC = 0; - n = containerA.firstChild; - - while (n != c && offsetC < offsetA) { - offsetC++; - n = n.nextSibling; - } - - if (offsetA <= offsetC) { - return -1; // before - } - - return 1; // after - } - - // In the third case a child node C of the container of B is an ancestor container - // of A. In this case, A is before B if the index of the child node C is less than - // the offset of B and A is after B otherwise. - c = containerA; - while (c && c.parentNode != containerB) { - c = c.parentNode; - } - - if (c) { - offsetC = 0; - n = containerB.firstChild; - - while (n != c && offsetC < offsetB) { - offsetC++; - n = n.nextSibling; - } - - if (offsetC < offsetB) { - return -1; // before - } - - return 1; // after - } - - // In the fourth case, none of three other cases hold: the containers of A and B - // are siblings or descendants of sibling nodes. In this case, A is before B if - // the container of A is before the container of B in a pre-order traversal of the - // Ranges' context tree and A is after B otherwise. - cmnRoot = dom.findCommonAncestor(containerA, containerB); - childA = containerA; - - while (childA && childA.parentNode != cmnRoot) { - childA = childA.parentNode; - } - - if (!childA) { - childA = cmnRoot; - } - - childB = containerB; - while (childB && childB.parentNode != cmnRoot) { - childB = childB.parentNode; - } - - if (!childB) { - childB = cmnRoot; - } - - if (childA == childB) { - return 0; // equal - } - - n = cmnRoot.firstChild; - while (n) { - if (n == childA) { - return -1; // before - } - - if (n == childB) { - return 1; // after - } - - n = n.nextSibling; - } - } - - function _setEndPoint(st, n, o) { - var ec, sc; - - if (st) { - t[START_CONTAINER] = n; - t[START_OFFSET] = o; - } else { - t[END_CONTAINER] = n; - t[END_OFFSET] = o; - } - - // If one boundary-point of a Range is set to have a root container - // other than the current one for the Range, the Range is collapsed to - // the new position. This enforces the restriction that both boundary- - // points of a Range must have the same root container. - ec = t[END_CONTAINER]; - while (ec.parentNode) { - ec = ec.parentNode; - } - - sc = t[START_CONTAINER]; - while (sc.parentNode) { - sc = sc.parentNode; - } - - if (sc == ec) { - // The start position of a Range is guaranteed to never be after the - // end position. To enforce this restriction, if the start is set to - // be at a position after the end, the Range is collapsed to that - // position. - if (_compareBoundaryPoints(t[START_CONTAINER], t[START_OFFSET], t[END_CONTAINER], t[END_OFFSET]) > 0) { - t.collapse(st); - } - } else { - t.collapse(st); - } - - t.collapsed = _isCollapsed(); - t.commonAncestorContainer = dom.findCommonAncestor(t[START_CONTAINER], t[END_CONTAINER]); - } - - function _traverse(how) { - var c, endContainerDepth = 0, startContainerDepth = 0, p, depthDiff, startNode, endNode, sp, ep; - - if (t[START_CONTAINER] == t[END_CONTAINER]) { - return _traverseSameContainer(how); - } - - for (c = t[END_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) { - if (p == t[START_CONTAINER]) { - return _traverseCommonStartContainer(c, how); - } - - ++endContainerDepth; - } - - for (c = t[START_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) { - if (p == t[END_CONTAINER]) { - return _traverseCommonEndContainer(c, how); - } - - ++startContainerDepth; - } - - depthDiff = startContainerDepth - endContainerDepth; - - startNode = t[START_CONTAINER]; - while (depthDiff > 0) { - startNode = startNode.parentNode; - depthDiff--; - } - - endNode = t[END_CONTAINER]; - while (depthDiff < 0) { - endNode = endNode.parentNode; - depthDiff++; - } - - // ascend the ancestor hierarchy until we have a common parent. - for (sp = startNode.parentNode, ep = endNode.parentNode; sp != ep; sp = sp.parentNode, ep = ep.parentNode) { - startNode = sp; - endNode = ep; - } - - return _traverseCommonAncestors(startNode, endNode, how); - } - - function _traverseSameContainer(how) { - var frag, s, sub, n, cnt, sibling, xferNode, start, len; - - if (how != DELETE) { - frag = createDocumentFragment(); - } - - // If selection is empty, just return the fragment - if (t[START_OFFSET] == t[END_OFFSET]) { - return frag; - } - - // Text node needs special case handling - if (t[START_CONTAINER].nodeType == 3 /* TEXT_NODE */) { - // get the substring - s = t[START_CONTAINER].nodeValue; - sub = s.substring(t[START_OFFSET], t[END_OFFSET]); - - // set the original text node to its new value - if (how != CLONE) { - n = t[START_CONTAINER]; - start = t[START_OFFSET]; - len = t[END_OFFSET] - t[START_OFFSET]; - - if (start === 0 && len >= n.nodeValue.length - 1) { - n.parentNode.removeChild(n); - } else { - n.deleteData(start, len); - } - - // Nothing is partially selected, so collapse to start point - t.collapse(TRUE); - } - - if (how == DELETE) { - return; - } - - if (sub.length > 0) { - frag.appendChild(doc.createTextNode(sub)); - } - - return frag; - } - - // Copy nodes between the start/end offsets. - n = _getSelectedNode(t[START_CONTAINER], t[START_OFFSET]); - cnt = t[END_OFFSET] - t[START_OFFSET]; - - while (n && cnt > 0) { - sibling = n.nextSibling; - xferNode = _traverseFullySelected(n, how); - - if (frag) { - frag.appendChild(xferNode); - } - - --cnt; - n = sibling; - } - - // Nothing is partially selected, so collapse to start point - if (how != CLONE) { - t.collapse(TRUE); - } - - return frag; - } - - function _traverseCommonStartContainer(endAncestor, how) { - var frag, n, endIdx, cnt, sibling, xferNode; - - if (how != DELETE) { - frag = createDocumentFragment(); - } - - n = _traverseRightBoundary(endAncestor, how); - - if (frag) { - frag.appendChild(n); - } - - endIdx = nodeIndex(endAncestor); - cnt = endIdx - t[START_OFFSET]; - - if (cnt <= 0) { - // Collapse to just before the endAncestor, which - // is partially selected. - if (how != CLONE) { - t.setEndBefore(endAncestor); - t.collapse(FALSE); - } - - return frag; - } - - n = endAncestor.previousSibling; - while (cnt > 0) { - sibling = n.previousSibling; - xferNode = _traverseFullySelected(n, how); - - if (frag) { - frag.insertBefore(xferNode, frag.firstChild); - } - - --cnt; - n = sibling; - } - - // Collapse to just before the endAncestor, which - // is partially selected. - if (how != CLONE) { - t.setEndBefore(endAncestor); - t.collapse(FALSE); - } - - return frag; - } - - function _traverseCommonEndContainer(startAncestor, how) { - var frag, startIdx, n, cnt, sibling, xferNode; - - if (how != DELETE) { - frag = createDocumentFragment(); - } - - n = _traverseLeftBoundary(startAncestor, how); - if (frag) { - frag.appendChild(n); - } - - startIdx = nodeIndex(startAncestor); - ++startIdx; // Because we already traversed it - - cnt = t[END_OFFSET] - startIdx; - n = startAncestor.nextSibling; - while (n && cnt > 0) { - sibling = n.nextSibling; - xferNode = _traverseFullySelected(n, how); - - if (frag) { - frag.appendChild(xferNode); - } - - --cnt; - n = sibling; - } - - if (how != CLONE) { - t.setStartAfter(startAncestor); - t.collapse(TRUE); - } - - return frag; - } - - function _traverseCommonAncestors(startAncestor, endAncestor, how) { - var n, frag, commonParent, startOffset, endOffset, cnt, sibling, nextSibling; - - if (how != DELETE) { - frag = createDocumentFragment(); - } - - n = _traverseLeftBoundary(startAncestor, how); - if (frag) { - frag.appendChild(n); - } - - commonParent = startAncestor.parentNode; - startOffset = nodeIndex(startAncestor); - endOffset = nodeIndex(endAncestor); - ++startOffset; - - cnt = endOffset - startOffset; - sibling = startAncestor.nextSibling; - - while (cnt > 0) { - nextSibling = sibling.nextSibling; - n = _traverseFullySelected(sibling, how); - - if (frag) { - frag.appendChild(n); - } - - sibling = nextSibling; - --cnt; - } - - n = _traverseRightBoundary(endAncestor, how); - - if (frag) { - frag.appendChild(n); - } - - if (how != CLONE) { - t.setStartAfter(startAncestor); - t.collapse(TRUE); - } - - return frag; - } - - function _traverseRightBoundary(root, how) { - var next = _getSelectedNode(t[END_CONTAINER], t[END_OFFSET] - 1), parent, clonedParent; - var prevSibling, clonedChild, clonedGrandParent, isFullySelected = next != t[END_CONTAINER]; - - if (next == root) { - return _traverseNode(next, isFullySelected, FALSE, how); - } - - parent = next.parentNode; - clonedParent = _traverseNode(parent, FALSE, FALSE, how); - - while (parent) { - while (next) { - prevSibling = next.previousSibling; - clonedChild = _traverseNode(next, isFullySelected, FALSE, how); - - if (how != DELETE) { - clonedParent.insertBefore(clonedChild, clonedParent.firstChild); - } - - isFullySelected = TRUE; - next = prevSibling; - } - - if (parent == root) { - return clonedParent; - } - - next = parent.previousSibling; - parent = parent.parentNode; - - clonedGrandParent = _traverseNode(parent, FALSE, FALSE, how); - - if (how != DELETE) { - clonedGrandParent.appendChild(clonedParent); - } - - clonedParent = clonedGrandParent; - } - } - - function _traverseLeftBoundary(root, how) { - var next = _getSelectedNode(t[START_CONTAINER], t[START_OFFSET]), isFullySelected = next != t[START_CONTAINER]; - var parent, clonedParent, nextSibling, clonedChild, clonedGrandParent; - - if (next == root) { - return _traverseNode(next, isFullySelected, TRUE, how); - } - - parent = next.parentNode; - clonedParent = _traverseNode(parent, FALSE, TRUE, how); - - while (parent) { - while (next) { - nextSibling = next.nextSibling; - clonedChild = _traverseNode(next, isFullySelected, TRUE, how); - - if (how != DELETE) { - clonedParent.appendChild(clonedChild); - } - - isFullySelected = TRUE; - next = nextSibling; - } - - if (parent == root) { - return clonedParent; - } - - next = parent.nextSibling; - parent = parent.parentNode; - - clonedGrandParent = _traverseNode(parent, FALSE, TRUE, how); - - if (how != DELETE) { - clonedGrandParent.appendChild(clonedParent); - } - - clonedParent = clonedGrandParent; - } - } - - function _traverseNode(n, isFullySelected, isLeft, how) { - var txtValue, newNodeValue, oldNodeValue, offset, newNode; - - if (isFullySelected) { - return _traverseFullySelected(n, how); - } - - if (n.nodeType == 3 /* TEXT_NODE */) { - txtValue = n.nodeValue; - - if (isLeft) { - offset = t[START_OFFSET]; - newNodeValue = txtValue.substring(offset); - oldNodeValue = txtValue.substring(0, offset); - } else { - offset = t[END_OFFSET]; - newNodeValue = txtValue.substring(0, offset); - oldNodeValue = txtValue.substring(offset); - } - - if (how != CLONE) { - n.nodeValue = oldNodeValue; - } - - if (how == DELETE) { - return; - } - - newNode = dom.clone(n, FALSE); - newNode.nodeValue = newNodeValue; - - return newNode; - } - - if (how == DELETE) { - return; - } - - return dom.clone(n, FALSE); - } - - function _traverseFullySelected(n, how) { - if (how != DELETE) { - return how == CLONE ? dom.clone(n, TRUE) : n; - } - - n.parentNode.removeChild(n); - } - - function toStringIE() { - return dom.create('body', null, cloneContents()).outerText; - } - - extend(t, { - // Inital states - startContainer: doc, - startOffset: 0, - endContainer: doc, - endOffset: 0, - collapsed: TRUE, - commonAncestorContainer: doc, - - // Range constants - START_TO_START: 0, - START_TO_END: 1, - END_TO_END: 2, - END_TO_START: 3, - - // Public methods - setStart: setStart, - setEnd: setEnd, - setStartBefore: setStartBefore, - setStartAfter: setStartAfter, - setEndBefore: setEndBefore, - setEndAfter: setEndAfter, - collapse: collapse, - selectNode: selectNode, - selectNodeContents: selectNodeContents, - compareBoundaryPoints: compareBoundaryPoints, - deleteContents: deleteContents, - extractContents: extractContents, - cloneContents: cloneContents, - insertNode: insertNode, - surroundContents: surroundContents, - cloneRange: cloneRange, - toStringIE: toStringIE - }); - - return t; - } - - // Older IE versions doesn't let you override toString by it's constructor so we have to stick it in the prototype - Range.prototype.toString = function() { - return this.toStringIE(); - }; - - return Range; -}); diff --git a/lib/tinymce/js/tinymce/classes/dom/RangeUtils.js b/lib/tinymce/js/tinymce/classes/dom/RangeUtils.js deleted file mode 100644 index d99339fb..00000000 --- a/lib/tinymce/js/tinymce/classes/dom/RangeUtils.js +++ /dev/null @@ -1,267 +0,0 @@ -/** - * Range.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -define("tinymce/dom/RangeUtils", [ - "tinymce/util/Tools" -], function(Tools) { - var each = Tools.each; - - function RangeUtils(dom) { - /** - * Walks the specified range like object and executes the callback for each sibling collection it finds. - * - * @param {Object} rng Range like object. - * @param {function} callback Callback function to execute for each sibling collection. - */ - this.walk = function(rng, callback) { - var startContainer = rng.startContainer, - startOffset = rng.startOffset, - endContainer = rng.endContainer, - endOffset = rng.endOffset, - ancestor, startPoint, - endPoint, node, parent, siblings, nodes; - - // Handle table cell selection the table plugin enables - // you to fake select table cells and perform formatting actions on them - nodes = dom.select('td.mce-item-selected,th.mce-item-selected'); - if (nodes.length > 0) { - each(nodes, function(node) { - callback([node]); - }); - - return; - } - - /** - * Excludes start/end text node if they are out side the range - * - * @private - * @param {Array} nodes Nodes to exclude items from. - * @return {Array} Array with nodes excluding the start/end container if needed. - */ - function exclude(nodes) { - var node; - - // First node is excluded - node = nodes[0]; - if (node.nodeType === 3 && node === startContainer && startOffset >= node.nodeValue.length) { - nodes.splice(0, 1); - } - - // Last node is excluded - node = nodes[nodes.length - 1]; - if (endOffset === 0 && nodes.length > 0 && node === endContainer && node.nodeType === 3) { - nodes.splice(nodes.length - 1, 1); - } - - return nodes; - } - - /** - * Collects siblings - * - * @private - * @param {Node} node Node to collect siblings from. - * @param {String} name Name of the sibling to check for. - * @return {Array} Array of collected siblings. - */ - function collectSiblings(node, name, end_node) { - var siblings = []; - - for (; node && node != end_node; node = node[name]) { - siblings.push(node); - } - - return siblings; - } - - /** - * Find an end point this is the node just before the common ancestor root. - * - * @private - * @param {Node} node Node to start at. - * @param {Node} root Root/ancestor element to stop just before. - * @return {Node} Node just before the root element. - */ - function findEndPoint(node, root) { - do { - if (node.parentNode == root) { - return node; - } - - node = node.parentNode; - } while(node); - } - - function walkBoundary(start_node, end_node, next) { - var siblingName = next ? 'nextSibling' : 'previousSibling'; - - for (node = start_node, parent = node.parentNode; node && node != end_node; node = parent) { - parent = node.parentNode; - siblings = collectSiblings(node == start_node ? node : node[siblingName], siblingName); - - if (siblings.length) { - if (!next) { - siblings.reverse(); - } - - callback(exclude(siblings)); - } - } - } - - // If index based start position then resolve it - if (startContainer.nodeType == 1 && startContainer.hasChildNodes()) { - startContainer = startContainer.childNodes[startOffset]; - } - - // If index based end position then resolve it - if (endContainer.nodeType == 1 && endContainer.hasChildNodes()) { - endContainer = endContainer.childNodes[Math.min(endOffset - 1, endContainer.childNodes.length - 1)]; - } - - // Same container - if (startContainer == endContainer) { - return callback(exclude([startContainer])); - } - - // Find common ancestor and end points - ancestor = dom.findCommonAncestor(startContainer, endContainer); - - // Process left side - for (node = startContainer; node; node = node.parentNode) { - if (node === endContainer) { - return walkBoundary(startContainer, ancestor, true); - } - - if (node === ancestor) { - break; - } - } - - // Process right side - for (node = endContainer; node; node = node.parentNode) { - if (node === startContainer) { - return walkBoundary(endContainer, ancestor); - } - - if (node === ancestor) { - break; - } - } - - // Find start/end point - startPoint = findEndPoint(startContainer, ancestor) || startContainer; - endPoint = findEndPoint(endContainer, ancestor) || endContainer; - - // Walk left leaf - walkBoundary(startContainer, startPoint, true); - - // Walk the middle from start to end point - siblings = collectSiblings( - startPoint == startContainer ? startPoint : startPoint.nextSibling, - 'nextSibling', - endPoint == endContainer ? endPoint.nextSibling : endPoint - ); - - if (siblings.length) { - callback(exclude(siblings)); - } - - // Walk right leaf - walkBoundary(endContainer, endPoint); - }; - - /** - * Splits the specified range at it's start/end points. - * - * @param {Range/RangeObject} rng Range to split. - * @return {Object} Range position object. - */ - this.split = function(rng) { - var startContainer = rng.startContainer, - startOffset = rng.startOffset, - endContainer = rng.endContainer, - endOffset = rng.endOffset; - - function splitText(node, offset) { - return node.splitText(offset); - } - - // Handle single text node - if (startContainer == endContainer && startContainer.nodeType == 3) { - if (startOffset > 0 && startOffset < startContainer.nodeValue.length) { - endContainer = splitText(startContainer, startOffset); - startContainer = endContainer.previousSibling; - - if (endOffset > startOffset) { - endOffset = endOffset - startOffset; - startContainer = endContainer = splitText(endContainer, endOffset).previousSibling; - endOffset = endContainer.nodeValue.length; - startOffset = 0; - } else { - endOffset = 0; - } - } - } else { - // Split startContainer text node if needed - if (startContainer.nodeType == 3 && startOffset > 0 && startOffset < startContainer.nodeValue.length) { - startContainer = splitText(startContainer, startOffset); - startOffset = 0; - } - - // Split endContainer text node if needed - if (endContainer.nodeType == 3 && endOffset > 0 && endOffset < endContainer.nodeValue.length) { - endContainer = splitText(endContainer, endOffset).previousSibling; - endOffset = endContainer.nodeValue.length; - } - } - - return { - startContainer: startContainer, - startOffset: startOffset, - endContainer: endContainer, - endOffset: endOffset - }; - }; - } - - /** - * Compares two ranges and checks if they are equal. - * - * @static - * @param {DOMRange} rng1 First range to compare. - * @param {DOMRange} rng2 First range to compare. - * @return {Boolean} true/false if the ranges are equal. - */ - RangeUtils.compareRanges = function(rng1, rng2) { - if (rng1 && rng2) { - // Compare native IE ranges - if (rng1.item || rng1.duplicate) { - // Both are control ranges and the selected element matches - if (rng1.item && rng2.item && rng1.item(0) === rng2.item(0)) { - return true; - } - - // Both are text ranges and the range matches - if (rng1.isEqual && rng2.isEqual && rng2.isEqual(rng1)) { - return true; - } - } else { - // Compare w3c ranges - return rng1.startContainer == rng2.startContainer && rng1.startOffset == rng2.startOffset; - } - } - - return false; - }; - - return RangeUtils; -}); diff --git a/lib/tinymce/js/tinymce/classes/dom/ScriptLoader.js b/lib/tinymce/js/tinymce/classes/dom/ScriptLoader.js deleted file mode 100644 index 3294cdc9..00000000 --- a/lib/tinymce/js/tinymce/classes/dom/ScriptLoader.js +++ /dev/null @@ -1,249 +0,0 @@ -/** - * ScriptLoader.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -/*globals console*/ - -/** - * This class handles asynchronous/synchronous loading of JavaScript files it will execute callbacks - * when various items gets loaded. This class is useful to load external JavaScript files. - * - * @class tinymce.dom.ScriptLoader - * @example - * // Load a script from a specific URL using the global script loader - * tinymce.ScriptLoader.load('somescript.js'); - * - * // Load a script using a unique instance of the script loader - * var scriptLoader = new tinymce.dom.ScriptLoader(); - * - * scriptLoader.load('somescript.js'); - * - * // Load multiple scripts - * var scriptLoader = new tinymce.dom.ScriptLoader(); - * - * scriptLoader.add('somescript1.js'); - * scriptLoader.add('somescript2.js'); - * scriptLoader.add('somescript3.js'); - * - * scriptLoader.loadQueue(function() { - * alert('All scripts are now loaded.'); - * }); - */ -define("tinymce/dom/ScriptLoader", [ - "tinymce/dom/DOMUtils", - "tinymce/util/Tools" -], function(DOMUtils, Tools) { - var DOM = DOMUtils.DOM; - var each = Tools.each, grep = Tools.grep; - - function ScriptLoader() { - var QUEUED = 0, - LOADING = 1, - LOADED = 2, - states = {}, - queue = [], - scriptLoadedCallbacks = {}, - queueLoadedCallbacks = [], - loading = 0, - undef; - - /** - * Loads a specific script directly without adding it to the load queue. - * - * @method load - * @param {String} url Absolute URL to script to add. - * @param {function} callback Optional callback function to execute ones this script gets loaded. - * @param {Object} scope Optional scope to execute callback in. - */ - function loadScript(url, callback) { - var dom = DOM, elm, id; - - // Execute callback when script is loaded - function done() { - dom.remove(id); - - if (elm) { - elm.onreadystatechange = elm.onload = elm = null; - } - - callback(); - } - - function error() { - // Report the error so it's easier for people to spot loading errors - if (typeof(console) !== "undefined" && console.log) { - console.log("Failed to load: " + url); - } - - // We can't mark it as done if there is a load error since - // A) We don't want to produce 404 errors on the server and - // B) the onerror event won't fire on all browsers. - // done(); - } - - id = dom.uniqueId(); - - // Create new script element - elm = document.createElement('script'); - elm.id = id; - elm.type = 'text/javascript'; - elm.src = url; - - elm.onload = done; - elm.onreadystatechange = function() { - if (/loaded|complete/.test(elm.readyState)) { - done(); - } - }; - - // Add onerror event will get fired on some browsers but not all of them - elm.onerror = error; - - // Add script to document - (document.getElementsByTagName('head')[0] || document.body).appendChild(elm); - } - - /** - * Returns true/false if a script has been loaded or not. - * - * @method isDone - * @param {String} url URL to check for. - * @return [Boolean} true/false if the URL is loaded. - */ - this.isDone = function(url) { - return states[url] == LOADED; - }; - - /** - * Marks a specific script to be loaded. This can be useful if a script got loaded outside - * the script loader or to skip it from loading some script. - * - * @method markDone - * @param {string} u Absolute URL to the script to mark as loaded. - */ - this.markDone = function(url) { - states[url] = LOADED; - }; - - /** - * Adds a specific script to the load queue of the script loader. - * - * @method add - * @param {String} url Absolute URL to script to add. - * @param {function} callback Optional callback function to execute ones this script gets loaded. - * @param {Object} scope Optional scope to execute callback in. - */ - this.add = this.load = function(url, callback, scope) { - var state = states[url]; - - // Add url to load queue - if (state == undef) { - queue.push(url); - states[url] = QUEUED; - } - - if (callback) { - // Store away callback for later execution - if (!scriptLoadedCallbacks[url]) { - scriptLoadedCallbacks[url] = []; - } - - scriptLoadedCallbacks[url].push({ - func: callback, - scope: scope || this - }); - } - }; - - /** - * Starts the loading of the queue. - * - * @method loadQueue - * @param {function} callback Optional callback to execute when all queued items are loaded. - * @param {Object} scope Optional scope to execute the callback in. - */ - this.loadQueue = function(callback, scope) { - this.loadScripts(queue, callback, scope); - }; - - /** - * Loads the specified queue of files and executes the callback ones they are loaded. - * This method is generally not used outside this class but it might be useful in some scenarios. - * - * @method loadScripts - * @param {Array} scripts Array of queue items to load. - * @param {function} callback Optional callback to execute ones all items are loaded. - * @param {Object} scope Optional scope to execute callback in. - */ - this.loadScripts = function(scripts, callback, scope) { - var loadScripts; - - function execScriptLoadedCallbacks(url) { - // Execute URL callback functions - each(scriptLoadedCallbacks[url], function(callback) { - callback.func.call(callback.scope); - }); - - scriptLoadedCallbacks[url] = undef; - } - - queueLoadedCallbacks.push({ - func: callback, - scope: scope || this - }); - - loadScripts = function() { - var loadingScripts = grep(scripts); - - // Current scripts has been handled - scripts.length = 0; - - // Load scripts that needs to be loaded - each(loadingScripts, function(url) { - // Script is already loaded then execute script callbacks directly - if (states[url] == LOADED) { - execScriptLoadedCallbacks(url); - return; - } - - // Is script not loading then start loading it - if (states[url] != LOADING) { - states[url] = LOADING; - loading++; - - loadScript(url, function() { - states[url] = LOADED; - loading--; - - execScriptLoadedCallbacks(url); - - // Load more scripts if they where added by the recently loaded script - loadScripts(); - }); - } - }); - - // No scripts are currently loading then execute all pending queue loaded callbacks - if (!loading) { - each(queueLoadedCallbacks, function(callback) { - callback.func.call(callback.scope); - }); - - queueLoadedCallbacks.length = 0; - } - }; - - loadScripts(); - }; - } - - ScriptLoader.ScriptLoader = new ScriptLoader(); - - return ScriptLoader; -}); diff --git a/lib/tinymce/js/tinymce/classes/dom/Selection.js b/lib/tinymce/js/tinymce/classes/dom/Selection.js deleted file mode 100644 index fee8305f..00000000 --- a/lib/tinymce/js/tinymce/classes/dom/Selection.js +++ /dev/null @@ -1,1314 +0,0 @@ -/** - * Selection.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -/** - * This class handles text and control selection it's an crossbrowser utility class. - * Consult the TinyMCE Wiki API for more details and examples on how to use this class. - * - * @class tinymce.dom.Selection - * @example - * // Getting the currently selected node for the active editor - * alert(tinymce.activeEditor.selection.getNode().nodeName); - */ -define("tinymce/dom/Selection", [ - "tinymce/dom/TreeWalker", - "tinymce/dom/TridentSelection", - "tinymce/dom/ControlSelection", - "tinymce/Env", - "tinymce/util/Tools" -], function(TreeWalker, TridentSelection, ControlSelection, Env, Tools) { - var each = Tools.each, grep = Tools.grep, trim = Tools.trim; - var isIE = Env.ie, isOpera = Env.opera; - - /** - * Constructs a new selection instance. - * - * @constructor - * @method Selection - * @param {tinymce.dom.DOMUtils} dom DOMUtils object reference. - * @param {Window} win Window to bind the selection object to. - * @param {tinymce.dom.Serializer} serializer DOM serialization class to use for getContent. - */ - function Selection(dom, win, serializer, editor) { - var self = this; - - self.dom = dom; - self.win = win; - self.serializer = serializer; - self.editor = editor; - - self.controlSelection = new ControlSelection(self, editor); - - editor.on('nodechange', function() { - var rng; - - // Use old style IE range since we want to restore control selections - if (editor.getDoc().selection) { - rng = editor.getDoc().selection.createRange(); - } else { - rng = self.getRng(); - } - - self.lastRng = rng; - }); - - // No W3C Range support - if (!self.win.getSelection) { - self.tridentSel = new TridentSelection(self); - } - } - - Selection.prototype = { - /** - * Move the selection cursor range to the specified node and offset. - * @param node Node to put the cursor in. - * @param offset Offset from the start of the node to put the cursor at. - */ - setCursorLocation: function(node, offset) { - var self = this, rng = self.dom.createRng(); - rng.setStart(node, offset); - rng.setEnd(node, offset); - self.setRng(rng); - self.collapse(false); - }, - - /** - * Returns the selected contents using the DOM serializer passed in to this class. - * - * @method getContent - * @param {Object} s Optional settings class with for example output format text or html. - * @return {String} Selected contents in for example HTML format. - * @example - * // Alerts the currently selected contents - * alert(tinymce.activeEditor.selection.getContent()); - * - * // Alerts the currently selected contents as plain text - * alert(tinymce.activeEditor.selection.getContent({format: 'text'})); - */ - getContent: function(args) { - var self = this, rng = self.getRng(), tmpElm = self.dom.create("body"); - var se = self.getSel(), whiteSpaceBefore, whiteSpaceAfter, fragment; - - args = args || {}; - whiteSpaceBefore = whiteSpaceAfter = ''; - args.get = true; - args.format = args.format || 'html'; - args.selection = true; - self.editor.fire('BeforeGetContent', args); - - if (args.format == 'text') { - return self.isCollapsed() ? '' : (rng.text || (se.toString ? se.toString() : '')); - } - - if (rng.cloneContents) { - fragment = rng.cloneContents(); - - if (fragment) { - tmpElm.appendChild(fragment); - } - } else if (rng.item !== undefined || rng.htmlText !== undefined) { - // IE will produce invalid markup if elements are present that - // it doesn't understand like custom elements or HTML5 elements. - // Adding a BR in front of the contents and then remoiving it seems to fix it though. - tmpElm.innerHTML = ']
- rng.moveToElementText(rng2.parentElement()); - if (rng.compareEndPoints('StartToEnd', rng2) === 0) { - rng2.move('character', -1); - } - - rng2.pasteHTML('' + chr + ''); - } - } catch (ex) { - // IE might throw unspecified error so lets ignore it - return null; - } - } else { - // Control selection - element = rng.item(0); - name = element.nodeName; - - return {name: name, index: findIndex(name, element)}; - } - } else { - element = t.getNode(); - name = element.nodeName; - if (name == 'IMG') { - return {name: name, index: findIndex(name, element)}; - } - - // W3C method - rng2 = normalizeTableCellSelection(rng.cloneRange()); - - // Insert end marker - if (!collapsed) { - rng2.collapse(false); - rng2.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_end', style: styles}, chr)); - } - - rng = normalizeTableCellSelection(rng); - rng.collapse(true); - rng.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_start', style: styles}, chr)); - } - - t.moveToBookmark({id: id, keep: 1}); - - return {id: id}; - }, - - /** - * Restores the selection to the specified bookmark. - * - * @method moveToBookmark - * @param {Object} bookmark Bookmark to restore selection from. - * @return {Boolean} true/false if it was successful or not. - * @example - * // Stores a bookmark of the current selection - * var bm = tinymce.activeEditor.selection.getBookmark(); - * - * tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content'); - * - * // Restore the selection bookmark - * tinymce.activeEditor.selection.moveToBookmark(bm); - */ - moveToBookmark: function(bookmark) { - var t = this, dom = t.dom, rng, root, startContainer, endContainer, startOffset, endOffset; - - function setEndPoint(start) { - var point = bookmark[start ? 'start' : 'end'], i, node, offset, children; - - if (point) { - offset = point[0]; - - // Find container node - for (node = root, i = point.length - 1; i >= 1; i--) { - children = node.childNodes; - - if (point[i] > children.length - 1) { - return; - } - - node = children[point[i]]; - } - - // Move text offset to best suitable location - if (node.nodeType === 3) { - offset = Math.min(point[0], node.nodeValue.length); - } - - // Move element offset to best suitable location - if (node.nodeType === 1) { - offset = Math.min(point[0], node.childNodes.length); - } - - // Set offset within container node - if (start) { - rng.setStart(node, offset); - } else { - rng.setEnd(node, offset); - } - } - - return true; - } - - function restoreEndPoint(suffix) { - var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev, keep = bookmark.keep; - - if (marker) { - node = marker.parentNode; - - if (suffix == 'start') { - if (!keep) { - idx = dom.nodeIndex(marker); - } else { - node = marker.firstChild; - idx = 1; - } - - startContainer = endContainer = node; - startOffset = endOffset = idx; - } else { - if (!keep) { - idx = dom.nodeIndex(marker); - } else { - node = marker.firstChild; - idx = 1; - } - - endContainer = node; - endOffset = idx; - } - - if (!keep) { - prev = marker.previousSibling; - next = marker.nextSibling; - - // Remove all marker text nodes - each(grep(marker.childNodes), function(node) { - if (node.nodeType == 3) { - node.nodeValue = node.nodeValue.replace(/\uFEFF/g, ''); - } - }); - - // Remove marker but keep children if for example contents where inserted into the marker - // Also remove duplicated instances of the marker for example by a - // split operation or by WebKit auto split on paste feature - while ((marker = dom.get(bookmark.id + '_' + suffix))) { - dom.remove(marker, 1); - } - - // If siblings are text nodes then merge them unless it's Opera since it some how removes the node - // and we are sniffing since adding a lot of detection code for a browser with 3% of the market - // isn't worth the effort. Sorry, Opera but it's just a fact - if (prev && next && prev.nodeType == next.nodeType && prev.nodeType == 3 && !isOpera) { - idx = prev.nodeValue.length; - prev.appendData(next.nodeValue); - dom.remove(next); - - if (suffix == 'start') { - startContainer = endContainer = prev; - startOffset = endOffset = idx; - } else { - endContainer = prev; - endOffset = idx; - } - } - } - } - } - - function addBogus(node) { - // Adds a bogus BR element for empty block elements - if (dom.isBlock(node) && !node.innerHTML && !isIE) { - node.innerHTML = 'x|
|
would become this:|
- sibling = startContainer.previousSibling; - if (sibling && !sibling.hasChildNodes() && dom.isBlock(sibling)) { - sibling.innerHTML = ''; - } else { - sibling = null; - } - - startContainer.innerHTML = ''; - ieRng.moveToElementText(startContainer.lastChild); - ieRng.select(); - dom.doc.selection.clear(); - startContainer.innerHTML = ''; - - if (sibling) { - sibling.innerHTML = ''; - } - return; - } else { - startOffset = dom.nodeIndex(startContainer); - startContainer = startContainer.parentNode; - } - } - - if (startOffset == endOffset - 1) { - try { - ctrlElm = startContainer.childNodes[startOffset]; - ctrlRng = body.createControlRange(); - ctrlRng.addElement(ctrlElm); - ctrlRng.select(); - - // Check if the range produced is on the correct element and is a control range - // On IE 8 it will select the parent contentEditable container if you select an inner element see: #5398 - nativeRng = selection.getRng(); - if (nativeRng.item && ctrlElm === nativeRng.item(0)) { - return; - } - } catch (ex) { - // Ignore - } - } - } - - // Set start/end point of selection - setEndPoint(true); - setEndPoint(); - - // Select the new range and scroll it into view - ieRng.select(); - }; - - // Expose range method - this.getRangeAt = getRange; - } - - return Selection; -}); diff --git a/lib/tinymce/js/tinymce/classes/html/DomParser.js b/lib/tinymce/js/tinymce/classes/html/DomParser.js deleted file mode 100644 index 1d5ee75f..00000000 --- a/lib/tinymce/js/tinymce/classes/html/DomParser.js +++ /dev/null @@ -1,752 +0,0 @@ -/** - * DomParser.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -/** - * This class parses HTML code into a DOM like structure of nodes it will remove redundant whitespace and make - * sure that the node tree is valid according to the specified schema. - * So for example:a
b
c will becomea
b
c
- * - * @example - * var parser = new tinymce.html.DomParser({validate: true}, schema); - * var rootNode = parser.parse('x
->x
- function trim(rootBlockNode) { - if (rootBlockNode) { - node = rootBlockNode.firstChild; - if (node && node.type == 3) { - node.value = node.value.replace(startWhiteSpaceRegExp, ''); - } - - node = rootBlockNode.lastChild; - if (node && node.type == 3) { - node.value = node.value.replace(endWhiteSpaceRegExp, ''); - } - } - } - - // Check if rootBlock is valid within rootNode for example if P is valid in H1 if H1 is the contentEditabe root - if (!schema.isValidChild(rootNode.name, rootBlockName.toLowerCase())) { - return; - } - - while (node) { - next = node.next; - - if (node.type == 3 || (node.type == 1 && node.name !== 'p' && - !blockElements[node.name] && !node.attr('data-mce-type'))) { - if (!rootBlockNode) { - // Create a new root block element - rootBlockNode = createNode(rootBlockName, 1); - rootNode.insert(rootBlockNode, node); - rootBlockNode.append(node); - } else { - rootBlockNode.append(node); - } - } else { - trim(rootBlockNode); - rootBlockNode = null; - } - - node = next; - } - - trim(rootBlockNode); - } - - function createNode(name, type) { - var node = new Node(name, type), list; - - if (name in nodeFilters) { - list = matchedNodes[name]; - - if (list) { - list.push(node); - } else { - matchedNodes[name] = [node]; - } - } - - return node; - } - - function removeWhitespaceBefore(node) { - var textNode, textVal, sibling; - - for (textNode = node.prev; textNode && textNode.type === 3; ) { - textVal = textNode.value.replace(endWhiteSpaceRegExp, ''); - - if (textVal.length > 0) { - textNode.value = textVal; - textNode = textNode.prev; - } else { - sibling = textNode.prev; - textNode.remove(); - textNode = sibling; - } - } - } - - function cloneAndExcludeBlocks(input) { - var name, output = {}; - - for (name in input) { - if (name !== 'li' && name != 'p') { - output[name] = input[name]; - } - } - - return output; - } - - parser = new SaxParser({ - validate: validate, - - // Exclude P and LI from DOM parsing since it's treated better by the DOM parser - self_closing_elements: cloneAndExcludeBlocks(schema.getSelfClosingElements()), - - cdata: function(text) { - node.append(createNode('#cdata', 4)).value = text; - }, - - text: function(text, raw) { - var textNode; - - // Trim all redundant whitespace on non white space elements - if (!isInWhiteSpacePreservedElement) { - text = text.replace(allWhiteSpaceRegExp, ' '); - - if (node.lastChild && blockElements[node.lastChild.name]) { - text = text.replace(startWhiteSpaceRegExp, ''); - } - } - - // Do we need to create the node - if (text.length !== 0) { - textNode = createNode('#text', 3); - textNode.raw = !!raw; - node.append(textNode).value = text; - } - }, - - comment: function(text) { - node.append(createNode('#comment', 8)).value = text; - }, - - pi: function(name, text) { - node.append(createNode(name, 7)).value = text; - removeWhitespaceBefore(node); - }, - - doctype: function(text) { - var newNode; - - newNode = node.append(createNode('#doctype', 10)); - newNode.value = text; - removeWhitespaceBefore(node); - }, - - start: function(name, attrs, empty) { - var newNode, attrFiltersLen, elementRule, attrName, parent; - - elementRule = validate ? schema.getElementRule(name) : {}; - if (elementRule) { - newNode = createNode(elementRule.outputName || name, 1); - newNode.attributes = attrs; - newNode.shortEnded = empty; - - node.append(newNode); - - // Check if node is valid child of the parent node is the child is - // unknown we don't collect it since it's probably a custom element - parent = children[node.name]; - if (parent && children[newNode.name] && !parent[newNode.name]) { - invalidChildren.push(newNode); - } - - attrFiltersLen = attributeFilters.length; - while (attrFiltersLen--) { - attrName = attributeFilters[attrFiltersLen].name; - - if (attrName in attrs.map) { - list = matchedAttributes[attrName]; - - if (list) { - list.push(newNode); - } else { - matchedAttributes[attrName] = [newNode]; - } - } - } - - // Trim whitespace before block - if (blockElements[name]) { - removeWhitespaceBefore(newNode); - } - - // Change current node if the element wasn't empty i.e nota
- lastParent = node; - while (parent.firstChild === lastParent && parent.lastChild === lastParent) { - lastParent = parent; - - if (blockElements[parent.name]) { - break; - } - - parent = parent.parent; - } - - if (lastParent === parent) { - textNode = new Node('#text', 3); - textNode.value = '\u00a0'; - node.replace(textNode); - } - } - } - }); - } - - // Force anchor names closed, unless the setting "allow_html_in_named_anchor" is explicitly included. - if (!settings.allow_html_in_named_anchor) { - self.addAttributeFilter('id,name', function(nodes) { - var i = nodes.length, sibling, prevSibling, parent, node; - - while (i--) { - node = nodes[i]; - if (node.name === 'a' && node.firstChild && !node.attr('href')) { - parent = node.parent; - - // Move children after current node - sibling = node.lastChild; - do { - prevSibling = sibling.prev; - parent.insert(sibling, node); - sibling = prevSibling; - } while (sibling); - } - } - }); - } - }; -}); diff --git a/lib/tinymce/js/tinymce/classes/html/Entities.js b/lib/tinymce/js/tinymce/classes/html/Entities.js deleted file mode 100644 index 7fbd8c4d..00000000 --- a/lib/tinymce/js/tinymce/classes/html/Entities.js +++ /dev/null @@ -1,261 +0,0 @@ -/** - * Entities.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -/*jshint bitwise:false */ - -/** - * Entity encoder class. - * - * @class tinymce.html.Entities - * @static - * @version 3.4 - */ -define("tinymce/html/Entities", [ - "tinymce/util/Tools" -], function(Tools) { - var makeMap = Tools.makeMap; - - var namedEntities, baseEntities, reverseEntities, - attrsCharsRegExp = /[&<>\"\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, - textCharsRegExp = /[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, - rawCharsRegExp = /[<>&\"\']/g, - entityRegExp = /&(#x|#)?([\w]+);/g, - asciiMap = { - 128: "\u20AC", 130: "\u201A", 131: "\u0192", 132: "\u201E", 133: "\u2026", 134: "\u2020", - 135: "\u2021", 136: "\u02C6", 137: "\u2030", 138: "\u0160", 139: "\u2039", 140: "\u0152", - 142: "\u017D", 145: "\u2018", 146: "\u2019", 147: "\u201C", 148: "\u201D", 149: "\u2022", - 150: "\u2013", 151: "\u2014", 152: "\u02DC", 153: "\u2122", 154: "\u0161", 155: "\u203A", - 156: "\u0153", 158: "\u017E", 159: "\u0178" - }; - - // Raw entities - baseEntities = { - '\"': '"', // Needs to be escaped since the YUI compressor would otherwise break the code - "'": ''', - '<': '<', - '>': '>', - '&': '&' - }; - - // Reverse lookup table for raw entities - reverseEntities = { - '<': '<', - '>': '>', - '&': '&', - '"': '"', - ''': "'" - }; - - // Decodes text by using the browser - function nativeDecode(text) { - var elm; - - elm = document.createElement("div"); - elm.innerHTML = text; - - return elm.textContent || elm.innerText || text; - } - - // Build a two way lookup table for the entities - function buildEntitiesLookup(items, radix) { - var i, chr, entity, lookup = {}; - - if (items) { - items = items.split(','); - radix = radix || 10; - - // Build entities lookup table - for (i = 0; i < items.length; i += 2) { - chr = String.fromCharCode(parseInt(items[i], radix)); - - // Only add non base entities - if (!baseEntities[chr]) { - entity = '&' + items[i + 1] + ';'; - lookup[chr] = entity; - lookup[entity] = chr; - } - } - - return lookup; - } - } - - // Unpack entities lookup where the numbers are in radix 32 to reduce the size - namedEntities = buildEntitiesLookup( - '50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' + - '5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' + - '5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' + - '5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' + - '68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' + - '6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' + - '6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' + - '75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' + - '7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' + - '7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' + - 'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' + - 'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' + - 't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' + - 'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' + - 'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' + - '81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' + - '8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' + - '8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' + - '8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' + - '8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,' + - 'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' + - 'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' + - 'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' + - '80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' + - '811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro', 32); - - var Entities = { - /** - * Encodes the specified string using raw entities. This means only the required XML base entities will be endoded. - * - * @method encodeRaw - * @param {String} text Text to encode. - * @param {Boolean} attr Optional flag to specify if the text is attribute contents. - * @return {String} Entity encoded text. - */ - encodeRaw: function(text, attr) { - return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { - return baseEntities[chr] || chr; - }); - }, - - /** - * Encoded the specified text with both the attributes and text entities. This function will produce larger text contents - * since it doesn't know if the context is within a attribute or text node. This was added for compatibility - * and is exposed as the DOMUtils.encode function. - * - * @method encodeAllRaw - * @param {String} text Text to encode. - * @return {String} Entity encoded text. - */ - encodeAllRaw: function(text) { - return ('' + text).replace(rawCharsRegExp, function(chr) { - return baseEntities[chr] || chr; - }); - }, - - /** - * Encodes the specified string using numeric entities. The core entities will be - * encoded as named ones but all non lower ascii characters will be encoded into numeric entities. - * - * @method encodeNumeric - * @param {String} text Text to encode. - * @param {Boolean} attr Optional flag to specify if the text is attribute contents. - * @return {String} Entity encoded text. - */ - encodeNumeric: function(text, attr) { - return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { - // Multi byte sequence convert it to a single entity - if (chr.length > 1) { - return '' + (((chr.charCodeAt(0) - 0xD800) * 0x400) + (chr.charCodeAt(1) - 0xDC00) + 0x10000) + ';'; - } - - return baseEntities[chr] || '' + chr.charCodeAt(0) + ';'; - }); - }, - - /** - * Encodes the specified string using named entities. The core entities will be encoded - * as named ones but all non lower ascii characters will be encoded into named entities. - * - * @method encodeNamed - * @param {String} text Text to encode. - * @param {Boolean} attr Optional flag to specify if the text is attribute contents. - * @param {Object} entities Optional parameter with entities to use. - * @return {String} Entity encoded text. - */ - encodeNamed: function(text, attr, entities) { - entities = entities || namedEntities; - - return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { - return baseEntities[chr] || entities[chr] || chr; - }); - }, - - /** - * Returns an encode function based on the name(s) and it's optional entities. - * - * @method getEncodeFunc - * @param {String} name Comma separated list of encoders for example named,numeric. - * @param {String} entities Optional parameter with entities to use instead of the built in set. - * @return {function} Encode function to be used. - */ - getEncodeFunc: function(name, entities) { - entities = buildEntitiesLookup(entities) || namedEntities; - - function encodeNamedAndNumeric(text, attr) { - return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { - return baseEntities[chr] || entities[chr] || '' + chr.charCodeAt(0) + ';' || chr; - }); - } - - function encodeCustomNamed(text, attr) { - return Entities.encodeNamed(text, attr, entities); - } - - // Replace + with , to be compatible with previous TinyMCE versions - name = makeMap(name.replace(/\+/g, ',')); - - // Named and numeric encoder - if (name.named && name.numeric) { - return encodeNamedAndNumeric; - } - - // Named encoder - if (name.named) { - // Custom names - if (entities) { - return encodeCustomNamed; - } - - return Entities.encodeNamed; - } - - // Numeric - if (name.numeric) { - return Entities.encodeNumeric; - } - - // Raw encoder - return Entities.encodeRaw; - }, - - /** - * Decodes the specified string, this will replace entities with raw UTF characters. - * - * @param {String} text Text to entity decode. - * @return {String} Entity decoded string. - */ - decode: function(text) { - return text.replace(entityRegExp, function(all, numeric, value) { - if (numeric) { - value = parseInt(value, numeric.length === 2 ? 16 : 10); - - // Support upper UTF - if (value > 0xFFFF) { - value -= 0x10000; - - return String.fromCharCode(0xD800 + (value >> 10), 0xDC00 + (value & 0x3FF)); - } else { - return asciiMap[value] || String.fromCharCode(value); - } - } - - return reverseEntities[all] || namedEntities[all] || nativeDecode(all); - }); - } - }; - - return Entities; -}); diff --git a/lib/tinymce/js/tinymce/classes/html/Node.js b/lib/tinymce/js/tinymce/classes/html/Node.js deleted file mode 100644 index acfc57a9..00000000 --- a/lib/tinymce/js/tinymce/classes/html/Node.js +++ /dev/null @@ -1,496 +0,0 @@ -/** - * Node.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -/** - * This class is a minimalistic implementation of a DOM like node used by the DomParser class. - * - * @example - * var node = new tinymce.html.Node('strong', 1); - * someRoot.append(node); - * - * @class tinymce.html.Node - * @version 3.4 - */ -define("tinymce/html/Node", [], function() { - var whiteSpaceRegExp = /^[ \t\r\n]*$/, typeLookup = { - '#text': 3, - '#comment': 8, - '#cdata': 4, - '#pi': 7, - '#doctype': 10, - '#document-fragment': 11 - }; - - // Walks the tree left/right - function walk(node, root_node, prev) { - var sibling, parent, startName = prev ? 'lastChild' : 'firstChild', siblingName = prev ? 'prev' : 'next'; - - // Walk into nodes if it has a start - if (node[startName]) { - return node[startName]; - } - - // Return the sibling if it has one - if (node !== root_node) { - sibling = node[siblingName]; - - if (sibling) { - return sibling; - } - - // Walk up the parents to look for siblings - for (parent = node.parent; parent && parent !== root_node; parent = parent.parent) { - sibling = parent[siblingName]; - - if (sibling) { - return sibling; - } - } - } - } - - /** - * Constructs a new Node instance. - * - * @constructor - * @method Node - * @param {String} name Name of the node type. - * @param {Number} type Numeric type representing the node. - */ - function Node(name, type) { - this.name = name; - this.type = type; - - if (type === 1) { - this.attributes = []; - this.attributes.map = {}; - } - } - - Node.prototype = { - /** - * Replaces the current node with the specified one. - * - * @example - * someNode.replace(someNewNode); - * - * @method replace - * @param {tinymce.html.Node} node Node to replace the current node with. - * @return {tinymce.html.Node} The old node that got replaced. - */ - replace: function(node) { - var self = this; - - if (node.parent) { - node.remove(); - } - - self.insert(node, self); - self.remove(); - - return self; - }, - - /** - * Gets/sets or removes an attribute by name. - * - * @example - * someNode.attr("name", "value"); // Sets an attribute - * console.log(someNode.attr("name")); // Gets an attribute - * someNode.attr("name", null); // Removes an attribute - * - * @method attr - * @param {String} name Attribute name to set or get. - * @param {String} value Optional value to set. - * @return {String/tinymce.html.Node} String or undefined on a get operation or the current node on a set operation. - */ - attr: function(name, value) { - var self = this, attrs, i, undef; - - if (typeof name !== "string") { - for (i in name) { - self.attr(i, name[i]); - } - - return self; - } - - if ((attrs = self.attributes)) { - if (value !== undef) { - // Remove attribute - if (value === null) { - if (name in attrs.map) { - delete attrs.map[name]; - - i = attrs.length; - while (i--) { - if (attrs[i].name === name) { - attrs = attrs.splice(i, 1); - return self; - } - } - } - - return self; - } - - // Set attribute - if (name in attrs.map) { - // Set attribute - i = attrs.length; - while (i--) { - if (attrs[i].name === name) { - attrs[i].value = value; - break; - } - } - } else { - attrs.push({name: name, value: value}); - } - - attrs.map[name] = value; - - return self; - } else { - return attrs.map[name]; - } - } - }, - - /** - * Does a shallow clones the node into a new node. It will also exclude id attributes since - * there should only be one id per document. - * - * @example - * var clonedNode = node.clone(); - * - * @method clone - * @return {tinymce.html.Node} New copy of the original node. - */ - clone: function() { - var self = this, clone = new Node(self.name, self.type), i, l, selfAttrs, selfAttr, cloneAttrs; - - // Clone element attributes - if ((selfAttrs = self.attributes)) { - cloneAttrs = []; - cloneAttrs.map = {}; - - for (i = 0, l = selfAttrs.length; i < l; i++) { - selfAttr = selfAttrs[i]; - - // Clone everything except id - if (selfAttr.name !== 'id') { - cloneAttrs[cloneAttrs.length] = {name: selfAttr.name, value: selfAttr.value}; - cloneAttrs.map[selfAttr.name] = selfAttr.value; - } - } - - clone.attributes = cloneAttrs; - } - - clone.value = self.value; - clone.shortEnded = self.shortEnded; - - return clone; - }, - - /** - * Wraps the node in in another node. - * - * @example - * node.wrap(wrapperNode); - * - * @method wrap - */ - wrap: function(wrapper) { - var self = this; - - self.parent.insert(wrapper, self); - wrapper.append(self); - - return self; - }, - - /** - * Unwraps the node in other words it removes the node but keeps the children. - * - * @example - * node.unwrap(); - * - * @method unwrap - */ - unwrap: function() { - var self = this, node, next; - - for (node = self.firstChild; node; ) { - next = node.next; - self.insert(node, self, true); - node = next; - } - - self.remove(); - }, - - /** - * Removes the node from it's parent. - * - * @example - * node.remove(); - * - * @method remove - * @return {tinymce.html.Node} Current node that got removed. - */ - remove: function() { - var self = this, parent = self.parent, next = self.next, prev = self.prev; - - if (parent) { - if (parent.firstChild === self) { - parent.firstChild = next; - - if (next) { - next.prev = null; - } - } else { - prev.next = next; - } - - if (parent.lastChild === self) { - parent.lastChild = prev; - - if (prev) { - prev.next = null; - } - } else { - next.prev = prev; - } - - self.parent = self.next = self.prev = null; - } - - return self; - }, - - /** - * Appends a new node as a child of the current node. - * - * @example - * node.append(someNode); - * - * @method append - * @param {tinymce.html.Node} node Node to append as a child of the current one. - * @return {tinymce.html.Node} The node that got appended. - */ - append: function(node) { - var self = this, last; - - if (node.parent) { - node.remove(); - } - - last = self.lastChild; - if (last) { - last.next = node; - node.prev = last; - self.lastChild = node; - } else { - self.lastChild = self.firstChild = node; - } - - node.parent = self; - - return node; - }, - - /** - * Inserts a node at a specific position as a child of the current node. - * - * @example - * parentNode.insert(newChildNode, oldChildNode); - * - * @method insert - * @param {tinymce.html.Node} node Node to insert as a child of the current node. - * @param {tinymce.html.Node} ref_node Reference node to set node before/after. - * @param {Boolean} before Optional state to insert the node before the reference node. - * @return {tinymce.html.Node} The node that got inserted. - */ - insert: function(node, ref_node, before) { - var parent; - - if (node.parent) { - node.remove(); - } - - parent = ref_node.parent || this; - - if (before) { - if (ref_node === parent.firstChild) { - parent.firstChild = node; - } else { - ref_node.prev.next = node; - } - - node.prev = ref_node.prev; - node.next = ref_node; - ref_node.prev = node; - } else { - if (ref_node === parent.lastChild) { - parent.lastChild = node; - } else { - ref_node.next.prev = node; - } - - node.next = ref_node.next; - node.prev = ref_node; - ref_node.next = node; - } - - node.parent = parent; - - return node; - }, - - /** - * Get all children by name. - * - * @method getAll - * @param {String} name Name of the child nodes to collect. - * @return {Array} Array with child nodes matchin the specified name. - */ - getAll: function(name) { - var self = this, node, collection = []; - - for (node = self.firstChild; node; node = walk(node, self)) { - if (node.name === name) { - collection.push(node); - } - } - - return collection; - }, - - /** - * Removes all children of the current node. - * - * @method empty - * @return {tinymce.html.Node} The current node that got cleared. - */ - empty: function() { - var self = this, nodes, i, node; - - // Remove all children - if (self.firstChild) { - nodes = []; - - // Collect the children - for (node = self.firstChild; node; node = walk(node, self)) { - nodes.push(node); - } - - // Remove the children - i = nodes.length; - while (i--) { - node = nodes[i]; - node.parent = node.firstChild = node.lastChild = node.next = node.prev = null; - } - } - - self.firstChild = self.lastChild = null; - - return self; - }, - - /** - * Returns true/false if the node is to be considered empty or not. - * - * @example - * node.isEmpty({img: true}); - * @method isEmpty - * @param {Object} elements Name/value object with elements that are automatically treated as non empty elements. - * @return {Boolean} true/false if the node is empty or not. - */ - isEmpty: function(elements) { - var self = this, node = self.firstChild, i, name; - - if (node) { - do { - if (node.type === 1) { - // Ignore bogus elements - if (node.attributes.map['data-mce-bogus']) { - continue; - } - - // Keep empty elements like
text
')); - * @class tinymce.html.Serializer - * @version 3.4 - */ -define("tinymce/html/Serializer", [ - "tinymce/html/Writer", - "tinymce/html/Schema" -], function(Writer, Schema) { - /** - * Constructs a new Serializer instance. - * - * @constructor - * @method Serializer - * @param {Object} settings Name/value settings object. - * @param {tinymce.html.Schema} schema Schema instance to use. - */ - return function(settings, schema) { - var self = this, writer = new Writer(settings); - - settings = settings || {}; - settings.validate = "validate" in settings ? settings.validate : true; - - self.schema = schema = schema || new Schema(); - self.writer = writer; - - /** - * Serializes the specified node into a string. - * - * @example - * new tinymce.html.Serializer().serialize(new tinymce.html.DomParser().parse('text
')); - * @method serialize - * @param {tinymce.html.Node} node Node instance to serialize. - * @return {String} String with HTML based on DOM tree. - */ - self.serialize = function(node) { - var handlers, validate; - - validate = settings.validate; - - handlers = { - // #text - 3: function(node) { - writer.text(node.value, node.raw); - }, - - // #comment - 8: function(node) { - writer.comment(node.value); - }, - - // Processing instruction - 7: function(node) { - writer.pi(node.name, node.value); - }, - - // Doctype - 10: function(node) { - writer.doctype(node.value); - }, - - // CDATA - 4: function(node) { - writer.cdata(node.value); - }, - - // Document fragment - 11: function(node) { - if ((node = node.firstChild)) { - do { - walk(node); - } while ((node = node.next)); - } - } - }; - - writer.reset(); - - function walk(node) { - var handler = handlers[node.type], name, isEmpty, attrs, attrName, attrValue, sortedAttrs, i, l, elementRule; - - if (!handler) { - name = node.name; - isEmpty = node.shortEnded; - attrs = node.attributes; - - // Sort attributes - if (validate && attrs && attrs.length > 1) { - sortedAttrs = []; - sortedAttrs.map = {}; - - elementRule = schema.getElementRule(node.name); - for (i = 0, l = elementRule.attributesOrder.length; i < l; i++) { - attrName = elementRule.attributesOrder[i]; - - if (attrName in attrs.map) { - attrValue = attrs.map[attrName]; - sortedAttrs.map[attrName] = attrValue; - sortedAttrs.push({name: attrName, value: attrValue}); - } - } - - for (i = 0, l = attrs.length; i < l; i++) { - attrName = attrs[i].name; - - if (!(attrName in sortedAttrs.map)) { - attrValue = attrs.map[attrName]; - sortedAttrs.map[attrName] = attrValue; - sortedAttrs.push({name: attrName, value: attrValue}); - } - } - - attrs = sortedAttrs; - } - - writer.start(node.name, attrs, isEmpty); - - if (!isEmpty) { - if ((node = node.firstChild)) { - do { - walk(node); - } while ((node = node.next)); - } - - writer.end(name); - } - } else { - handler(node); - } - } - - // Serialize element and treat all non elements as fragments - if (node.type == 1 && !settings.inner) { - walk(node); - } else { - handlers[11](node); - } - - return writer.getContent(); - }; - }; -}); diff --git a/lib/tinymce/js/tinymce/classes/html/Styles.js b/lib/tinymce/js/tinymce/classes/html/Styles.js deleted file mode 100644 index 1d869ff2..00000000 --- a/lib/tinymce/js/tinymce/classes/html/Styles.js +++ /dev/null @@ -1,297 +0,0 @@ -/** - * Styles.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -/** - * This class is used to parse CSS styles it also compresses styles to reduce the output size. - * - * @example - * var Styles = new tinymce.html.Styles({ - * url_converter: function(url) { - * return url; - * } - * }); - * - * styles = Styles.parse('border: 1px solid red'); - * styles.color = 'red'; - * - * console.log(new tinymce.html.StyleSerializer().serialize(styles)); - * - * @class tinymce.html.Styles - * @version 3.4 - */ -define("tinymce/html/Styles", [], function() { - return function(settings, schema) { - /*jshint maxlen:255 */ - var rgbRegExp = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi, - urlOrStrRegExp = /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi, - styleRegExp = /\s*([^:]+):\s*([^;]+);?/g, - trimRightRegExp = /\s+$/, - undef, i, encodingLookup = {}, encodingItems, invisibleChar = '\uFEFF'; - - settings = settings || {}; - - encodingItems = ('\\" \\\' \\; \\: ; : ' + invisibleChar).split(' '); - for (i = 0; i < encodingItems.length; i++) { - encodingLookup[encodingItems[i]] = invisibleChar + i; - encodingLookup[invisibleChar + i] = encodingItems[i]; - } - - function toHex(match, r, g, b) { - function hex(val) { - val = parseInt(val, 10).toString(16); - - return val.length > 1 ? val : '0' + val; // 0 -> 00 - } - - return '#' + hex(r) + hex(g) + hex(b); - } - - return { - /** - * Parses the specified RGB color value and returns a hex version of that color. - * - * @method toHex - * @param {String} color RGB string value like rgb(1,2,3) - * @return {String} Hex version of that RGB value like #FF00FF. - */ - toHex: function(color) { - return color.replace(rgbRegExp, toHex); - }, - - /** - * Parses the specified style value into an object collection. This parser will also - * merge and remove any redundant items that browsers might have added. It will also convert non hex - * colors to hex values. Urls inside the styles will also be converted to absolute/relative based on settings. - * - * @method parse - * @param {String} css Style value to parse for example: border:1px solid red;. - * @return {Object} Object representation of that style like {border: '1px solid red'} - */ - parse: function(css) { - var styles = {}, matches, name, value, isEncoded, urlConverter = settings.url_converter, urlConverterScope = settings.url_converter_scope || this; - - function compress(prefix, suffix) { - var top, right, bottom, left; - - // Get values and check it it needs compressing - top = styles[prefix + '-top' + suffix]; - if (!top) { - return; - } - - right = styles[prefix + '-right' + suffix]; - if (top != right) { - return; - } - - bottom = styles[prefix + '-bottom' + suffix]; - if (right != bottom) { - return; - } - - left = styles[prefix + '-left' + suffix]; - if (bottom != left) { - return; - } - - // Compress - styles[prefix + suffix] = left; - delete styles[prefix + '-top' + suffix]; - delete styles[prefix + '-right' + suffix]; - delete styles[prefix + '-bottom' + suffix]; - delete styles[prefix + '-left' + suffix]; - } - - /** - * Checks if the specific style can be compressed in other words if all border-width are equal. - */ - function canCompress(key) { - var value = styles[key], i; - - if (!value || value.indexOf(' ') < 0) { - return; - } - - value = value.split(' '); - i = value.length; - while (i--) { - if (value[i] !== value[0]) { - return false; - } - } - - styles[key] = value[0]; - - return true; - } - - /** - * Compresses multiple styles into one style. - */ - function compress2(target, a, b, c) { - if (!canCompress(a)) { - return; - } - - if (!canCompress(b)) { - return; - } - - if (!canCompress(c)) { - return; - } - - // Compress - styles[target] = styles[a] + ' ' + styles[b] + ' ' + styles[c]; - delete styles[a]; - delete styles[b]; - delete styles[c]; - } - - // Encodes the specified string by replacing all \" \' ; : with _.
- *
- * @method start
- * @param {String} name Name of the element.
- * @param {Array} attrs Optional attribute array or undefined if it hasn't any.
- * @param {Boolean} empty Optional empty state if the tag should end like
.
- */
- start: function(name, attrs, empty) {
- var i, l, attr, value;
-
- if (indent && indentBefore[name] && html.length > 0) {
- value = html[html.length - 1];
-
- if (value.length > 0 && value !== '\n') {
- html.push('\n');
- }
- }
-
- html.push('<', name);
-
- if (attrs) {
- for (i = 0, l = attrs.length; i < l; i++) {
- attr = attrs[i];
- html.push(' ', attr.name, '="', encode(attr.value, true), '"');
- }
- }
-
- if (!empty || htmlOutput) {
- html[html.length] = '>';
- } else {
- html[html.length] = ' />';
- }
-
- if (empty && indent && indentAfter[name] && html.length > 0) {
- value = html[html.length - 1];
-
- if (value.length > 0 && value !== '\n') {
- html.push('\n');
- }
- }
- },
-
- /**
- * Writes the a end element such as
' +
- ' ' +
- ' ' +
- ' | '
- );
- }
-
- html += '
|b
- * - * Will produce this on backspace: - *|
- * - * Or: - *|
- if (!isDefaultPrevented(e) && (keyCode == DELETE || keyCode == BACKSPACE)) { - isCollapsed = editor.selection.isCollapsed(); - - // Selection is collapsed but the editor isn't empty - if (isCollapsed && !dom.isEmpty(editor.getBody())) { - return; - } - - // IE deletes all contents correctly when everything is selected - if (isIE && !isCollapsed) { - return; - } - - // Selection isn't collapsed but not all the contents is selected - if (!isCollapsed && !allContentsSelected(editor.selection.getRng())) { - return; - } - - // Manually empty the editor - e.preventDefault(); - editor.setContent(''); - editor.selection.setCursorLocation(editor.getBody(), 0); - editor.nodeChanged(); - } - }); - } - - /** - * WebKit doesn't select all the nodes in the body when you press Ctrl+A. - * This selects the whole body so that backspace/delete logic will delete everything - */ - function selectAll() { - editor.on('keydown', function(e) { - if (!isDefaultPrevented(e) && e.keyCode == 65 && VK.metaKeyPressed(e)) { - e.preventDefault(); - editor.execCommand('SelectAll'); - } - }); - } - - /** - * WebKit has a weird issue where it some times fails to properly convert keypresses to input method keystrokes. - * The IME on Mac doesn't initialize when it doesn't fire a proper focus event. - * - * This seems to happen when the user manages to click the documentElement element then the window doesn't get proper focus until - * you enter a character into the editor. - * - * It also happens when the first focus in made to the body. - * - * See: https://bugs.webkit.org/show_bug.cgi?id=83566 - */ - function inputMethodFocus() { - if (!editor.settings.content_editable) { - // Case 1 IME doesn't initialize if you focus the document - dom.bind(editor.getDoc(), 'focusin', function() { - selection.setRng(selection.getRng()); - }); - - // Case 2 IME doesn't initialize if you click the documentElement it also doesn't properly fire the focusin event - dom.bind(editor.getDoc(), 'mousedown', function(e) { - if (e.target == editor.getDoc().documentElement) { - editor.getWin().focus(); - selection.setRng(selection.getRng()); - } - }); - } - } - - /** - * Backspacing in FireFox/IE from a paragraph into a horizontal rule results in a floating text node because the - * browser just deletes the paragraph - the browser fails to merge the text node with a horizontal rule so it is - * left there. TinyMCE sees a floating text node and wraps it in a paragraph on the key up event (ForceBlocks.js - * addRootBlocks), meaning the action does nothing. With this code, FireFox/IE matche the behaviour of other - * browsers - */ - function removeHrOnBackspace() { - editor.on('keydown', function(e) { - if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) { - if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) { - var node = selection.getNode(); - var previousSibling = node.previousSibling; - - if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "hr") { - dom.remove(previousSibling); - e.preventDefault(); - } - } - } - }); - } - - /** - * Firefox 3.x has an issue where the body element won't get proper focus if you click out - * side it's rectangle. - */ - function focusBody() { - // Fix for a focus bug in FF 3.x where the body element - // wouldn't get proper focus if the user clicked on the HTML element - if (!window.Range.prototype.getClientRects) { // Detect getClientRects got introduced in FF 4 - editor.on('mousedown', function(e) { - if (!isDefaultPrevented(e) && e.target.nodeName === "HTML") { - var body = editor.getBody(); - - // Blur the body it's focused but not correctly focused - body.blur(); - - // Refocus the body after a little while - setTimeout(function() { - body.focus(); - }, 0); - } - }); - } - } - - /** - * WebKit has a bug where it isn't possible to select image, hr or anchor elements - * by clicking on them so we need to fake that. - */ - function selectControlElements() { - editor.on('click', function(e) { - e = e.target; - - // Workaround for bug, http://bugs.webkit.org/show_bug.cgi?id=12250 - // WebKit can't even do simple things like selecting an image - // Needs tobe the setBaseAndExtend or it will fail to select floated images - if (/^(IMG|HR)$/.test(e.nodeName)) { - selection.getSel().setBaseAndExtent(e, 0, e, 1); - } - - if (e.nodeName == 'A' && dom.hasClass(e, 'mceItemAnchor')) { - selection.select(e); - } - - editor.nodeChanged(); - }); - } - - /** - * Fixes a Gecko bug where the style attribute gets added to the wrong element when deleting between two block elements. - * - * Fixes do backspace/delete on this: - *bla[ck
r]ed
- * - * Would become: - *bla|ed
- * - * Instead of: - *bla|ed
- */ - function removeStylesWhenDeletingAccrossBlockElements() { - function getAttributeApplyFunction() { - var template = dom.getAttribs(selection.getStart().cloneNode(false)); - - return function() { - var target = selection.getStart(); - - if (target !== editor.getBody()) { - dom.setAttrib(target, "style", null); - - each(template, function(attr) { - target.setAttributeNode(attr.cloneNode(true)); - }); - } - }; - } - - function isSelectionAcrossElements() { - return !selection.isCollapsed() && - dom.getParent(selection.getStart(), dom.isBlock) != dom.getParent(selection.getEnd(), dom.isBlock); - } - - editor.on('keypress', function(e) { - var applyAttributes; - - if (!isDefaultPrevented(e) && (e.keyCode == 8 || e.keyCode == 46) && isSelectionAcrossElements()) { - applyAttributes = getAttributeApplyFunction(); - editor.getDoc().execCommand('delete', false, null); - applyAttributes(); - e.preventDefault(); - return false; - } - }); - - dom.bind(editor.getDoc(), 'cut', function(e) { - var applyAttributes; - - if (!isDefaultPrevented(e) && isSelectionAcrossElements()) { - applyAttributes = getAttributeApplyFunction(); - - setTimeout(function() { - applyAttributes(); - }, 0); - } - }); - } - - /** - * Fire a nodeChanged when the selection is changed on WebKit this fixes selection issues on iOS5. It only fires the nodeChange - * event every 50ms since it would other wise update the UI when you type and it hogs the CPU. - */ - function selectionChangeNodeChanged() { - var lastRng, selectionTimer; - - editor.on('selectionchange', function() { - if (selectionTimer) { - clearTimeout(selectionTimer); - selectionTimer = 0; - } - - selectionTimer = window.setTimeout(function() { - var rng = selection.getRng(); - - // Compare the ranges to see if it was a real change or not - if (!lastRng || !RangeUtils.compareRanges(rng, lastRng)) { - editor.nodeChanged(); - lastRng = rng; - } - }, 50); - }); - } - - /** - * Screen readers on IE needs to have the role application set on the body. - */ - function ensureBodyHasRoleApplication() { - document.body.setAttribute("role", "application"); - } - - /** - * Backspacing into a table behaves differently depending upon browser type. - * Therefore, disable Backspace when cursor immediately follows a table. - */ - function disableBackspaceIntoATable() { - editor.on('keydown', function(e) { - if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) { - if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) { - var previousSibling = selection.getNode().previousSibling; - if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "table") { - e.preventDefault(); - return false; - } - } - } - }); - } - - /** - * Old IE versions can't properly render BR elements in PRE tags white in contentEditable mode. So this - * logic adds a \n before the BR so that it will get rendered. - */ - function addNewLinesBeforeBrInPre() { - // IE8+ rendering mode does the right thing with BR in PRE - if (getDocumentMode() > 7) { - return; - } - - // Enable display: none in area and add a specific class that hides all BR elements in PRE to - // avoid the caret from getting stuck at the BR elements while pressing the right arrow key - setEditorCommandState('RespectVisibilityInDesign', true); - editor.contentStyles.push('.mceHideBrInPre pre br {display: none}'); - dom.addClass(editor.getBody(), 'mceHideBrInPre'); - - // Adds a \n before all BR elements in PRE to get them visual - parser.addNodeFilter('pre', function(nodes) { - var i = nodes.length, brNodes, j, brElm, sibling; - - while (i--) { - brNodes = nodes[i].getAll('br'); - j = brNodes.length; - while (j--) { - brElm = brNodes[j]; - - // Add \n before BR in PRE elements on older IE:s so the new lines get rendered - sibling = brElm.prev; - if (sibling && sibling.type === 3 && sibling.value.charAt(sibling.value - 1) != '\n') { - sibling.value += '\n'; - } else { - brElm.parent.insert(new Node('#text', 3), brElm, true).value = '\n'; - } - } - } - }); - - // Removes any \n before BR elements in PRE since other browsers and in contentEditable=false mode they will be visible - serializer.addNodeFilter('pre', function(nodes) { - var i = nodes.length, brNodes, j, brElm, sibling; - - while (i--) { - brNodes = nodes[i].getAll('br'); - j = brNodes.length; - while (j--) { - brElm = brNodes[j]; - sibling = brElm.prev; - if (sibling && sibling.type == 3) { - sibling.value = sibling.value.replace(/\r?\n$/, ''); - } - } - } - }); - } - - /** - * Moves style width/height to attribute width/height when the user resizes an image on IE. - */ - function removePreSerializedStylesWhenSelectingControls() { - dom.bind(editor.getBody(), 'mouseup', function() { - var value, node = selection.getNode(); - - // Moved styles to attributes on IMG eements - if (node.nodeName == 'IMG') { - // Convert style width to width attribute - if ((value = dom.getStyle(node, 'width'))) { - dom.setAttrib(node, 'width', value.replace(/[^0-9%]+/g, '')); - dom.setStyle(node, 'width', ''); - } - - // Convert style height to height attribute - if ((value = dom.getStyle(node, 'height'))) { - dom.setAttrib(node, 'height', value.replace(/[^0-9%]+/g, '')); - dom.setStyle(node, 'height', ''); - } - } - }); - } - - /** - * Backspace or delete on WebKit will combine all visual styles in a span if the last character is deleted. - * - * For example backspace on: - *x|
- * - * Will produce: - *|
|
|x
|
- container = selection.getRng().startContainer; - sibling = container.previousSibling; - if (sibling && sibling.nodeType == 1 && !dom.isBlock(sibling) && dom.isEmpty(sibling) && - !nonEmptyElements[sibling.nodeName.toLowerCase()]) { - dom.remove(sibling); - } - - // Remove the temp element we inserted - dom.remove('__tmp'); - } - } - }); - } - - /** - * Removes a blockquote when backspace is pressed at the beginning of it. - * - * For example: - *- * - * Becomes: - *|x
|x
- */ - function removeBlockQuoteOnBackSpace() { - // Add block quote deletion handler - editor.on('keydown', function(e) { - var rng, container, offset, root, parent; - - if (isDefaultPrevented(e) || e.keyCode != VK.BACKSPACE) { - return; - } - - rng = selection.getRng(); - container = rng.startContainer; - offset = rng.startOffset; - root = dom.getRoot(); - parent = container; - - if (!rng.collapsed || offset !== 0) { - return; - } - - while (parent && parent.parentNode && parent.parentNode.firstChild == parent && parent.parentNode != root) { - parent = parent.parentNode; - } - - // Is the cursor at the beginning of a blockquote? - if (parent.tagName === 'BLOCKQUOTE') { - // Remove the blockquote - editor.formatter.toggle('blockquote', null, parent); - - // Move the caret to the beginning of container - rng = dom.createRng(); - rng.setStart(container, 0); - rng.setEnd(container, 0); - selection.setRng(rng); - } - }); - } - - /** - * Sets various Gecko editing options on mouse down and before a execCommand to disable inline table editing that is broken etc. - */ - function setGeckoEditingOptions() { - function setOpts() { - editor._refreshContentEditable(); - - setEditorCommandState("StyleWithCSS", false); - setEditorCommandState("enableInlineTableEditing", false); - - if (!settings.object_resizing) { - setEditorCommandState("enableObjectResizing", false); - } - } - - if (!settings.readonly) { - editor.on('BeforeExecCommand MouseDown', setOpts); - } - } - - /** - * Fixes a gecko link bug, when a link is placed at the end of block elements there is - * no way to move the caret behind the link. This fix adds a bogus br element after the link. - * - * For example this: - * - * - * Becomes this: - * - */ - function addBrAfterLastLinks() { - function fixLinks() { - each(dom.select('a'), function(node) { - var parentNode = node.parentNode, root = dom.getRoot(); - - if (parentNode.lastChild === node) { - while (parentNode && !dom.isBlock(parentNode)) { - if (parentNode.parentNode.lastChild !== parentNode || parentNode === root) { - return; - } - - parentNode = parentNode.parentNode; - } - - dom.add(parentNode, 'br', {'data-mce-bogus': 1}); - } - }); - } - - editor.on('SetContent ExecCommand', function(e) { - if (e.type == "setcontent" || e.command === 'mceInsertLink') { - fixLinks(); - } - }); - } - - /** - * WebKit will produce DIV elements here and there by default. But since TinyMCE uses paragraphs by - * default we want to change that behavior. - */ - function setDefaultBlockType() { - if (settings.forced_root_block) { - editor.on('init', function() { - setEditorCommandState('DefaultParagraphSeparator', settings.forced_root_block); - }); - } - } - - /** - * Removes ghost selections from images/tables on Gecko. - */ - function removeGhostSelection() { - editor.on('Undo Redo SetContent', function(e) { - if (!e.initial) { - editor.execCommand('mceRepaint'); - } - }); - } - - /** - * Deletes the selected image on IE instead of navigating to previous page. - */ - function deleteControlItemOnBackSpace() { - editor.on('keydown', function(e) { - var rng; - - if (!isDefaultPrevented(e) && e.keyCode == BACKSPACE) { - rng = editor.getDoc().selection.createRange(); - if (rng && rng.item) { - e.preventDefault(); - editor.undoManager.beforeChange(); - dom.remove(rng.item(0)); - editor.undoManager.add(); - } - } - }); - } - - /** - * IE10 doesn't properly render block elements with the right height until you add contents to them. - * This fixes that by adding a padding-right to all empty text block elements. - * See: https://connect.microsoft.com/IE/feedback/details/743881 - */ - function renderEmptyBlocksFix() { - var emptyBlocksCSS; - - // IE10+ - if (getDocumentMode() >= 10) { - emptyBlocksCSS = ''; - each('p div h1 h2 h3 h4 h5 h6'.split(' '), function(name, i) { - emptyBlocksCSS += (i > 0 ? ',' : '') + name + ':empty'; - }); - - editor.contentStyles.push(emptyBlocksCSS + '{padding-right: 1px !important}'); - } - } - - /** - * Old IE versions can't retain contents within noscript elements so this logic will store the contents - * as a attribute and the insert that value as it's raw text when the DOM is serialized. - */ - function keepNoScriptContents() { - if (getDocumentMode() < 9) { - parser.addNodeFilter('noscript', function(nodes) { - var i = nodes.length, node, textNode; - - while (i--) { - node = nodes[i]; - textNode = node.firstChild; - - if (textNode) { - node.attr('data-mce-innertext', textNode.value); - } - } - }); - - serializer.addNodeFilter('noscript', function(nodes) { - var i = nodes.length, node, textNode, value; - - while (i--) { - node = nodes[i]; - textNode = nodes[i].firstChild; - - if (textNode) { - textNode.value = Entities.decode(textNode.value); - } else { - // Old IE can't retain noscript value so an attribute is used to store it - value = node.attributes.map['data-mce-innertext']; - if (value) { - node.attr('data-mce-innertext', null); - textNode = new Node('#text', 3); - textNode.value = value; - textNode.raw = true; - node.append(textNode); - } - } - } - }); - } - } - - /** - * IE has an issue where you can't select/move the caret by clicking outside the body if the document is in standards mode. - */ - function fixCaretSelectionOfDocumentElementOnIe() { - var doc = dom.doc, body = doc.body, started, startRng, htmlElm; - - // Return range from point or null if it failed - function rngFromPoint(x, y) { - var rng = body.createTextRange(); - - try { - rng.moveToPoint(x, y); - } catch (ex) { - // IE sometimes throws and exception, so lets just ignore it - rng = null; - } - - return rng; - } - - // Fires while the selection is changing - function selectionChange(e) { - var pointRng; - - // Check if the button is down or not - if (e.button) { - // Create range from mouse position - pointRng = rngFromPoint(e.x, e.y); - - if (pointRng) { - // Check if pointRange is before/after selection then change the endPoint - if (pointRng.compareEndPoints('StartToStart', startRng) > 0) { - pointRng.setEndPoint('StartToStart', startRng); - } else { - pointRng.setEndPoint('EndToEnd', startRng); - } - - pointRng.select(); - } - } else { - endSelection(); - } - } - - // Removes listeners - function endSelection() { - var rng = doc.selection.createRange(); - - // If the range is collapsed then use the last start range - if (startRng && !rng.item && rng.compareEndPoints('StartToEnd', rng) === 0) { - startRng.select(); - } - - dom.unbind(doc, 'mouseup', endSelection); - dom.unbind(doc, 'mousemove', selectionChange); - startRng = started = 0; - } - - // Make HTML element unselectable since we are going to handle selection by hand - doc.documentElement.unselectable = true; - - // Detect when user selects outside BODY - dom.bind(doc, 'mousedown contextmenu', function(e) { - if (e.target.nodeName === 'HTML') { - if (started) { - endSelection(); - } - - // Detect vertical scrollbar, since IE will fire a mousedown on the scrollbar and have target set as HTML - htmlElm = doc.documentElement; - if (htmlElm.scrollHeight > htmlElm.clientHeight) { - return; - } - - started = 1; - // Setup start position - startRng = rngFromPoint(e.x, e.y); - if (startRng) { - // Listen for selection change events - dom.bind(doc, 'mouseup', endSelection); - dom.bind(doc, 'mousemove', selectionChange); - - dom.win.focus(); - startRng.select(); - } - } - }); - } - - /** - * Fixes selection issues on Gecko where the caret can be placed between two inline elements like a|b - * this fix will lean the caret right into the closest inline element. - */ - function normalizeSelection() { - // Normalize selection for example a|a becomes a|a except for Ctrl+A since it selects everything - editor.on('keyup focusin', function(e) { - if (e.keyCode != 65 || !VK.metaKeyPressed(e)) { - selection.normalize(); - } - }); - } - - // All browsers - disableBackspaceIntoATable(); - removeBlockQuoteOnBackSpace(); - emptyEditorWhenDeleting(); - normalizeSelection(); - - // WebKit - if (isWebKit) { - keepInlineElementOnDeleteBackspace(); - cleanupStylesWhenDeleting(); - inputMethodFocus(); - selectControlElements(); - setDefaultBlockType(); - - // iOS - if (Env.iOS) { - selectionChangeNodeChanged(); - } else { - selectAll(); - } - } - - // IE - if (isIE) { - removeHrOnBackspace(); - ensureBodyHasRoleApplication(); - addNewLinesBeforeBrInPre(); - removePreSerializedStylesWhenSelectingControls(); - deleteControlItemOnBackSpace(); - renderEmptyBlocksFix(); - keepNoScriptContents(); - fixCaretSelectionOfDocumentElementOnIe(); - } - - // Gecko - if (isGecko) { - removeHrOnBackspace(); - focusBody(); - removeStylesWhenDeletingAccrossBlockElements(); - setGeckoEditingOptions(); - addBrAfterLastLinks(); - removeGhostSelection(); - } - }; -}); \ No newline at end of file diff --git a/lib/tinymce/js/tinymce/classes/util/Tools.js b/lib/tinymce/js/tinymce/classes/util/Tools.js deleted file mode 100644 index 66b6b4b6..00000000 --- a/lib/tinymce/js/tinymce/classes/util/Tools.js +++ /dev/null @@ -1,496 +0,0 @@ -/** - * Quirks.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -define("tinymce/util/Tools", [], function() { - /** - * Removes whitespace from the beginning and end of a string. - * - * @method trim - * @param {String} s String to remove whitespace from. - * @return {String} New string with removed whitespace. - */ - var whiteSpaceRegExp = /^\s*|\s*$/g; - var trim = function(str) { - return (str === null || str === undefined) ? '' : ("" + str).replace(whiteSpaceRegExp, ''); - }; - - /** - * Returns true/false if the object is an array or not. - * - * @method isArray - * @param {Object} obj Object to check. - * @return {boolean} true/false state if the object is an array or not. - */ - var isArray = Array.isArray || function(obj) { - return Object.prototype.toString.call(obj) === "[object Array]"; - }; - - /** - * Checks if a object is of a specific type for example an array. - * - * @method is - * @param {Object} o Object to check type of. - * @param {string} t Optional type to check for. - * @return {Boolean} true/false if the object is of the specified type. - */ - function is(o, t) { - if (!t) { - return o !== undefined; - } - - if (t == 'array' && isArray(o)) { - return true; - } - - return typeof(o) == t; - } - - /** - * Converts the specified object into a real JavaScript array. - * - * @method toArray - * @param {Object} obj Object to convert into array. - * @return {Array} Array object based in input. - */ - function toArray(obj) { - var array = [], i, l; - - for (i = 0, l = obj.length; i < l; i++) { - array[i] = obj[i]; - } - - return array; - } - - /** - * Makes a name/object map out of an array with names. - * - * @method makeMap - * @param {Array/String} items Items to make map out of. - * @param {String} delim Optional delimiter to split string by. - * @param {Object} map Optional map to add items to. - * @return {Object} Name/value map of items. - */ - function makeMap(items, delim, map) { - var i; - - items = items || []; - delim = delim || ','; - - if (typeof(items) == "string") { - items = items.split(delim); - } - - map = map || {}; - - i = items.length; - while (i--) { - map[items[i]] = {}; - } - - return map; - } - - /** - * Performs an iteration of all items in a collection such as an object or array. This method will execure the - * callback function for each item in the collection, if the callback returns false the iteration will terminate. - * The callback has the following format: cb(value, key_or_index). - * - * @method each - * @param {Object} o Collection to iterate. - * @param {function} cb Callback function to execute for each item. - * @param {Object} s Optional scope to execute the callback in. - * @example - * // Iterate an array - * tinymce.each([1,2,3], function(v, i) { - * console.debug("Value: " + v + ", Index: " + i); - * }); - * - * // Iterate an object - * tinymce.each({a: 1, b: 2, c: 3], function(v, k) { - * console.debug("Value: " + v + ", Key: " + k); - * }); - */ - function each(o, cb, s) { - var n, l; - - if (!o) { - return 0; - } - - s = s || o; - - if (o.length !== undefined) { - // Indexed arrays, needed for Safari - for (n=0, l = o.length; n < l; n++) { - if (cb.call(s, o[n], n, o) === false) { - return 0; - } - } - } else { - // Hashtables - for (n in o) { - if (o.hasOwnProperty(n)) { - if (cb.call(s, o[n], n, o) === false) { - return 0; - } - } - } - } - - return 1; - } - - /** - * Creates a new array by the return value of each iteration function call. This enables you to convert - * one array list into another. - * - * @method map - * @param {Array} a Array of items to iterate. - * @param {function} f Function to call for each item. It's return value will be the new value. - * @return {Array} Array with new values based on function return values. - */ - function map(a, f) { - var o = []; - - each(a, function(v) { - o.push(f(v)); - }); - - return o; - } - - /** - * Filters out items from the input array by calling the specified function for each item. - * If the function returns false the item will be excluded if it returns true it will be included. - * - * @method grep - * @param {Array} a Array of items to loop though. - * @param {function} f Function to call for each item. Include/exclude depends on it's return value. - * @return {Array} New array with values imported and filtered based in input. - * @example - * // Filter out some items, this will return an array with 4 and 5 - * var items = tinymce.grep([1,2,3,4,5], function(v) {return v > 3;}); - */ - function grep(a, f) { - var o = []; - - each(a, function(v) { - if (!f || f(v)) { - o.push(v); - } - }); - - return o; - } - - /** - * Creates a class, subclass or static singleton. - * More details on this method can be found in the Wiki. - * - * @method create - * @param {String} s Class name, inheritage and prefix. - * @param {Object} p Collection of methods to add to the class. - * @param {Object} root Optional root object defaults to the global window object. - * @example - * // Creates a basic class - * tinymce.create('tinymce.somepackage.SomeClass', { - * SomeClass: function() { - * // Class constructor - * }, - * - * method: function() { - * // Some method - * } - * }); - * - * // Creates a basic subclass class - * tinymce.create('tinymce.somepackage.SomeSubClass:tinymce.somepackage.SomeClass', { - * SomeSubClass: function() { - * // Class constructor - * this.parent(); // Call parent constructor - * }, - * - * method: function() { - * // Some method - * this.parent(); // Call parent method - * }, - * - * 'static': { - * staticMethod: function() { - * // Static method - * } - * } - * }); - * - * // Creates a singleton/static class - * tinymce.create('static tinymce.somepackage.SomeSingletonClass', { - * method: function() { - * // Some method - * } - * }); - */ - function create(s, p, root) { - var t = this, sp, ns, cn, scn, c, de = 0; - - // Parse :]*>/gi,"[quote]"); - rep(/<\/blockquote>/gi,"[/quote]"); - rep(/
/gi,"\n"); - rep(/
/gi,"\n"); - rep(/
/gi,"\n"); - rep(//gi,""); - rep(/<\/p>/gi,"\n"); - rep(/ |\u00a0/gi," "); - rep(/"/gi,"\""); - rep(/</gi,"<"); - rep(/>/gi,">"); - rep(/&/gi,"&"); - - return s; - }, - - // BBCode -> HTML from PunBB dialect - _punbb_bbcode2html : function(s) { - s = tinymce.trim(s); - - function rep(re, str) { - s = s.replace(re, str); - } - - // example: [b] to - rep(/\n/gi,"
"); - rep(/\[b\]/gi,""); - rep(/\[\/b\]/gi,""); - rep(/\[i\]/gi,""); - rep(/\[\/i\]/gi,""); - rep(/\[u\]/gi,""); - rep(/\[\/u\]/gi,""); - rep(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,"$2"); - rep(/\[url\](.*?)\[\/url\]/gi,"$1"); - rep(/\[img\](.*?)\[\/img\]/gi,""); - rep(/\[color=(.*?)\](.*?)\[\/color\]/gi,"$2"); - rep(/\[code\](.*?)\[\/code\]/gi,"$1 "); - rep(/\[quote.*?\](.*?)\[\/quote\]/gi,"$1 "); - - return s; - } - }); - - // Register plugin - tinymce.PluginManager.add('bbcode', tinymce.plugins.BBCodePlugin); -})(); \ No newline at end of file +(function () { + 'use strict'; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + + var html2bbcode = function (s) { + s = global$1.trim(s); + var rep = function (re, str) { + s = s.replace(re, str); + }; + rep(/
(.*?)<\/a>/gi, '[url=$1]$2[/url]'); + rep(/ (.*?)<\/font>/gi, '[code][color=$1]$2[/color][/code]'); + rep(/ (.*?)<\/font>/gi, '[quote][color=$1]$2[/color][/quote]'); + rep(/ (.*?)<\/font>/gi, '[code][color=$1]$2[/color][/code]'); + rep(/ (.*?)<\/font>/gi, '[quote][color=$1]$2[/color][/quote]'); + rep(/(.*?)<\/span>/gi, '[color=$1]$2[/color]'); + rep(/ (.*?)<\/font>/gi, '[color=$1]$2[/color]'); + rep(/(.*?)<\/span>/gi, '[size=$1]$2[/size]'); + rep(/(.*?)<\/font>/gi, '$1'); + rep(/ /gi, '[img]$1[/img]'); + rep(/(.*?)<\/span>/gi, '[code]$1[/code]'); + rep(/(.*?)<\/span>/gi, '[quote]$1[/quote]'); + rep(/(.*?)<\/strong>/gi, '[code][b]$1[/b][/code]'); + rep(/(.*?)<\/strong>/gi, '[quote][b]$1[/b][/quote]'); + rep(/(.*?)<\/em>/gi, '[code][i]$1[/i][/code]'); + rep(/(.*?)<\/em>/gi, '[quote][i]$1[/i][/quote]'); + rep(/(.*?)<\/u>/gi, '[code][u]$1[/u][/code]'); + rep(/(.*?)<\/u>/gi, '[quote][u]$1[/u][/quote]'); + rep(/<\/(strong|b)>/gi, '[/b]'); + rep(/<(strong|b)>/gi, '[b]'); + rep(/<\/(em|i)>/gi, '[/i]'); + rep(/<(em|i)>/gi, '[i]'); + rep(/<\/u>/gi, '[/u]'); + rep(/(.*?)<\/span>/gi, '[u]$1[/u]'); + rep(//gi, '[u]'); + rep(/ ]*>/gi, '[quote]'); + rep(/<\/blockquote>/gi, '[/quote]'); + rep(/
/gi, '\n'); + rep(/
/gi, '\n'); + rep(/
/gi, '\n'); + rep(//gi, ''); + rep(/<\/p>/gi, '\n'); + rep(/ |\u00a0/gi, ' '); + rep(/"/gi, '"'); + rep(/</gi, '<'); + rep(/>/gi, '>'); + rep(/&/gi, '&'); + return s; + }; + var bbcode2html = function (s) { + s = global$1.trim(s); + var rep = function (re, str) { + s = s.replace(re, str); + }; + rep(/\n/gi, '
'); + rep(/\[b\]/gi, ''); + rep(/\[\/b\]/gi, ''); + rep(/\[i\]/gi, ''); + rep(/\[\/i\]/gi, ''); + rep(/\[u\]/gi, ''); + rep(/\[\/u\]/gi, ''); + rep(/\[url=([^\]]+)\](.*?)\[\/url\]/gi, '$2'); + rep(/\[url\](.*?)\[\/url\]/gi, '$1'); + rep(/\[img\](.*?)\[\/img\]/gi, ''); + rep(/\[color=(.*?)\](.*?)\[\/color\]/gi, '$2'); + rep(/\[code\](.*?)\[\/code\]/gi, '$1 '); + rep(/\[quote.*?\](.*?)\[\/quote\]/gi, '$1 '); + return s; + }; + var Convert = { + html2bbcode: html2bbcode, + bbcode2html: bbcode2html + }; + + function Plugin () { + global.add('bbcode', function (editor) { + editor.on('BeforeSetContent', function (e) { + e.content = Convert.bbcode2html(e.content); + }); + editor.on('PostProcess', function (e) { + if (e.set) { + e.content = Convert.bbcode2html(e.content); + } + if (e.get) { + e.content = Convert.html2bbcode(e.content); + } + }); + }); + } + + Plugin(); + +}()); diff --git a/lib/tinymce/js/tinymce/plugins/bbcode/plugin.min.js b/lib/tinymce/js/tinymce/plugins/bbcode/plugin.min.js index 578e8985..eb2a0055 100644 --- a/lib/tinymce/js/tinymce/plugins/bbcode/plugin.min.js +++ b/lib/tinymce/js/tinymce/plugins/bbcode/plugin.min.js @@ -1 +1,9 @@ -(function(){tinymce.create("tinymce.plugins.BBCodePlugin",{init:function(e){var t=this,n=e.getParam("bbcode_dialect","punbb").toLowerCase();e.on("beforeSetContent",function(e){e.content=t["_"+n+"_bbcode2html"](e.content)}),e.on("postProcess",function(e){e.set&&(e.content=t["_"+n+"_bbcode2html"](e.content)),e.get&&(e.content=t["_"+n+"_html2bbcode"](e.content))})},getInfo:function(){return{longname:"BBCode Plugin",author:"Moxiecode Systems AB",authorurl:"http://www.tinymce.com",infourl:"http://www.tinymce.com/wiki.php/Plugin:bbcode"}},_punbb_html2bbcode:function(e){function t(t,n){e=e.replace(t,n)}return e=tinymce.trim(e),t(/
(.*?)<\/a>/gi,"[url=$1]$2[/url]"),t(/ (.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),t(/ (.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),t(/ (.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),t(/ (.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),t(/(.*?)<\/span>/gi,"[color=$1]$2[/color]"),t(/ (.*?)<\/font>/gi,"[color=$1]$2[/color]"),t(/(.*?)<\/span>/gi,"[size=$1]$2[/size]"),t(/(.*?)<\/font>/gi,"$1"),t(/ /gi,"[img]$1[/img]"),t(/(.*?)<\/span>/gi,"[code]$1[/code]"),t(/(.*?)<\/span>/gi,"[quote]$1[/quote]"),t(/(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"),t(/(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"),t(/(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"),t(/(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"),t(/(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"),t(/(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"),t(/<\/(strong|b)>/gi,"[/b]"),t(/<(strong|b)>/gi,"[b]"),t(/<\/(em|i)>/gi,"[/i]"),t(/<(em|i)>/gi,"[i]"),t(/<\/u>/gi,"[/u]"),t(/(.*?)<\/span>/gi,"[u]$1[/u]"),t(//gi,"[u]"),t(/ ]*>/gi,"[quote]"),t(/<\/blockquote>/gi,"[/quote]"),t(/
/gi,"\n"),t(/
/gi,"\n"),t(/
/gi,"\n"),t(//gi,""),t(/<\/p>/gi,"\n"),t(/ |\u00a0/gi," "),t(/"/gi,'"'),t(/</gi,"<"),t(/>/gi,">"),t(/&/gi,"&"),e},_punbb_bbcode2html:function(e){function t(t,n){e=e.replace(t,n)}return e=tinymce.trim(e),t(/\n/gi,"
"),t(/\[b\]/gi,""),t(/\[\/b\]/gi,""),t(/\[i\]/gi,""),t(/\[\/i\]/gi,""),t(/\[u\]/gi,""),t(/\[\/u\]/gi,""),t(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'$2'),t(/\[url\](.*?)\[\/url\]/gi,'$1'),t(/\[img\](.*?)\[\/img\]/gi,''),t(/\[color=(.*?)\](.*?)\[\/color\]/gi,'$2'),t(/\[code\](.*?)\[\/code\]/gi,'$1 '),t(/\[quote.*?\](.*?)\[\/quote\]/gi,'$1 '),e}}),tinymce.PluginManager.add("bbcode",tinymce.plugins.BBCodePlugin)})(); \ No newline at end of file +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.1.6 (2020-01-28) + */ +!function(){"use strict";var o=tinymce.util.Tools.resolve("tinymce.PluginManager"),e=tinymce.util.Tools.resolve("tinymce.util.Tools"),t=function(t){t=e.trim(t);function o(o,e){t=t.replace(o,e)}return o(/
(.*?)<\/a>/gi,"[url=$1]$2[/url]"),o(/ (.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),o(/ (.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),o(/ (.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),o(/ (.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),o(/(.*?)<\/span>/gi,"[color=$1]$2[/color]"),o(/ (.*?)<\/font>/gi,"[color=$1]$2[/color]"),o(/(.*?)<\/span>/gi,"[size=$1]$2[/size]"),o(/(.*?)<\/font>/gi,"$1"),o(/ /gi,"[img]$1[/img]"),o(/(.*?)<\/span>/gi,"[code]$1[/code]"),o(/(.*?)<\/span>/gi,"[quote]$1[/quote]"),o(/(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"),o(/(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"),o(/(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"),o(/(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"),o(/(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"),o(/(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"),o(/<\/(strong|b)>/gi,"[/b]"),o(/<(strong|b)>/gi,"[b]"),o(/<\/(em|i)>/gi,"[/i]"),o(/<(em|i)>/gi,"[i]"),o(/<\/u>/gi,"[/u]"),o(/(.*?)<\/span>/gi,"[u]$1[/u]"),o(//gi,"[u]"),o(/ ]*>/gi,"[quote]"),o(/<\/blockquote>/gi,"[/quote]"),o(/
/gi,"\n"),o(/
/gi,"\n"),o(/
/gi,"\n"),o(//gi,""),o(/<\/p>/gi,"\n"),o(/ |\u00a0/gi," "),o(/"/gi,'"'),o(/</gi,"<"),o(/>/gi,">"),o(/&/gi,"&"),t},i=function(t){t=e.trim(t);function o(o,e){t=t.replace(o,e)}return o(/\n/gi,"
"),o(/\[b\]/gi,""),o(/\[\/b\]/gi,""),o(/\[i\]/gi,""),o(/\[\/i\]/gi,""),o(/\[u\]/gi,""),o(/\[\/u\]/gi,""),o(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'$2'),o(/\[url\](.*?)\[\/url\]/gi,'$1'),o(/\[img\](.*?)\[\/img\]/gi,''),o(/\[color=(.*?)\](.*?)\[\/color\]/gi,'$2'),o(/\[code\](.*?)\[\/code\]/gi,'$1 '),o(/\[quote.*?\](.*?)\[\/quote\]/gi,'$1 '),t};!function n(){o.add("bbcode",function(o){o.on("BeforeSetContent",function(o){o.content=i(o.content)}),o.on("PostProcess",function(o){o.set&&(o.content=i(o.content)),o.get&&(o.content=t(o.content))})})}()}(); \ No newline at end of file diff --git a/lib/tinymce/js/tinymce/plugins/charmap/plugin.js b/lib/tinymce/js/tinymce/plugins/charmap/plugin.js index b82b671b..d981805c 100644 --- a/lib/tinymce/js/tinymce/plugins/charmap/plugin.js +++ b/lib/tinymce/js/tinymce/plugins/charmap/plugin.js @@ -1,361 +1,1696 @@ /** - * plugin.js + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing + * Version: 5.1.6 (2020-01-28) */ +(function (domGlobals) { + 'use strict'; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var fireInsertCustomChar = function (editor, chr) { + return editor.fire('insertCustomChar', { chr: chr }); + }; + var Events = { fireInsertCustomChar: fireInsertCustomChar }; + + var insertChar = function (editor, chr) { + var evtChr = Events.fireInsertCustomChar(editor, chr).chr; + editor.execCommand('mceInsertContent', false, evtChr); + }; + var Actions = { insertChar: insertChar }; + + var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + + var getCharMap = function (editor) { + return editor.settings.charmap; + }; + var getCharMapAppend = function (editor) { + return editor.settings.charmap_append; + }; + var Settings = { + getCharMap: getCharMap, + getCharMapAppend: getCharMapAppend + }; + + var noop = function () { + }; + var constant = function (value) { + return function () { + return value; + }; + }; + var never = constant(false); + var always = constant(true); + + var none = function () { + return NONE; + }; + var NONE = function () { + var eq = function (o) { + return o.isNone(); + }; + var call = function (thunk) { + return thunk(); + }; + var id = function (n) { + return n; + }; + var me = { + fold: function (n, s) { + return n(); + }, + is: never, + isSome: never, + isNone: always, + getOr: id, + getOrThunk: call, + getOrDie: function (msg) { + throw new Error(msg || 'error: getOrDie called on none.'); + }, + getOrNull: constant(null), + getOrUndefined: constant(undefined), + or: id, + orThunk: call, + map: none, + each: noop, + bind: none, + exists: never, + forall: always, + filter: none, + equals: eq, + equals_: eq, + toArray: function () { + return []; + }, + toString: constant('none()') + }; + if (Object.freeze) { + Object.freeze(me); + } + return me; + }(); + var some = function (a) { + var constant_a = constant(a); + var self = function () { + return me; + }; + var bind = function (f) { + return f(a); + }; + var me = { + fold: function (n, s) { + return s(a); + }, + is: function (v) { + return a === v; + }, + isSome: always, + isNone: never, + getOr: constant_a, + getOrThunk: constant_a, + getOrDie: constant_a, + getOrNull: constant_a, + getOrUndefined: constant_a, + or: self, + orThunk: self, + map: function (f) { + return some(f(a)); + }, + each: function (f) { + f(a); + }, + bind: bind, + exists: bind, + forall: bind, + filter: function (f) { + return f(a) ? me : NONE; + }, + toArray: function () { + return [a]; + }, + toString: function () { + return 'some(' + a + ')'; + }, + equals: function (o) { + return o.is(a); + }, + equals_: function (o, elementEq) { + return o.fold(never, function (b) { + return elementEq(a, b); + }); + } + }; + return me; + }; + var from = function (value) { + return value === null || value === undefined ? NONE : some(value); + }; + var Option = { + some: some, + none: none, + from: from + }; -/*global tinymce:true */ + var typeOf = function (x) { + if (x === null) { + return 'null'; + } + var t = typeof x; + if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) { + return 'array'; + } + if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) { + return 'string'; + } + return t; + }; + var isType = function (type) { + return function (value) { + return typeOf(value) === type; + }; + }; + var isArray = isType('array'); + var isFunction = isType('function'); -tinymce.PluginManager.add('charmap', function(editor) { - var charmap = [ - ['160', 'no-break space'], - ['38', 'ampersand'], - ['34', 'quotation mark'], - // finance - ['162', 'cent sign'], - ['8364', 'euro sign'], - ['163', 'pound sign'], - ['165', 'yen sign'], - // signs - ['169', 'copyright sign'], - ['174', 'registered sign'], - ['8482', 'trade mark sign'], - ['8240', 'per mille sign'], - ['181', 'micro sign'], - ['183', 'middle dot'], - ['8226', 'bullet'], - ['8230', 'three dot leader'], - ['8242', 'minutes / feet'], - ['8243', 'seconds / inches'], - ['167', 'section sign'], - ['182', 'paragraph sign'], - ['223', 'sharp s / ess-zed'], - // quotations - ['8249', 'single left-pointing angle quotation mark'], - ['8250', 'single right-pointing angle quotation mark'], - ['171', 'left pointing guillemet'], - ['187', 'right pointing guillemet'], - ['8216', 'left single quotation mark'], - ['8217', 'right single quotation mark'], - ['8220', 'left double quotation mark'], - ['8221', 'right double quotation mark'], - ['8218', 'single low-9 quotation mark'], - ['8222', 'double low-9 quotation mark'], - ['60', 'less-than sign'], - ['62', 'greater-than sign'], - ['8804', 'less-than or equal to'], - ['8805', 'greater-than or equal to'], - ['8211', 'en dash'], - ['8212', 'em dash'], - ['175', 'macron'], - ['8254', 'overline'], - ['164', 'currency sign'], - ['166', 'broken bar'], - ['168', 'diaeresis'], - ['161', 'inverted exclamation mark'], - ['191', 'turned question mark'], - ['710', 'circumflex accent'], - ['732', 'small tilde'], - ['176', 'degree sign'], - ['8722', 'minus sign'], - ['177', 'plus-minus sign'], - ['247', 'division sign'], - ['8260', 'fraction slash'], - ['215', 'multiplication sign'], - ['185', 'superscript one'], - ['178', 'superscript two'], - ['179', 'superscript three'], - ['188', 'fraction one quarter'], - ['189', 'fraction one half'], - ['190', 'fraction three quarters'], - // math / logical - ['402', 'function / florin'], - ['8747', 'integral'], - ['8721', 'n-ary sumation'], - ['8734', 'infinity'], - ['8730', 'square root'], - ['8764', 'similar to'], - ['8773', 'approximately equal to'], - ['8776', 'almost equal to'], - ['8800', 'not equal to'], - ['8801', 'identical to'], - ['8712', 'element of'], - ['8713', 'not an element of'], - ['8715', 'contains as member'], - ['8719', 'n-ary product'], - ['8743', 'logical and'], - ['8744', 'logical or'], - ['172', 'not sign'], - ['8745', 'intersection'], - ['8746', 'union'], - ['8706', 'partial differential'], - ['8704', 'for all'], - ['8707', 'there exists'], - ['8709', 'diameter'], - ['8711', 'backward difference'], - ['8727', 'asterisk operator'], - ['8733', 'proportional to'], - ['8736', 'angle'], - // undefined - ['180', 'acute accent'], - ['184', 'cedilla'], - ['170', 'feminine ordinal indicator'], - ['186', 'masculine ordinal indicator'], - ['8224', 'dagger'], - ['8225', 'double dagger'], - // alphabetical special chars - ['192', 'A - grave'], - ['193', 'A - acute'], - ['194', 'A - circumflex'], - ['195', 'A - tilde'], - ['196', 'A - diaeresis'], - ['197', 'A - ring above'], - ['198', 'ligature AE'], - ['199', 'C - cedilla'], - ['200', 'E - grave'], - ['201', 'E - acute'], - ['202', 'E - circumflex'], - ['203', 'E - diaeresis'], - ['204', 'I - grave'], - ['205', 'I - acute'], - ['206', 'I - circumflex'], - ['207', 'I - diaeresis'], - ['208', 'ETH'], - ['209', 'N - tilde'], - ['210', 'O - grave'], - ['211', 'O - acute'], - ['212', 'O - circumflex'], - ['213', 'O - tilde'], - ['214', 'O - diaeresis'], - ['216', 'O - slash'], - ['338', 'ligature OE'], - ['352', 'S - caron'], - ['217', 'U - grave'], - ['218', 'U - acute'], - ['219', 'U - circumflex'], - ['220', 'U - diaeresis'], - ['221', 'Y - acute'], - ['376', 'Y - diaeresis'], - ['222', 'THORN'], - ['224', 'a - grave'], - ['225', 'a - acute'], - ['226', 'a - circumflex'], - ['227', 'a - tilde'], - ['228', 'a - diaeresis'], - ['229', 'a - ring above'], - ['230', 'ligature ae'], - ['231', 'c - cedilla'], - ['232', 'e - grave'], - ['233', 'e - acute'], - ['234', 'e - circumflex'], - ['235', 'e - diaeresis'], - ['236', 'i - grave'], - ['237', 'i - acute'], - ['238', 'i - circumflex'], - ['239', 'i - diaeresis'], - ['240', 'eth'], - ['241', 'n - tilde'], - ['242', 'o - grave'], - ['243', 'o - acute'], - ['244', 'o - circumflex'], - ['245', 'o - tilde'], - ['246', 'o - diaeresis'], - ['248', 'o slash'], - ['339', 'ligature oe'], - ['353', 's - caron'], - ['249', 'u - grave'], - ['250', 'u - acute'], - ['251', 'u - circumflex'], - ['252', 'u - diaeresis'], - ['253', 'y - acute'], - ['254', 'thorn'], - ['255', 'y - diaeresis'], - ['913', 'Alpha'], - ['914', 'Beta'], - ['915', 'Gamma'], - ['916', 'Delta'], - ['917', 'Epsilon'], - ['918', 'Zeta'], - ['919', 'Eta'], - ['920', 'Theta'], - ['921', 'Iota'], - ['922', 'Kappa'], - ['923', 'Lambda'], - ['924', 'Mu'], - ['925', 'Nu'], - ['926', 'Xi'], - ['927', 'Omicron'], - ['928', 'Pi'], - ['929', 'Rho'], - ['931', 'Sigma'], - ['932', 'Tau'], - ['933', 'Upsilon'], - ['934', 'Phi'], - ['935', 'Chi'], - ['936', 'Psi'], - ['937', 'Omega'], - ['945', 'alpha'], - ['946', 'beta'], - ['947', 'gamma'], - ['948', 'delta'], - ['949', 'epsilon'], - ['950', 'zeta'], - ['951', 'eta'], - ['952', 'theta'], - ['953', 'iota'], - ['954', 'kappa'], - ['955', 'lambda'], - ['956', 'mu'], - ['957', 'nu'], - ['958', 'xi'], - ['959', 'omicron'], - ['960', 'pi'], - ['961', 'rho'], - ['962', 'final sigma'], - ['963', 'sigma'], - ['964', 'tau'], - ['965', 'upsilon'], - ['966', 'phi'], - ['967', 'chi'], - ['968', 'psi'], - ['969', 'omega'], - // symbols - ['8501', 'alef symbol'], - ['982', 'pi symbol'], - ['8476', 'real part symbol'], - ['978', 'upsilon - hook symbol'], - ['8472', 'Weierstrass p'], - ['8465', 'imaginary part'], - // arrows - ['8592', 'leftwards arrow'], - ['8593', 'upwards arrow'], - ['8594', 'rightwards arrow'], - ['8595', 'downwards arrow'], - ['8596', 'left right arrow'], - ['8629', 'carriage return'], - ['8656', 'leftwards double arrow'], - ['8657', 'upwards double arrow'], - ['8658', 'rightwards double arrow'], - ['8659', 'downwards double arrow'], - ['8660', 'left right double arrow'], - ['8756', 'therefore'], - ['8834', 'subset of'], - ['8835', 'superset of'], - ['8836', 'not a subset of'], - ['8838', 'subset of or equal to'], - ['8839', 'superset of or equal to'], - ['8853', 'circled plus'], - ['8855', 'circled times'], - ['8869', 'perpendicular'], - ['8901', 'dot operator'], - ['8968', 'left ceiling'], - ['8969', 'right ceiling'], - ['8970', 'left floor'], - ['8971', 'right floor'], - ['9001', 'left-pointing angle bracket'], - ['9002', 'right-pointing angle bracket'], - ['9674', 'lozenge'], - ['9824', 'black spade suit'], - ['9827', 'black club suit'], - ['9829', 'black heart suit'], - ['9830', 'black diamond suit'], - ['8194', 'en space'], - ['8195', 'em space'], - ['8201', 'thin space'], - ['8204', 'zero width non-joiner'], - ['8205', 'zero width joiner'], - ['8206', 'left-to-right mark'], - ['8207', 'right-to-left mark'], - ['173', 'soft hyphen'] - ]; + var nativeSlice = Array.prototype.slice; + var nativePush = Array.prototype.push; + var map = function (xs, f) { + var len = xs.length; + var r = new Array(len); + for (var i = 0; i < len; i++) { + var x = xs[i]; + r[i] = f(x, i); + } + return r; + }; + var each = function (xs, f) { + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + f(x, i); + } + }; + var find = function (xs, pred) { + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + if (pred(x, i)) { + return Option.some(x); + } + } + return Option.none(); + }; + var flatten = function (xs) { + var r = []; + for (var i = 0, len = xs.length; i < len; ++i) { + if (!isArray(xs[i])) { + throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs); + } + nativePush.apply(r, xs[i]); + } + return r; + }; + var bind = function (xs, f) { + var output = map(xs, f); + return flatten(output); + }; + var from$1 = isFunction(Array.from) ? Array.from : function (x) { + return nativeSlice.call(x); + }; - function showDialog() { - var gridHtml, x, y, win; + var isArray$1 = global$1.isArray; + var UserDefined = 'User Defined'; + var getDefaultCharMap = function () { + return [ + { + name: 'Currency', + characters: [ + [ + 36, + 'dollar sign' + ], + [ + 162, + 'cent sign' + ], + [ + 8364, + 'euro sign' + ], + [ + 163, + 'pound sign' + ], + [ + 165, + 'yen sign' + ], + [ + 164, + 'currency sign' + ], + [ + 8352, + 'euro-currency sign' + ], + [ + 8353, + 'colon sign' + ], + [ + 8354, + 'cruzeiro sign' + ], + [ + 8355, + 'french franc sign' + ], + [ + 8356, + 'lira sign' + ], + [ + 8357, + 'mill sign' + ], + [ + 8358, + 'naira sign' + ], + [ + 8359, + 'peseta sign' + ], + [ + 8360, + 'rupee sign' + ], + [ + 8361, + 'won sign' + ], + [ + 8362, + 'new sheqel sign' + ], + [ + 8363, + 'dong sign' + ], + [ + 8365, + 'kip sign' + ], + [ + 8366, + 'tugrik sign' + ], + [ + 8367, + 'drachma sign' + ], + [ + 8368, + 'german penny symbol' + ], + [ + 8369, + 'peso sign' + ], + [ + 8370, + 'guarani sign' + ], + [ + 8371, + 'austral sign' + ], + [ + 8372, + 'hryvnia sign' + ], + [ + 8373, + 'cedi sign' + ], + [ + 8374, + 'livre tournois sign' + ], + [ + 8375, + 'spesmilo sign' + ], + [ + 8376, + 'tenge sign' + ], + [ + 8377, + 'indian rupee sign' + ], + [ + 8378, + 'turkish lira sign' + ], + [ + 8379, + 'nordic mark sign' + ], + [ + 8380, + 'manat sign' + ], + [ + 8381, + 'ruble sign' + ], + [ + 20870, + 'yen character' + ], + [ + 20803, + 'yuan character' + ], + [ + 22291, + 'yuan character, in hong kong and taiwan' + ], + [ + 22278, + 'yen/yuan character variant one' + ] + ] + }, + { + name: 'Text', + characters: [ + [ + 169, + 'copyright sign' + ], + [ + 174, + 'registered sign' + ], + [ + 8482, + 'trade mark sign' + ], + [ + 8240, + 'per mille sign' + ], + [ + 181, + 'micro sign' + ], + [ + 183, + 'middle dot' + ], + [ + 8226, + 'bullet' + ], + [ + 8230, + 'three dot leader' + ], + [ + 8242, + 'minutes / feet' + ], + [ + 8243, + 'seconds / inches' + ], + [ + 167, + 'section sign' + ], + [ + 182, + 'paragraph sign' + ], + [ + 223, + 'sharp s / ess-zed' + ] + ] + }, + { + name: 'Quotations', + characters: [ + [ + 8249, + 'single left-pointing angle quotation mark' + ], + [ + 8250, + 'single right-pointing angle quotation mark' + ], + [ + 171, + 'left pointing guillemet' + ], + [ + 187, + 'right pointing guillemet' + ], + [ + 8216, + 'left single quotation mark' + ], + [ + 8217, + 'right single quotation mark' + ], + [ + 8220, + 'left double quotation mark' + ], + [ + 8221, + 'right double quotation mark' + ], + [ + 8218, + 'single low-9 quotation mark' + ], + [ + 8222, + 'double low-9 quotation mark' + ], + [ + 60, + 'less-than sign' + ], + [ + 62, + 'greater-than sign' + ], + [ + 8804, + 'less-than or equal to' + ], + [ + 8805, + 'greater-than or equal to' + ], + [ + 8211, + 'en dash' + ], + [ + 8212, + 'em dash' + ], + [ + 175, + 'macron' + ], + [ + 8254, + 'overline' + ], + [ + 164, + 'currency sign' + ], + [ + 166, + 'broken bar' + ], + [ + 168, + 'diaeresis' + ], + [ + 161, + 'inverted exclamation mark' + ], + [ + 191, + 'turned question mark' + ], + [ + 710, + 'circumflex accent' + ], + [ + 732, + 'small tilde' + ], + [ + 176, + 'degree sign' + ], + [ + 8722, + 'minus sign' + ], + [ + 177, + 'plus-minus sign' + ], + [ + 247, + 'division sign' + ], + [ + 8260, + 'fraction slash' + ], + [ + 215, + 'multiplication sign' + ], + [ + 185, + 'superscript one' + ], + [ + 178, + 'superscript two' + ], + [ + 179, + 'superscript three' + ], + [ + 188, + 'fraction one quarter' + ], + [ + 189, + 'fraction one half' + ], + [ + 190, + 'fraction three quarters' + ] + ] + }, + { + name: 'Mathematical', + characters: [ + [ + 402, + 'function / florin' + ], + [ + 8747, + 'integral' + ], + [ + 8721, + 'n-ary sumation' + ], + [ + 8734, + 'infinity' + ], + [ + 8730, + 'square root' + ], + [ + 8764, + 'similar to' + ], + [ + 8773, + 'approximately equal to' + ], + [ + 8776, + 'almost equal to' + ], + [ + 8800, + 'not equal to' + ], + [ + 8801, + 'identical to' + ], + [ + 8712, + 'element of' + ], + [ + 8713, + 'not an element of' + ], + [ + 8715, + 'contains as member' + ], + [ + 8719, + 'n-ary product' + ], + [ + 8743, + 'logical and' + ], + [ + 8744, + 'logical or' + ], + [ + 172, + 'not sign' + ], + [ + 8745, + 'intersection' + ], + [ + 8746, + 'union' + ], + [ + 8706, + 'partial differential' + ], + [ + 8704, + 'for all' + ], + [ + 8707, + 'there exists' + ], + [ + 8709, + 'diameter' + ], + [ + 8711, + 'backward difference' + ], + [ + 8727, + 'asterisk operator' + ], + [ + 8733, + 'proportional to' + ], + [ + 8736, + 'angle' + ] + ] + }, + { + name: 'Extended Latin', + characters: [ + [ + 192, + 'A - grave' + ], + [ + 193, + 'A - acute' + ], + [ + 194, + 'A - circumflex' + ], + [ + 195, + 'A - tilde' + ], + [ + 196, + 'A - diaeresis' + ], + [ + 197, + 'A - ring above' + ], + [ + 256, + 'A - macron' + ], + [ + 198, + 'ligature AE' + ], + [ + 199, + 'C - cedilla' + ], + [ + 200, + 'E - grave' + ], + [ + 201, + 'E - acute' + ], + [ + 202, + 'E - circumflex' + ], + [ + 203, + 'E - diaeresis' + ], + [ + 274, + 'E - macron' + ], + [ + 204, + 'I - grave' + ], + [ + 205, + 'I - acute' + ], + [ + 206, + 'I - circumflex' + ], + [ + 207, + 'I - diaeresis' + ], + [ + 298, + 'I - macron' + ], + [ + 208, + 'ETH' + ], + [ + 209, + 'N - tilde' + ], + [ + 210, + 'O - grave' + ], + [ + 211, + 'O - acute' + ], + [ + 212, + 'O - circumflex' + ], + [ + 213, + 'O - tilde' + ], + [ + 214, + 'O - diaeresis' + ], + [ + 216, + 'O - slash' + ], + [ + 332, + 'O - macron' + ], + [ + 338, + 'ligature OE' + ], + [ + 352, + 'S - caron' + ], + [ + 217, + 'U - grave' + ], + [ + 218, + 'U - acute' + ], + [ + 219, + 'U - circumflex' + ], + [ + 220, + 'U - diaeresis' + ], + [ + 362, + 'U - macron' + ], + [ + 221, + 'Y - acute' + ], + [ + 376, + 'Y - diaeresis' + ], + [ + 562, + 'Y - macron' + ], + [ + 222, + 'THORN' + ], + [ + 224, + 'a - grave' + ], + [ + 225, + 'a - acute' + ], + [ + 226, + 'a - circumflex' + ], + [ + 227, + 'a - tilde' + ], + [ + 228, + 'a - diaeresis' + ], + [ + 229, + 'a - ring above' + ], + [ + 257, + 'a - macron' + ], + [ + 230, + 'ligature ae' + ], + [ + 231, + 'c - cedilla' + ], + [ + 232, + 'e - grave' + ], + [ + 233, + 'e - acute' + ], + [ + 234, + 'e - circumflex' + ], + [ + 235, + 'e - diaeresis' + ], + [ + 275, + 'e - macron' + ], + [ + 236, + 'i - grave' + ], + [ + 237, + 'i - acute' + ], + [ + 238, + 'i - circumflex' + ], + [ + 239, + 'i - diaeresis' + ], + [ + 299, + 'i - macron' + ], + [ + 240, + 'eth' + ], + [ + 241, + 'n - tilde' + ], + [ + 242, + 'o - grave' + ], + [ + 243, + 'o - acute' + ], + [ + 244, + 'o - circumflex' + ], + [ + 245, + 'o - tilde' + ], + [ + 246, + 'o - diaeresis' + ], + [ + 248, + 'o slash' + ], + [ + 333, + 'o macron' + ], + [ + 339, + 'ligature oe' + ], + [ + 353, + 's - caron' + ], + [ + 249, + 'u - grave' + ], + [ + 250, + 'u - acute' + ], + [ + 251, + 'u - circumflex' + ], + [ + 252, + 'u - diaeresis' + ], + [ + 363, + 'u - macron' + ], + [ + 253, + 'y - acute' + ], + [ + 254, + 'thorn' + ], + [ + 255, + 'y - diaeresis' + ], + [ + 563, + 'y - macron' + ], + [ + 913, + 'Alpha' + ], + [ + 914, + 'Beta' + ], + [ + 915, + 'Gamma' + ], + [ + 916, + 'Delta' + ], + [ + 917, + 'Epsilon' + ], + [ + 918, + 'Zeta' + ], + [ + 919, + 'Eta' + ], + [ + 920, + 'Theta' + ], + [ + 921, + 'Iota' + ], + [ + 922, + 'Kappa' + ], + [ + 923, + 'Lambda' + ], + [ + 924, + 'Mu' + ], + [ + 925, + 'Nu' + ], + [ + 926, + 'Xi' + ], + [ + 927, + 'Omicron' + ], + [ + 928, + 'Pi' + ], + [ + 929, + 'Rho' + ], + [ + 931, + 'Sigma' + ], + [ + 932, + 'Tau' + ], + [ + 933, + 'Upsilon' + ], + [ + 934, + 'Phi' + ], + [ + 935, + 'Chi' + ], + [ + 936, + 'Psi' + ], + [ + 937, + 'Omega' + ], + [ + 945, + 'alpha' + ], + [ + 946, + 'beta' + ], + [ + 947, + 'gamma' + ], + [ + 948, + 'delta' + ], + [ + 949, + 'epsilon' + ], + [ + 950, + 'zeta' + ], + [ + 951, + 'eta' + ], + [ + 952, + 'theta' + ], + [ + 953, + 'iota' + ], + [ + 954, + 'kappa' + ], + [ + 955, + 'lambda' + ], + [ + 956, + 'mu' + ], + [ + 957, + 'nu' + ], + [ + 958, + 'xi' + ], + [ + 959, + 'omicron' + ], + [ + 960, + 'pi' + ], + [ + 961, + 'rho' + ], + [ + 962, + 'final sigma' + ], + [ + 963, + 'sigma' + ], + [ + 964, + 'tau' + ], + [ + 965, + 'upsilon' + ], + [ + 966, + 'phi' + ], + [ + 967, + 'chi' + ], + [ + 968, + 'psi' + ], + [ + 969, + 'omega' + ] + ] + }, + { + name: 'Symbols', + characters: [ + [ + 8501, + 'alef symbol' + ], + [ + 982, + 'pi symbol' + ], + [ + 8476, + 'real part symbol' + ], + [ + 978, + 'upsilon - hook symbol' + ], + [ + 8472, + 'Weierstrass p' + ], + [ + 8465, + 'imaginary part' + ] + ] + }, + { + name: 'Arrows', + characters: [ + [ + 8592, + 'leftwards arrow' + ], + [ + 8593, + 'upwards arrow' + ], + [ + 8594, + 'rightwards arrow' + ], + [ + 8595, + 'downwards arrow' + ], + [ + 8596, + 'left right arrow' + ], + [ + 8629, + 'carriage return' + ], + [ + 8656, + 'leftwards double arrow' + ], + [ + 8657, + 'upwards double arrow' + ], + [ + 8658, + 'rightwards double arrow' + ], + [ + 8659, + 'downwards double arrow' + ], + [ + 8660, + 'left right double arrow' + ], + [ + 8756, + 'therefore' + ], + [ + 8834, + 'subset of' + ], + [ + 8835, + 'superset of' + ], + [ + 8836, + 'not a subset of' + ], + [ + 8838, + 'subset of or equal to' + ], + [ + 8839, + 'superset of or equal to' + ], + [ + 8853, + 'circled plus' + ], + [ + 8855, + 'circled times' + ], + [ + 8869, + 'perpendicular' + ], + [ + 8901, + 'dot operator' + ], + [ + 8968, + 'left ceiling' + ], + [ + 8969, + 'right ceiling' + ], + [ + 8970, + 'left floor' + ], + [ + 8971, + 'right floor' + ], + [ + 9001, + 'left-pointing angle bracket' + ], + [ + 9002, + 'right-pointing angle bracket' + ], + [ + 9674, + 'lozenge' + ], + [ + 9824, + 'black spade suit' + ], + [ + 9827, + 'black club suit' + ], + [ + 9829, + 'black heart suit' + ], + [ + 9830, + 'black diamond suit' + ], + [ + 8194, + 'en space' + ], + [ + 8195, + 'em space' + ], + [ + 8201, + 'thin space' + ], + [ + 8204, + 'zero width non-joiner' + ], + [ + 8205, + 'zero width joiner' + ], + [ + 8206, + 'left-to-right mark' + ], + [ + 8207, + 'right-to-left mark' + ] + ] + } + ]; + }; + var charmapFilter = function (charmap) { + return global$1.grep(charmap, function (item) { + return isArray$1(item) && item.length === 2; + }); + }; + var getCharsFromSetting = function (settingValue) { + if (isArray$1(settingValue)) { + return [].concat(charmapFilter(settingValue)); + } + if (typeof settingValue === 'function') { + return settingValue(); + } + return []; + }; + var extendCharMap = function (editor, charmap) { + var userCharMap = Settings.getCharMap(editor); + if (userCharMap) { + charmap = [{ + name: UserDefined, + characters: getCharsFromSetting(userCharMap) + }]; + } + var userCharMapAppend = Settings.getCharMapAppend(editor); + if (userCharMapAppend) { + var userDefinedGroup = global$1.grep(charmap, function (cg) { + return cg.name === UserDefined; + }); + if (userDefinedGroup.length) { + userDefinedGroup[0].characters = [].concat(userDefinedGroup[0].characters).concat(getCharsFromSetting(userCharMapAppend)); + return charmap; + } + return [].concat(charmap).concat({ + name: UserDefined, + characters: getCharsFromSetting(userCharMapAppend) + }); + } + return charmap; + }; + var getCharMap$1 = function (editor) { + var groups = extendCharMap(editor, getDefaultCharMap()); + return groups.length > 1 ? [{ + name: 'All', + characters: bind(groups, function (g) { + return g.characters; + }) + }].concat(groups) : groups; + }; + var CharMap = { getCharMap: getCharMap$1 }; - function getParentTd(elm) { - while (elm) { - if (elm.nodeName == 'TD') { - return elm; - } + var get = function (editor) { + var getCharMap = function () { + return CharMap.getCharMap(editor); + }; + var insertChar = function (chr) { + Actions.insertChar(editor, chr); + }; + return { + getCharMap: getCharMap, + insertChar: insertChar + }; + }; + var Api = { get: get }; - elm = elm.parentNode; - } - } + var Cell = function (initial) { + var value = initial; + var get = function () { + return value; + }; + var set = function (v) { + value = v; + }; + var clone = function () { + return Cell(get()); + }; + return { + get: get, + set: set, + clone: clone + }; + }; - gridHtml = '
'; + var last = function (fn, rate) { + var timer = null; + var cancel = function () { + if (timer !== null) { + domGlobals.clearTimeout(timer); + timer = null; + } + }; + var throttle = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + if (timer !== null) { + domGlobals.clearTimeout(timer); + } + timer = domGlobals.setTimeout(function () { + fn.apply(null, args); + timer = null; + }, rate); + }; + return { + cancel: cancel, + throttle: throttle + }; + }; - for (y = 0; y < 10; y++) { - gridHtml += '
'; + var global$2 = tinymce.util.Tools.resolve('tinymce.util.Promise'); - var charMapPanel = { - type: 'container', - html: gridHtml, - onclick: function(e) { - var target = e.target; - if (target.nodeName == 'DIV') { - editor.execCommand('mceInsertContent', false, target.firstChild.nodeValue); - } - }, - onmouseover: function(e) { - var td = getParentTd(e.target); + var init = function (editor, all) { + editor.ui.registry.addAutocompleter('charmap', { + ch: ':', + columns: 'auto', + minChars: 2, + fetch: function (pattern, maxResults) { + return new global$2(function (resolve, reject) { + resolve(Scan.scan(all, pattern)); + }); + }, + onAction: function (autocompleteApi, rng, value) { + editor.selection.setRng(rng); + editor.insertContent(value); + autocompleteApi.hide(); + } + }); + }; - if (td) { - win.find('#preview').text(td.firstChild.firstChild.data); - } - } - }; + var register$1 = function (editor) { + editor.ui.registry.addButton('charmap', { + icon: 'insert-character', + tooltip: 'Special character', + onAction: function () { + return editor.execCommand('mceShowCharmap'); + } + }); + editor.ui.registry.addMenuItem('charmap', { + icon: 'insert-character', + text: 'Special character...', + onAction: function () { + return editor.execCommand('mceShowCharmap'); + } + }); + }; + var Buttons = { register: register$1 }; - win = editor.windowManager.open({ - title: "Special characters", - spacing: 10, - padding: 10, - items: [ - charMapPanel, - { - type: 'label', - name: 'preview', - text: ' ', - style: 'font-size: 40px; text-align: center', - border: 1, - minWidth: 100, - minHeight: 80 - } - ], - buttons: [ - {text: "Close", onclick: function() { - win.close(); - }} - ] - }); - } + function Plugin () { + global.add('charmap', function (editor) { + var charMap = CharMap.getCharMap(editor); + Commands.register(editor, charMap); + Buttons.register(editor); + init(editor, charMap[0]); + return Api.get(editor); + }); + } - editor.addButton('charmap', { - icon: 'charmap', - tooltip: 'Insert special character', - onclick: showDialog - }); + Plugin(); - editor.addMenuItem('charmap', { - icon: 'charmap', - text: 'Special character', - onclick: showDialog, - context: 'insert' - }); -}); \ No newline at end of file +}(window)); diff --git a/lib/tinymce/js/tinymce/plugins/charmap/plugin.min.js b/lib/tinymce/js/tinymce/plugins/charmap/plugin.min.js index c491c904..6afb56a4 100644 --- a/lib/tinymce/js/tinymce/plugins/charmap/plugin.min.js +++ b/lib/tinymce/js/tinymce/plugins/charmap/plugin.min.js @@ -1 +1,9 @@ -tinymce.PluginManager.add("charmap",function(e){function t(){function t(e){for(;e;){if("TD"==e.nodeName)return e;e=e.parentNode}}var o,i,a,r;for(o=''; + var contains = function (str, substr) { + return str.indexOf(substr) !== -1; + }; - for (x = 0; x < 20; x++) { - var chr = charmap[y * 10 + x]; - var id = 'g' + (y * 10 + x); + var charMatches = function (charCode, name, lowerCasePattern) { + if (contains(String.fromCharCode(charCode).toLowerCase(), lowerCasePattern)) { + return true; + } else { + return contains(name.toLowerCase(), lowerCasePattern) || contains(name.toLowerCase().replace(/\s+/g, ''), lowerCasePattern); + } + }; + var scan = function (group, pattern) { + var matches = []; + var lowerCasePattern = pattern.toLowerCase(); + each(group.characters, function (g) { + if (charMatches(g[0], g[1], lowerCasePattern)) { + matches.push(g); + } + }); + return map(matches, function (m) { + return { + text: m[1], + value: String.fromCharCode(m[0]), + icon: String.fromCharCode(m[0]) + }; + }); + }; + var Scan = { scan: scan }; - gridHtml += ' '; - } + var register = function (editor, charMap) { + editor.addCommand('mceShowCharmap', function () { + Dialog.open(editor, charMap); + }); + }; + var Commands = { register: register }; - gridHtml += ''; - } + var patternName = 'pattern'; + var open = function (editor, charMap) { + var makeGroupItems = function () { + return [ + { + label: 'Search', + type: 'input', + name: patternName + }, + { + type: 'collection', + name: 'results' + } + ]; + }; + var makeTabs = function () { + return map(charMap, function (charGroup) { + return { + title: charGroup.name, + name: charGroup.name, + items: makeGroupItems() + }; + }); + }; + var makePanel = function () { + return { + type: 'panel', + items: makeGroupItems() + }; + }; + var makeTabPanel = function () { + return { + type: 'tabpanel', + tabs: makeTabs() + }; + }; + var currentTab = charMap.length === 1 ? Cell(UserDefined) : Cell('All'); + var scanAndSet = function (dialogApi, pattern) { + find(charMap, function (group) { + return group.name === currentTab.get(); + }).each(function (f) { + var items = Scan.scan(f, pattern); + dialogApi.setData({ results: items }); + }); + }; + var SEARCH_DELAY = 40; + var updateFilter = last(function (dialogApi) { + var pattern = dialogApi.getData().pattern; + scanAndSet(dialogApi, pattern); + }, SEARCH_DELAY); + var body = charMap.length === 1 ? makePanel() : makeTabPanel(); + var initialData = { + pattern: '', + results: Scan.scan(charMap[0], '') + }; + var bridgeSpec = { + title: 'Special Character', + size: 'normal', + body: body, + buttons: [{ + type: 'cancel', + name: 'close', + text: 'Close', + primary: true + }], + initialData: initialData, + onAction: function (api, details) { + if (details.name === 'results') { + Actions.insertChar(editor, details.value); + api.close(); + } + }, + onTabChange: function (dialogApi, details) { + currentTab.set(details.newTabName); + updateFilter.throttle(dialogApi); + }, + onChange: function (dialogApi, changeData) { + if (changeData.name === patternName) { + updateFilter.throttle(dialogApi); + } + } + }; + var dialogApi = editor.windowManager.open(bridgeSpec); + dialogApi.focus(patternName); + }; + var Dialog = { open: open }; - gridHtml += ' ' + - (chr ? String.fromCharCode(parseInt(chr[0], 10)) : ' ') + '',a=0;10>a;a++){for(o+="
";var c={type:"container",html:o,onclick:function(t){var n=t.target;"DIV"==n.nodeName&&e.execCommand("mceInsertContent",!1,n.firstChild.nodeValue)},onmouseover:function(e){var n=t(e.target);n&&r.find("#preview").text(n.firstChild.firstChild.data)}};r=e.windowManager.open({title:"Special characters",spacing:10,padding:10,items:[c,{type:"label",name:"preview",text:" ",style:"font-size: 40px; text-align: center",border:1,minWidth:100,minHeight:80}],buttons:[{text:"Close",onclick:function(){r.close()}}]})}var n=[["160","no-break space"],["38","ampersand"],["34","quotation mark"],["162","cent sign"],["8364","euro sign"],["163","pound sign"],["165","yen sign"],["169","copyright sign"],["174","registered sign"],["8482","trade mark sign"],["8240","per mille sign"],["181","micro sign"],["183","middle dot"],["8226","bullet"],["8230","three dot leader"],["8242","minutes / feet"],["8243","seconds / inches"],["167","section sign"],["182","paragraph sign"],["223","sharp s / ess-zed"],["8249","single left-pointing angle quotation mark"],["8250","single right-pointing angle quotation mark"],["171","left pointing guillemet"],["187","right pointing guillemet"],["8216","left single quotation mark"],["8217","right single quotation mark"],["8220","left double quotation mark"],["8221","right double quotation mark"],["8218","single low-9 quotation mark"],["8222","double low-9 quotation mark"],["60","less-than sign"],["62","greater-than sign"],["8804","less-than or equal to"],["8805","greater-than or equal to"],["8211","en dash"],["8212","em dash"],["175","macron"],["8254","overline"],["164","currency sign"],["166","broken bar"],["168","diaeresis"],["161","inverted exclamation mark"],["191","turned question mark"],["710","circumflex accent"],["732","small tilde"],["176","degree sign"],["8722","minus sign"],["177","plus-minus sign"],["247","division sign"],["8260","fraction slash"],["215","multiplication sign"],["185","superscript one"],["178","superscript two"],["179","superscript three"],["188","fraction one quarter"],["189","fraction one half"],["190","fraction three quarters"],["402","function / florin"],["8747","integral"],["8721","n-ary sumation"],["8734","infinity"],["8730","square root"],["8764","similar to"],["8773","approximately equal to"],["8776","almost equal to"],["8800","not equal to"],["8801","identical to"],["8712","element of"],["8713","not an element of"],["8715","contains as member"],["8719","n-ary product"],["8743","logical and"],["8744","logical or"],["172","not sign"],["8745","intersection"],["8746","union"],["8706","partial differential"],["8704","for all"],["8707","there exists"],["8709","diameter"],["8711","backward difference"],["8727","asterisk operator"],["8733","proportional to"],["8736","angle"],["180","acute accent"],["184","cedilla"],["170","feminine ordinal indicator"],["186","masculine ordinal indicator"],["8224","dagger"],["8225","double dagger"],["192","A - grave"],["193","A - acute"],["194","A - circumflex"],["195","A - tilde"],["196","A - diaeresis"],["197","A - ring above"],["198","ligature AE"],["199","C - cedilla"],["200","E - grave"],["201","E - acute"],["202","E - circumflex"],["203","E - diaeresis"],["204","I - grave"],["205","I - acute"],["206","I - circumflex"],["207","I - diaeresis"],["208","ETH"],["209","N - tilde"],["210","O - grave"],["211","O - acute"],["212","O - circumflex"],["213","O - tilde"],["214","O - diaeresis"],["216","O - slash"],["338","ligature OE"],["352","S - caron"],["217","U - grave"],["218","U - acute"],["219","U - circumflex"],["220","U - diaeresis"],["221","Y - acute"],["376","Y - diaeresis"],["222","THORN"],["224","a - grave"],["225","a - acute"],["226","a - circumflex"],["227","a - tilde"],["228","a - diaeresis"],["229","a - ring above"],["230","ligature ae"],["231","c - cedilla"],["232","e - grave"],["233","e - acute"],["234","e - circumflex"],["235","e - diaeresis"],["236","i - grave"],["237","i - acute"],["238","i - circumflex"],["239","i - diaeresis"],["240","eth"],["241","n - tilde"],["242","o - grave"],["243","o - acute"],["244","o - circumflex"],["245","o - tilde"],["246","o - diaeresis"],["248","o slash"],["339","ligature oe"],["353","s - caron"],["249","u - grave"],["250","u - acute"],["251","u - circumflex"],["252","u - diaeresis"],["253","y - acute"],["254","thorn"],["255","y - diaeresis"],["913","Alpha"],["914","Beta"],["915","Gamma"],["916","Delta"],["917","Epsilon"],["918","Zeta"],["919","Eta"],["920","Theta"],["921","Iota"],["922","Kappa"],["923","Lambda"],["924","Mu"],["925","Nu"],["926","Xi"],["927","Omicron"],["928","Pi"],["929","Rho"],["931","Sigma"],["932","Tau"],["933","Upsilon"],["934","Phi"],["935","Chi"],["936","Psi"],["937","Omega"],["945","alpha"],["946","beta"],["947","gamma"],["948","delta"],["949","epsilon"],["950","zeta"],["951","eta"],["952","theta"],["953","iota"],["954","kappa"],["955","lambda"],["956","mu"],["957","nu"],["958","xi"],["959","omicron"],["960","pi"],["961","rho"],["962","final sigma"],["963","sigma"],["964","tau"],["965","upsilon"],["966","phi"],["967","chi"],["968","psi"],["969","omega"],["8501","alef symbol"],["982","pi symbol"],["8476","real part symbol"],["978","upsilon - hook symbol"],["8472","Weierstrass p"],["8465","imaginary part"],["8592","leftwards arrow"],["8593","upwards arrow"],["8594","rightwards arrow"],["8595","downwards arrow"],["8596","left right arrow"],["8629","carriage return"],["8656","leftwards double arrow"],["8657","upwards double arrow"],["8658","rightwards double arrow"],["8659","downwards double arrow"],["8660","left right double arrow"],["8756","therefore"],["8834","subset of"],["8835","superset of"],["8836","not a subset of"],["8838","subset of or equal to"],["8839","superset of or equal to"],["8853","circled plus"],["8855","circled times"],["8869","perpendicular"],["8901","dot operator"],["8968","left ceiling"],["8969","right ceiling"],["8970","left floor"],["8971","right floor"],["9001","left-pointing angle bracket"],["9002","right-pointing angle bracket"],["9674","lozenge"],["9824","black spade suit"],["9827","black club suit"],["9829","black heart suit"],["9830","black diamond suit"],["8194","en space"],["8195","em space"],["8201","thin space"],["8204","zero width non-joiner"],["8205","zero width joiner"],["8206","left-to-right mark"],["8207","right-to-left mark"],["173","soft hyphen"]];e.addButton("charmap",{icon:"charmap",tooltip:"Insert special character",onclick:t}),e.addMenuItem("charmap",{icon:"charmap",text:"Special character",onclick:t,context:"insert"})}); \ No newline at end of file +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.1.6 (2020-01-28) + */ +!function(c){"use strict";function n(){}function i(n){return function(){return n}}function e(){return m}var r,t=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=function(n,e){return n.fire("insertCustomChar",{chr:e})},u=function(n,e){var r=a(n,e).chr;n.execCommand("mceInsertContent",!1,r)},o=tinymce.util.Tools.resolve("tinymce.util.Tools"),s=function(n){return n.settings.charmap},l=function(n){return n.settings.charmap_append},f=i(!1),g=i(!0),m=(r={fold:function(n,e){return n()},is:f,isSome:f,isNone:g,getOr:p,getOrThunk:d,getOrDie:function(n){throw new Error(n||"error: getOrDie called on none.")},getOrNull:i(null),getOrUndefined:i(undefined),or:p,orThunk:d,map:e,each:n,bind:e,exists:f,forall:g,filter:e,equals:h,equals_:h,toArray:function(){return[]},toString:i("none()")},Object.freeze&&Object.freeze(r),r);function h(n){return n.isNone()}function d(n){return n()}function p(n){return n}function y(e){return function(n){return function(n){if(null===n)return"null";var e=typeof n;return"object"==e&&(Array.prototype.isPrototypeOf(n)||n.constructor&&"Array"===n.constructor.name)?"array":"object"==e&&(String.prototype.isPrototypeOf(n)||n.constructor&&"String"===n.constructor.name)?"string":e}(n)===e}}function w(n,e){for(var r=n.length,t=new Array(r),a=0;a",i=0;20>i;i++){var s=n[10*a+i],l="g"+(10*a+i);o+=' "}o+=""}o+=" '+(s?String.fromCharCode(parseInt(s[0],10)):" ")+"text.length) { + break tokenloop; + } + if (str instanceof Token) { + continue; + } + pattern.lastIndex = 0; + var match = pattern.exec(str); + if (match) { + if (lookbehind) { + lookbehindLength = match[1].length; + } + var from = match.index - 1 + lookbehindLength; + match = match[0].slice(lookbehindLength); + var len = match.length, to = from + len, before = str.slice(0, from + 1), after = str.slice(to + 1); + var args = [ + i, + 1 + ]; + if (before) { + args.push(before); + } + var wrapped = new Token(token, inside ? _.tokenize(match, inside) : match, alias); + args.push(wrapped); + if (after) { + args.push(after); + } + Array.prototype.splice.apply(strarr, args); + } + } + } + } + return strarr; + }, + hooks: { + all: {}, + add: function (name, callback) { + var hooks = _.hooks.all; + hooks[name] = hooks[name] || []; + hooks[name].push(callback); + }, + run: function (name, env) { + var callbacks = _.hooks.all[name]; + if (!callbacks || !callbacks.length) { + return; + } + for (var i = 0, callback = void 0; callback = callbacks[i++];) { + callback(env); + } + } + } + }; + var Token = _.Token = function (type, content, alias) { + this.type = type; + this.content = content; + this.alias = alias; + }; + Token.stringify = function (o, language, parent) { + if (typeof o === 'string') { + return o; + } + if (_.util.type(o) === 'Array') { + return o.map(function (element) { + return Token.stringify(element, language, o); + }).join(''); + } + var env = { + type: o.type, + content: Token.stringify(o.content, language, parent), + tag: 'span', + classes: [ + 'token', + o.type + ], + attributes: {}, + language: language, + parent: parent + }; + if (env.type === 'comment') { + env.attributes.spellcheck = 'true'; + } + if (o.alias) { + var aliases = _.util.type(o.alias) === 'Array' ? o.alias : [o.alias]; + Array.prototype.push.apply(env.classes, aliases); + } + _.hooks.run('wrap', env); + var attributes = ''; + for (var name in env.attributes) { + attributes += (attributes ? ' ' : '') + name + '="' + (env.attributes[name] || '') + '"'; + } + return '<' + env.tag + ' class="' + env.classes.join(' ') + '" ' + attributes + '>' + env.content + '' + env.tag + '>'; + }; + if (!_self.document) { + if (!_self.addEventListener) { + return _self.Prism; + } + _self.addEventListener('message', function (evt) { + var message = JSON.parse(evt.data), lang = message.language, code = message.code, immediateClose = message.immediateClose; + _self.postMessage(_.highlight(code, _.languages[lang], lang)); + if (immediateClose) { + _self.close(); + } + }, false); + return _self.Prism; + } + }(); + if (typeof global$2 !== 'undefined') { + global$2.Prism = Prism; + } + Prism.languages.markup = { + comment: //, + prolog: /<\?[\w\W]+?\?>/, + doctype: //, + cdata: //i, + tag: { + pattern: /<\/?[^\s>\/=.]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i, + inside: { + 'tag': { + pattern: /^<\/?[^\s>\/]+/i, + inside: { + punctuation: /^<\/?/, + namespace: /^[^\s>\/:]+:/ + } + }, + 'attr-value': { + pattern: /=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i, + inside: { punctuation: /[=>"']/ } + }, + 'punctuation': /\/?>/, + 'attr-name': { + pattern: /[^\s>\/]+/, + inside: { namespace: /^[^\s>\/:]+:/ } + } + } + }, + entity: /?[\da-z]{1,8};/i + }; + Prism.hooks.add('wrap', function (env) { + if (env.type === 'entity') { + env.attributes.title = env.content.replace(/&/, '&'); + } + }); + Prism.languages.xml = Prism.languages.markup; + Prism.languages.html = Prism.languages.markup; + Prism.languages.mathml = Prism.languages.markup; + Prism.languages.svg = Prism.languages.markup; + Prism.languages.css = { + comment: /\/\*[\w\W]*?\*\//, + atrule: { + pattern: /@[\w-]+?.*?(;|(?=\s*\{))/i, + inside: { rule: /@[\w-]+/ } + }, + url: /url\((?:(["'])(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1|.*?)\)/i, + selector: /[^\{\}\s][^\{\};]*?(?=\s*\{)/, + string: /("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/, + property: /(\b|\B)[\w-]+(?=\s*:)/i, + important: /\B!important\b/i, + function: /[-a-z0-9]+(?=\()/i, + punctuation: /[(){};:]/ + }; + Prism.languages.css.atrule.inside.rest = Prism.util.clone(Prism.languages.css); + if (Prism.languages.markup) { + Prism.languages.insertBefore('markup', 'tag', { + style: { + pattern: /'; + } + var cors = Settings.shouldUseContentCssCors(editor) ? ' crossorigin="anonymous"' : ''; + global$1.each(editor.contentCSS, function (url) { + headHtml += ''; + }); + var bodyId = editor.settings.body_id || 'tinymce'; + 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 isMetaKeyPressed = global$2.mac ? 'e.metaKey' : 'e.ctrlKey && !e.altKey'; + var preventClicksOnLinksScript = ' '; + var directionality = editor.getBody().dir; + var dirAttr = directionality ? ' dir="' + encode(directionality) + '"' : ''; + var previewHtml = '' + '' + '' + headHtml + '' + '' + editor.getContent() + preventClicksOnLinksScript + '' + ''; + return previewHtml; + }; + var IframeContent = { getPreviewHtml: getPreviewHtml }; + + var open = function (editor) { + var content = IframeContent.getPreviewHtml(editor); + var dataApi = editor.windowManager.open({ + title: 'Preview', + size: 'large', + body: { + type: 'panel', + items: [{ + name: 'preview', + type: 'iframe', + sandboxed: true + }] + }, + buttons: [{ + type: 'cancel', + name: 'close', + text: 'Close', + primary: true + }], + initialData: { preview: content } + }); + dataApi.focus('close'); + }; + + var register = function (editor) { + editor.addCommand('mcePreview', function () { + open(editor); + }); + }; + var Commands = { register: register }; + + var register$1 = function (editor) { + editor.ui.registry.addButton('preview', { + icon: 'preview', + tooltip: 'Preview', + onAction: function () { + return editor.execCommand('mcePreview'); + } + }); + editor.ui.registry.addMenuItem('preview', { + icon: 'preview', + text: 'Preview', + onAction: function () { + return editor.execCommand('mcePreview'); + } + }); + }; + var Buttons = { register: register$1 }; + + function Plugin () { + global.add('preview', function (editor) { + Commands.register(editor); + Buttons.register(editor); + }); + } + + Plugin(); -/*global tinymce:true */ - -tinymce.PluginManager.add('preview', function(editor) { - editor.addCommand('mcePreview', function() { - editor.windowManager.open({ - title: 'Preview', - width : parseInt(editor.getParam("plugin_preview_width", "650"), 10), - height : parseInt(editor.getParam("plugin_preview_height", "500"), 10), - html: '', - buttons: { - text: 'Close', - onclick: function() { - this.parent().parent().close(); - } - }, - onPostRender: function() { - var doc = this.getEl('body').firstChild.contentWindow.document, previewHtml, headHtml = ''; - - tinymce.each(tinymce.explode(editor.settings.content_css), function(url) { - headHtml += ''; - }); - - previewHtml = ( - '' + - '' + - '' + - headHtml + - '' + - '' + - editor.getContent() + - '' + - '' - ); - - doc.open(); - doc.write(previewHtml); - doc.close(); - } - }); - }); - - editor.addButton('preview', { - title : 'Preview', - cmd : 'mcePreview' - }); - - editor.addMenuItem('preview', { - text : 'Preview', - cmd : 'mcePreview', - context: 'view' - }); -}); +}()); diff --git a/lib/tinymce/js/tinymce/plugins/preview/plugin.min.js b/lib/tinymce/js/tinymce/plugins/preview/plugin.min.js index a16b2593..df7741df 100644 --- a/lib/tinymce/js/tinymce/plugins/preview/plugin.min.js +++ b/lib/tinymce/js/tinymce/plugins/preview/plugin.min.js @@ -1 +1,9 @@ -tinymce.PluginManager.add("preview",function(e){e.addCommand("mcePreview",function(){e.windowManager.open({title:"Preview",width:parseInt(e.getParam("plugin_preview_width","650"),10),height:parseInt(e.getParam("plugin_preview_height","500"),10),html:"",buttons:{text:"Close",onclick:function(){this.parent().parent().close()}},onPostRender:function(){var t,n=this.getEl("body").firstChild.contentWindow.document,i="";tinymce.each(tinymce.explode(e.settings.content_css),function(t){i+=''}),t=""+i+""+""+e.getContent()+""+"",n.open(),n.write(t),n.close()}})}),e.addButton("preview",{title:"Preview",cmd:"mcePreview"}),e.addMenuItem("preview",{text:"Preview",cmd:"mcePreview",context:"view"})}); \ No newline at end of file +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.1.6 (2020-01-28) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),l=tinymce.util.Tools.resolve("tinymce.util.Tools"),m=function(e){return e.getParam("content_style","")},u=function(e){return e.getParam("content_css_cors",!1,"boolean")},y=tinymce.util.Tools.resolve("tinymce.Env"),n=function(t){var n="",i=t.dom.encode,e=m(t);n+=' ',e&&(n+='");var o=u(t)?' crossorigin="anonymous"':"";l.each(t.contentCSS,function(e){n+='"});var r=t.settings.body_id||"tinymce";-1!==r.indexOf("=")&&(r=(r=t.getParam("body_id","","hash"))[t.id]||r);var a=t.settings.body_class||"";-1!==a.indexOf("=")&&(a=(a=t.getParam("body_class","","hash"))[t.id]||"");var c='\n'; - moduleCount++; - } - - // Expose globally - exports.define = define; - exports.require = require; - - expose(["tinymce/spellcheckerplugin/DomTextMatcher","tinymce/spellcheckerplugin/Plugin"]); - - load('classes/DomTextMatcher.js'); - load('classes/Plugin.js'); - - writeScripts(); -})(this); - -// $hash: b7c8d0a3a68383a9664606d506fd504a \ No newline at end of file diff --git a/lib/tinymce/js/tinymce/plugins/spellchecker/plugin.js b/lib/tinymce/js/tinymce/plugins/spellchecker/plugin.js index f3c46ef1..f046b672 100644 --- a/lib/tinymce/js/tinymce/plugins/spellchecker/plugin.js +++ b/lib/tinymce/js/tinymce/plugins/spellchecker/plugin.js @@ -1,630 +1,761 @@ /** - * Compiled inline version. (Library mode) - */ - -/*jshint smarttabs:true, undef:true, latedef:true, curly:true, bitwise:true, camelcase:true */ -/*globals $code */ - -(function(exports, undefined) { - "use strict"; - - var modules = {}; - - function require(ids, callback) { - var module, defs = []; - - for (var i = 0; i < ids.length; ++i) { - module = modules[ids[i]] || resolve(ids[i]); - if (!module) { - throw 'module definition dependecy not found: ' + ids[i]; - } - - defs.push(module); - } - - callback.apply(null, defs); - } - - function define(id, dependencies, definition) { - if (typeof id !== 'string') { - throw 'invalid module definition, module id must be defined and be a string'; - } - - if (dependencies === undefined) { - throw 'invalid module definition, dependencies must be specified'; - } - - if (definition === undefined) { - throw 'invalid module definition, definition function must be specified'; - } - - require(dependencies, function() { - modules[id] = definition.apply(null, arguments); - }); - } - - function defined(id) { - return !!modules[id]; - } - - function resolve(id) { - var target = exports; - var fragments = id.split(/[.\/]/); - - for (var fi = 0; fi < fragments.length; ++fi) { - if (!target[fragments[fi]]) { - return; - } - - target = target[fragments[fi]]; - } - - return target; - } - - function expose(ids) { - for (var i = 0; i < ids.length; i++) { - var target = exports; - var id = ids[i]; - var fragments = id.split(/[.\/]/); - - for (var fi = 0; fi < fragments.length - 1; ++fi) { - if (target[fragments[fi]] === undefined) { - target[fragments[fi]] = {}; - } - - target = target[fragments[fi]]; - } - - target[fragments[fragments.length - 1]] = modules[id]; - } - } - -// Included from: js/tinymce/plugins/spellchecker/classes/DomTextMatcher.js - -/** - * DomTextMatcher.js + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing + * Version: 5.1.6 (2020-01-28) */ - -/** - * This class logic for filtering text and matching words. - * - * @class tinymce.spellcheckerplugin.TextFilter - * @private - */ -define("tinymce/spellcheckerplugin/DomTextMatcher", [], function() { - // Based on work developed by: James Padolsey http://james.padolsey.com - // released under UNLICENSE that is compatible with LGPL - // TODO: Handle contentEditable edgecase: - // texttexttexttexttext
- return function(regex, node, schema) { - var m, matches = [], text, count = 0, doc; - var blockElementsMap, hiddenTextElementsMap, shortEndedElementsMap; - - doc = node.ownerDocument; - blockElementsMap = schema.getBlockElements(); // H1-H6, P, TD etc - hiddenTextElementsMap = schema.getWhiteSpaceElements(); // TEXTAREA, PRE, STYLE, SCRIPT - shortEndedElementsMap = schema.getShortEndedElements(); // BR, IMG, INPUT - - function getMatchIndexes(m) { - if (!m[0]) { - throw 'findAndReplaceDOMText cannot handle zero-length matches'; - } - - var index = m.index; - - return [index, index + m[0].length, [m[0]]]; - } - - function getText(node) { - var txt; - - if (node.nodeType === 3) { - return node.data; - } - - if (hiddenTextElementsMap[node.nodeName]) { - return ''; - } - - txt = ''; - - if (blockElementsMap[node.nodeName] || shortEndedElementsMap[node.nodeName]) { - txt += '\n'; - } - - if ((node = node.firstChild)) { - do { - txt += getText(node); - } while ((node = node.nextSibling)); - } - - return txt; - } - - function stepThroughMatches(node, matches, replaceFn) { - var startNode, endNode, startNodeIndex, - endNodeIndex, innerNodes = [], atIndex = 0, curNode = node, - matchLocation = matches.shift(), matchIndex = 0; - - out: while (true) { - if (blockElementsMap[curNode.nodeName] || shortEndedElementsMap[curNode.nodeName]) { - atIndex++; - } - - if (curNode.nodeType === 3) { - if (!endNode && curNode.length + atIndex >= matchLocation[1]) { - // We've found the ending - endNode = curNode; - endNodeIndex = matchLocation[1] - atIndex; - } else if (startNode) { - // Intersecting node - innerNodes.push(curNode); - } - - if (!startNode && curNode.length + atIndex > matchLocation[0]) { - // We've found the match start - startNode = curNode; - startNodeIndex = matchLocation[0] - atIndex; - } - - atIndex += curNode.length; - } - - if (startNode && endNode) { - curNode = replaceFn({ - startNode: startNode, - startNodeIndex: startNodeIndex, - endNode: endNode, - endNodeIndex: endNodeIndex, - innerNodes: innerNodes, - match: matchLocation[2], - matchIndex: matchIndex - }); - - // replaceFn has to return the node that replaced the endNode - // and then we step back so we can continue from the end of the - // match: - atIndex -= (endNode.length - endNodeIndex); - startNode = null; - endNode = null; - innerNodes = []; - matchLocation = matches.shift(); - matchIndex++; - - if (!matchLocation) { - break; // no more matches - } - } else if (!hiddenTextElementsMap[curNode.nodeName] && curNode.firstChild) { - // Move down - curNode = curNode.firstChild; - continue; - } else if (curNode.nextSibling) { - // Move forward: - curNode = curNode.nextSibling; - continue; - } - - // Move forward or up: - while (true) { - if (curNode.nextSibling) { - curNode = curNode.nextSibling; - break; - } else if (curNode.parentNode !== node) { - curNode = curNode.parentNode; - } else { - break out; - } - } - } - } - - /** - * Generates the actual replaceFn which splits up text nodes - * and inserts the replacement element. - */ - function genReplacer(nodeName) { - var makeReplacementNode; - - if (typeof nodeName != 'function') { - var stencilNode = nodeName.nodeType ? nodeName : doc.createElement(nodeName); - - makeReplacementNode = function(fill, matchIndex) { - var clone = stencilNode.cloneNode(false); - - clone.setAttribute('data-mce-index', matchIndex); - - if (fill) { - clone.appendChild(doc.createTextNode(fill)); - } - - return clone; - }; - } else { - makeReplacementNode = nodeName; - } - - return function replace(range) { - var before, after, parentNode, startNode = range.startNode, - endNode = range.endNode, matchIndex = range.matchIndex; - - if (startNode === endNode) { - var node = startNode; - - parentNode = node.parentNode; - if (range.startNodeIndex > 0) { - // Add `before` text node (before the match) - before = doc.createTextNode(node.data.substring(0, range.startNodeIndex)); - parentNode.insertBefore(before, node); - } - - // Create the replacement node: - var el = makeReplacementNode(range.match[0], matchIndex); - parentNode.insertBefore(el, node); - if (range.endNodeIndex < node.length) { - // Add `after` text node (after the match) - after = doc.createTextNode(node.data.substring(range.endNodeIndex)); - parentNode.insertBefore(after, node); - } - - node.parentNode.removeChild(node); - - return el; - } else { - // Replace startNode -> [innerNodes...] -> endNode (in that order) - before = doc.createTextNode(startNode.data.substring(0, range.startNodeIndex)); - after = doc.createTextNode(endNode.data.substring(range.endNodeIndex)); - var elA = makeReplacementNode(startNode.data.substring(range.startNodeIndex), matchIndex); - var innerEls = []; - - for (var i = 0, l = range.innerNodes.length; i < l; ++i) { - var innerNode = range.innerNodes[i]; - var innerEl = makeReplacementNode(innerNode.data, matchIndex); - innerNode.parentNode.replaceChild(innerEl, innerNode); - innerEls.push(innerEl); - } - - var elB = makeReplacementNode(endNode.data.substring(0, range.endNodeIndex), matchIndex); - - parentNode = startNode.parentNode; - parentNode.insertBefore(before, startNode); - parentNode.insertBefore(elA, startNode); - parentNode.removeChild(startNode); - - parentNode = endNode.parentNode; - parentNode.insertBefore(elB, endNode); - parentNode.insertBefore(after, endNode); - parentNode.removeChild(endNode); - - return elB; - } - }; - } - - text = getText(node); - if (text && regex.global) { - while ((m = regex.exec(text))) { - matches.push(getMatchIndexes(m)); - } - } - - function filter(callback) { - var filteredMatches = []; - - each(function(match, i) { - if (callback(match, i)) { - filteredMatches.push(match); - } - }); - - matches = filteredMatches; - - /*jshint validthis:true*/ - return this; - } - - function each(callback) { - for (var i = 0, l = matches.length; i < l; i++) { - if (callback(matches[i], i) === false) { - break; - } - } - - /*jshint validthis:true*/ - return this; - } - - function mark(replacementNode) { - if (matches.length) { - count = matches.length; - stepThroughMatches(node, matches, genReplacer(replacementNode)); - } - - /*jshint validthis:true*/ - return this; - } - - return { - text: text, - count: count, - matches: matches, - each: each, - filter: filter, - mark: mark - }; - }; -}); - -// Included from: js/tinymce/plugins/spellchecker/classes/Plugin.js - -/** - * Plugin.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -/*jshint camelcase:false */ - -/** - * This class contains all core logic for the spellchecker plugin. - * - * @class tinymce.spellcheckerplugin.Plugin - * @private - */ -define("tinymce/spellcheckerplugin/Plugin", [ - "tinymce/spellcheckerplugin/DomTextMatcher", - "tinymce/PluginManager", - "tinymce/util/Tools", - "tinymce/ui/Menu", - "tinymce/dom/DOMUtils", - "tinymce/util/JSONRequest" -], function(DomTextMatcher, PluginManager, Tools, Menu, DOMUtils, JSONRequest) { - PluginManager.add('spellchecker', function(editor) { - var lastSuggestions, started; - - function isEmpty(obj) { - /*jshint unused:false*/ - for (var name in obj) { - return false; - } - - return true; - } - - function showSuggestions(target, word) { - var items = [], suggestions = lastSuggestions[word]; - - Tools.each(suggestions, function(suggestion) { - items.push({ - text: suggestion, - onclick: function() { - editor.insertContent(suggestion); - checkIfFinished(); - } - }); - }); - - items.push.apply(items, [ - {text: '-'}, - - {text: 'Ignore', onclick: function() { - ignoreWord(target, word); - }}, - - {text: 'Ignore all', onclick: function() { - ignoreWord(target, word, true); - }}, - - {text: 'Finish', onclick: finish} - ]); - - // Render menu - var menu = new Menu({ - items: items, - context: 'contextmenu', - onhide: function() { - menu.remove(); - } - }); - - menu.renderTo(document.body); - - // Position menu - var pos = DOMUtils.DOM.getPos(editor.getContentAreaContainer()); - var targetPos = editor.dom.getPos(target); - - pos.x += targetPos.x; - pos.y += targetPos.y; - - menu.moveTo(pos.x, pos.y + target.offsetHeight); - } - - function spellcheck() { - var textFilter, words = [], uniqueWords = {}; - - if (started) { - finish(); - return; - } - - started = true; - - function doneCallback(suggestions) { - editor.setProgressState(false); - - if (isEmpty(suggestions)) { - editor.windowManager.alert('No misspellings found'); - return; - } - - lastSuggestions = suggestions; - - textFilter.filter(function(match) { - return !!suggestions[match[2][0]]; - }).mark(editor.dom.create('span', { - "class": 'mce-spellchecker-word', - "data-mce-bogus": 1 - })); - - textFilter = null; - editor.fire('SpellcheckStart'); - } - - // Find all words and make an unique words array - textFilter = new DomTextMatcher(/\w+/g, editor.getBody(), editor.schema).each(function(match) { - if (!uniqueWords[match[2][0]]) { - words.push(match[2][0]); - uniqueWords[match[2][0]] = true; - } - }); - - editor.settings.spellcheck_callback = function(method, words, doneCallback) { - JSONRequest.sendRPC({ - url: editor.settings.spellchecker_rpc_url, - method: method, - params: { - lang: "en", - words: words - }, - success: function(result) { - doneCallback(result); - }, - error: function(result, xhr) { - editor.windowManager.alert("Error: " + result + "\nData:" + xhr.responseText); - editor.setProgressState(false); - textFilter = null; - } - }); - }; - - editor.setProgressState(true); - editor.settings.spellcheck_callback("spellcheck", words, doneCallback); - } - - function checkIfFinished() { - if (!editor.dom.select('span.mce-spellchecker-word').length) { - finish(); - } - } - - function unwrap(node) { - var parentNode = node.parentNode; - parentNode.insertBefore(node.firstChild, node); - node.parentNode.removeChild(node); - } - - function ignoreWord(target, word, all) { - if (all) { - Tools.each(editor.dom.select('span.mce-spellchecker-word'), function(item) { - var text = item.innerText || item.textContent; - - if (text == word) { - unwrap(item); - } - }); - } else { - unwrap(target); - } - - checkIfFinished(); - } - - function finish() { - var i, nodes, node; - - started = false; - node = editor.getBody(); - nodes = node.getElementsByTagName('span'); - i = nodes.length; - while (i--) { - node = nodes[i]; - if (node.getAttribute('data-mce-index')) { - unwrap(node); - } - } - - editor.fire('SpellcheckEnd'); - } - - function selectMatch(index) { - var nodes, i, spanElm, spanIndex = -1, startContainer, endContainer; - - index = "" + index; - nodes = editor.getBody().getElementsByTagName("span"); - for (i = 0; i < nodes.length; i++) { - spanElm = nodes[i]; - if (spanElm.className == "mce-spellchecker-word") { - spanIndex = spanElm.getAttribute('data-mce-index'); - if (spanIndex === index) { - spanIndex = index; - - if (!startContainer) { - startContainer = spanElm.firstChild; - } - - endContainer = spanElm.firstChild; - } - - if (spanIndex !== index && endContainer) { - break; - } - } - } - - var rng = editor.dom.createRng(); - rng.setStart(startContainer, 0); - rng.setEnd(endContainer, endContainer.length); - editor.selection.setRng(rng); - - return rng; - } - - editor.on('click', function(e) { - if (e.target.className == "mce-spellchecker-word") { - e.preventDefault(); - - var rng = selectMatch(e.target.getAttribute('data-mce-index')); - showSuggestions(e.target, rng.toString()); - } - }); - - editor.addMenuItem('spellchecker', { - text: 'Spellcheck', - context: 'tools', - onclick: spellcheck, - selectable: true, - onPostRender: function() { - var self = this; - - editor.on('SpellcheckStart SpellcheckEnd', function() { - self.active(started); - }); - } - }); - - editor.addButton('spellchecker', { - tooltip: 'Spellcheck', - onclick: spellcheck, - onPostRender: function() { - var self = this; - - editor.on('SpellcheckStart SpellcheckEnd', function() { - self.active(started); - }); - } - }); - }); -}); - -expose(["tinymce/spellcheckerplugin/DomTextMatcher","tinymce/spellcheckerplugin/Plugin"]); -})(this); \ No newline at end of file +(function (domGlobals) { + 'use strict'; + + var Cell = function (initial) { + var value = initial; + var get = function () { + return value; + }; + var set = function (v) { + value = v; + }; + var clone = function () { + return Cell(get()); + }; + return { + get: get, + set: set, + clone: clone + }; + }; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var hasProPlugin = function (editor) { + if (/(^|[ ,])tinymcespellchecker([, ]|$)/.test(editor.settings.plugins) && global.get('tinymcespellchecker')) { + if (typeof domGlobals.window.console !== 'undefined' && domGlobals.window.console.log) { + domGlobals.window.console.log('Spell Checker Pro is incompatible with Spell Checker plugin! ' + 'Remove \'spellchecker\' from the \'plugins\' option.'); + } + return true; + } else { + return false; + } + }; + var DetectProPlugin = { hasProPlugin: hasProPlugin }; + + var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + + var global$2 = tinymce.util.Tools.resolve('tinymce.util.URI'); + + var global$3 = tinymce.util.Tools.resolve('tinymce.util.XHR'); + + var fireSpellcheckStart = function (editor) { + return editor.fire('SpellcheckStart'); + }; + var fireSpellcheckEnd = function (editor) { + return editor.fire('SpellcheckEnd'); + }; + var Events = { + fireSpellcheckStart: fireSpellcheckStart, + fireSpellcheckEnd: fireSpellcheckEnd + }; + + var getLanguages = function (editor) { + var defaultLanguages = 'English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr_FR,German=de,Italian=it,Polish=pl,Portuguese=pt_BR,Spanish=es,Swedish=sv'; + return editor.getParam('spellchecker_languages', defaultLanguages); + }; + var getLanguage = function (editor) { + var defaultLanguage = editor.getParam('language', 'en'); + return editor.getParam('spellchecker_language', defaultLanguage); + }; + var getRpcUrl = function (editor) { + return editor.getParam('spellchecker_rpc_url'); + }; + var getSpellcheckerCallback = function (editor) { + return editor.getParam('spellchecker_callback'); + }; + var getSpellcheckerWordcharPattern = function (editor) { + var defaultPattern = new RegExp('[^' + '\\s!"#$%&()*+,-./:;<=>?@[\\]^_{|}`' + '\xA7\xA9\xAB\xAE\xB1\xB6\xB7\xB8\xBB' + '\xBC\xBD\xBE\xBF\xD7\xF7\xA4\u201D\u201C\u201E\xA0\u2002\u2003\u2009' + ']+', 'g'); + return editor.getParam('spellchecker_wordchar_pattern', defaultPattern); + }; + var Settings = { + getLanguages: getLanguages, + getLanguage: getLanguage, + getRpcUrl: getRpcUrl, + getSpellcheckerCallback: getSpellcheckerCallback, + getSpellcheckerWordcharPattern: getSpellcheckerWordcharPattern + }; + + function isContentEditableFalse(node) { + return node && node.nodeType === 1 && node.contentEditable === 'false'; + } + var DomTextMatcher = function (node, editor) { + var m, matches = [], text; + var dom = editor.dom; + var blockElementsMap, hiddenTextElementsMap, shortEndedElementsMap; + blockElementsMap = editor.schema.getBlockElements(); + hiddenTextElementsMap = editor.schema.getWhiteSpaceElements(); + shortEndedElementsMap = editor.schema.getShortEndedElements(); + function createMatch(m, data) { + if (!m[0]) { + throw new Error('findAndReplaceDOMText cannot handle zero-length matches'); + } + return { + start: m.index, + end: m.index + m[0].length, + text: m[0], + data: data + }; + } + function getText(node) { + var txt; + if (node.nodeType === 3) { + return node.data; + } + if (hiddenTextElementsMap[node.nodeName] && !blockElementsMap[node.nodeName]) { + return ''; + } + if (isContentEditableFalse(node)) { + return '\n'; + } + txt = ''; + if (blockElementsMap[node.nodeName] || shortEndedElementsMap[node.nodeName]) { + txt += '\n'; + } + if (node = node.firstChild) { + do { + txt += getText(node); + } while (node = node.nextSibling); + } + return txt; + } + function stepThroughMatches(node, matches, replaceFn) { + var startNode, endNode, startNodeIndex, endNodeIndex, innerNodes = [], atIndex = 0, curNode = node, matchLocation, matchIndex = 0; + matches = matches.slice(0); + matches.sort(function (a, b) { + return a.start - b.start; + }); + matchLocation = matches.shift(); + out: + while (true) { + if (blockElementsMap[curNode.nodeName] || shortEndedElementsMap[curNode.nodeName] || isContentEditableFalse(curNode)) { + atIndex++; + } + if (curNode.nodeType === 3) { + if (!endNode && curNode.length + atIndex >= matchLocation.end) { + endNode = curNode; + endNodeIndex = matchLocation.end - atIndex; + } else if (startNode) { + innerNodes.push(curNode); + } + if (!startNode && curNode.length + atIndex > matchLocation.start) { + startNode = curNode; + startNodeIndex = matchLocation.start - atIndex; + } + atIndex += curNode.length; + } + if (startNode && endNode) { + curNode = replaceFn({ + startNode: startNode, + startNodeIndex: startNodeIndex, + endNode: endNode, + endNodeIndex: endNodeIndex, + innerNodes: innerNodes, + match: matchLocation.text, + matchIndex: matchIndex + }); + atIndex -= endNode.length - endNodeIndex; + startNode = null; + endNode = null; + innerNodes = []; + matchLocation = matches.shift(); + matchIndex++; + if (!matchLocation) { + break; + } + } else if ((!hiddenTextElementsMap[curNode.nodeName] || blockElementsMap[curNode.nodeName]) && curNode.firstChild) { + if (!isContentEditableFalse(curNode)) { + curNode = curNode.firstChild; + continue; + } + } else if (curNode.nextSibling) { + curNode = curNode.nextSibling; + continue; + } + while (true) { + if (curNode.nextSibling) { + curNode = curNode.nextSibling; + break; + } else if (curNode.parentNode !== node) { + curNode = curNode.parentNode; + } else { + break out; + } + } + } + } + function genReplacer(callback) { + function makeReplacementNode(fill, matchIndex) { + var match = matches[matchIndex]; + if (!match.stencil) { + match.stencil = callback(match); + } + var clone = match.stencil.cloneNode(false); + clone.setAttribute('data-mce-index', matchIndex); + if (fill) { + clone.appendChild(dom.doc.createTextNode(fill)); + } + return clone; + } + return function (range) { + var before; + var after; + var parentNode; + var startNode = range.startNode; + var endNode = range.endNode; + var matchIndex = range.matchIndex; + var doc = dom.doc; + if (startNode === endNode) { + var node_1 = startNode; + parentNode = node_1.parentNode; + if (range.startNodeIndex > 0) { + before = doc.createTextNode(node_1.data.substring(0, range.startNodeIndex)); + parentNode.insertBefore(before, node_1); + } + var el = makeReplacementNode(range.match, matchIndex); + parentNode.insertBefore(el, node_1); + if (range.endNodeIndex < node_1.length) { + after = doc.createTextNode(node_1.data.substring(range.endNodeIndex)); + parentNode.insertBefore(after, node_1); + } + node_1.parentNode.removeChild(node_1); + return el; + } + before = doc.createTextNode(startNode.data.substring(0, range.startNodeIndex)); + after = doc.createTextNode(endNode.data.substring(range.endNodeIndex)); + var elA = makeReplacementNode(startNode.data.substring(range.startNodeIndex), matchIndex); + for (var i = 0, l = range.innerNodes.length; i < l; ++i) { + var innerNode = range.innerNodes[i]; + var innerEl = makeReplacementNode(innerNode.data, matchIndex); + innerNode.parentNode.replaceChild(innerEl, innerNode); + } + var elB = makeReplacementNode(endNode.data.substring(0, range.endNodeIndex), matchIndex); + parentNode = startNode.parentNode; + parentNode.insertBefore(before, startNode); + parentNode.insertBefore(elA, startNode); + parentNode.removeChild(startNode); + parentNode = endNode.parentNode; + parentNode.insertBefore(elB, endNode); + parentNode.insertBefore(after, endNode); + parentNode.removeChild(endNode); + return elB; + }; + } + function unwrapElement(element) { + var parentNode = element.parentNode; + parentNode.insertBefore(element.firstChild, element); + element.parentNode.removeChild(element); + } + function hasClass(elm) { + return elm.className.indexOf('mce-spellchecker-word') !== -1; + } + function getWrappersByIndex(index) { + var elements = node.getElementsByTagName('*'), wrappers = []; + index = typeof index === 'number' ? '' + index : null; + for (var i = 0; i < elements.length; i++) { + var element = elements[i], dataIndex = element.getAttribute('data-mce-index'); + if (dataIndex !== null && dataIndex.length && hasClass(element)) { + if (dataIndex === index || index === null) { + wrappers.push(element); + } + } + } + return wrappers; + } + function indexOf(match) { + var i = matches.length; + while (i--) { + if (matches[i] === match) { + return i; + } + } + return -1; + } + function filter(callback) { + var filteredMatches = []; + each(function (match, i) { + if (callback(match, i)) { + filteredMatches.push(match); + } + }); + matches = filteredMatches; + return this; + } + function each(callback) { + for (var i = 0, l = matches.length; i < l; i++) { + if (callback(matches[i], i) === false) { + break; + } + } + return this; + } + function wrap(callback) { + if (matches.length) { + stepThroughMatches(node, matches, genReplacer(callback)); + } + return this; + } + function find(regex, data) { + if (text && regex.global) { + while (m = regex.exec(text)) { + matches.push(createMatch(m, data)); + } + } + return this; + } + function unwrap(match) { + var i; + var elements = getWrappersByIndex(match ? indexOf(match) : null); + i = elements.length; + while (i--) { + unwrapElement(elements[i]); + } + return this; + } + function matchFromElement(element) { + return matches[element.getAttribute('data-mce-index')]; + } + function elementFromMatch(match) { + return getWrappersByIndex(indexOf(match))[0]; + } + function add(start, length, data) { + matches.push({ + start: start, + end: start + length, + text: text.substr(start, length), + data: data + }); + return this; + } + function rangeFromMatch(match) { + var wrappers = getWrappersByIndex(indexOf(match)); + var rng = editor.dom.createRng(); + rng.setStartBefore(wrappers[0]); + rng.setEndAfter(wrappers[wrappers.length - 1]); + return rng; + } + function replace(match, text) { + var rng = rangeFromMatch(match); + rng.deleteContents(); + if (text.length > 0) { + rng.insertNode(editor.dom.doc.createTextNode(text)); + } + return rng; + } + function reset() { + matches.splice(0, matches.length); + unwrap(); + return this; + } + text = getText(node); + return { + text: text, + matches: matches, + each: each, + filter: filter, + reset: reset, + matchFromElement: matchFromElement, + elementFromMatch: elementFromMatch, + find: find, + add: add, + wrap: wrap, + unwrap: unwrap, + replace: replace, + rangeFromMatch: rangeFromMatch, + indexOf: indexOf + }; + }; + + var getTextMatcher = function (editor, textMatcherState) { + if (!textMatcherState.get()) { + var textMatcher = DomTextMatcher(editor.getBody(), editor); + textMatcherState.set(textMatcher); + } + return textMatcherState.get(); + }; + var isEmpty = function (obj) { + for (var _ in obj) { + return false; + } + return true; + }; + var defaultSpellcheckCallback = function (editor, pluginUrl, currentLanguageState) { + return function (method, text, doneCallback, errorCallback) { + var data = { + method: method, + lang: currentLanguageState.get() + }; + var postData = ''; + data[method === 'addToDictionary' ? 'word' : 'text'] = text; + global$1.each(data, function (value, key) { + if (postData) { + postData += '&'; + } + postData += key + '=' + encodeURIComponent(value); + }); + global$3.send({ + url: new global$2(pluginUrl).toAbsolute(Settings.getRpcUrl(editor)), + type: 'post', + content_type: 'application/x-www-form-urlencoded', + data: postData, + success: function (result) { + var parseResult = JSON.parse(result); + if (!parseResult) { + var message = editor.translate('Server response wasn\'t proper JSON.'); + errorCallback(message); + } else if (parseResult.error) { + errorCallback(parseResult.error); + } else { + doneCallback(parseResult); + } + }, + error: function () { + var message = editor.translate('The spelling service was not found: (') + Settings.getRpcUrl(editor) + editor.translate(')'); + errorCallback(message); + } + }); + }; + }; + var sendRpcCall = function (editor, pluginUrl, currentLanguageState, name, data, successCallback, errorCallback) { + var userSpellcheckCallback = Settings.getSpellcheckerCallback(editor); + var spellCheckCallback = userSpellcheckCallback ? userSpellcheckCallback : defaultSpellcheckCallback(editor, pluginUrl, currentLanguageState); + spellCheckCallback.call(editor.plugins.spellchecker, name, data, successCallback, errorCallback); + }; + var spellcheck = function (editor, pluginUrl, startedState, textMatcherState, lastSuggestionsState, currentLanguageState) { + if (finish(editor, startedState, textMatcherState)) { + return; + } + var errorCallback = function (message) { + editor.notificationManager.open({ + text: message, + type: 'error' + }); + editor.setProgressState(false); + finish(editor, startedState, textMatcherState); + }; + var successCallback = function (data) { + markErrors(editor, startedState, textMatcherState, lastSuggestionsState, data); + }; + editor.setProgressState(true); + sendRpcCall(editor, pluginUrl, currentLanguageState, 'spellcheck', getTextMatcher(editor, textMatcherState).text, successCallback, errorCallback); + editor.focus(); + }; + var checkIfFinished = function (editor, startedState, textMatcherState) { + if (!editor.dom.select('span.mce-spellchecker-word').length) { + finish(editor, startedState, textMatcherState); + } + }; + var addToDictionary = function (editor, pluginUrl, startedState, textMatcherState, currentLanguageState, word, spans) { + editor.setProgressState(true); + sendRpcCall(editor, pluginUrl, currentLanguageState, 'addToDictionary', word, function () { + editor.setProgressState(false); + editor.dom.remove(spans, true); + checkIfFinished(editor, startedState, textMatcherState); + }, function (message) { + editor.notificationManager.open({ + text: message, + type: 'error' + }); + editor.setProgressState(false); + }); + }; + var ignoreWord = function (editor, startedState, textMatcherState, word, spans, all) { + editor.selection.collapse(); + if (all) { + global$1.each(editor.dom.select('span.mce-spellchecker-word'), function (span) { + if (span.getAttribute('data-mce-word') === word) { + editor.dom.remove(span, true); + } + }); + } else { + editor.dom.remove(spans, true); + } + checkIfFinished(editor, startedState, textMatcherState); + }; + var finish = function (editor, startedState, textMatcherState) { + var bookmark = editor.selection.getBookmark(); + getTextMatcher(editor, textMatcherState).reset(); + editor.selection.moveToBookmark(bookmark); + textMatcherState.set(null); + if (startedState.get()) { + startedState.set(false); + Events.fireSpellcheckEnd(editor); + return true; + } + }; + var getElmIndex = function (elm) { + var value = elm.getAttribute('data-mce-index'); + if (typeof value === 'number') { + return '' + value; + } + return value; + }; + var findSpansByIndex = function (editor, index) { + var nodes; + var spans = []; + nodes = global$1.toArray(editor.getBody().getElementsByTagName('span')); + if (nodes.length) { + for (var i = 0; i < nodes.length; i++) { + var nodeIndex = getElmIndex(nodes[i]); + if (nodeIndex === null || !nodeIndex.length) { + continue; + } + if (nodeIndex === index.toString()) { + spans.push(nodes[i]); + } + } + } + return spans; + }; + var markErrors = function (editor, startedState, textMatcherState, lastSuggestionsState, data) { + var hasDictionarySupport = !!data.dictionary; + var suggestions = data.words; + editor.setProgressState(false); + if (isEmpty(suggestions)) { + var message = editor.translate('No misspellings found.'); + editor.notificationManager.open({ + text: message, + type: 'info' + }); + startedState.set(false); + return; + } + lastSuggestionsState.set({ + suggestions: suggestions, + hasDictionarySupport: hasDictionarySupport + }); + var bookmark = editor.selection.getBookmark(); + getTextMatcher(editor, textMatcherState).find(Settings.getSpellcheckerWordcharPattern(editor)).filter(function (match) { + return !!suggestions[match.text]; + }).wrap(function (match) { + return editor.dom.create('span', { + 'class': 'mce-spellchecker-word', + 'aria-invalid': 'spelling', + 'data-mce-bogus': 1, + 'data-mce-word': match.text + }); + }); + editor.selection.moveToBookmark(bookmark); + startedState.set(true); + Events.fireSpellcheckStart(editor); + }; + var Actions = { + spellcheck: spellcheck, + checkIfFinished: checkIfFinished, + addToDictionary: addToDictionary, + ignoreWord: ignoreWord, + findSpansByIndex: findSpansByIndex, + getElmIndex: getElmIndex, + markErrors: markErrors + }; + + var get = function (editor, startedState, lastSuggestionsState, textMatcherState, currentLanguageState, url) { + var getLanguage = function () { + return currentLanguageState.get(); + }; + var getWordCharPattern = function () { + return Settings.getSpellcheckerWordcharPattern(editor); + }; + var markErrors = function (data) { + Actions.markErrors(editor, startedState, textMatcherState, lastSuggestionsState, data); + }; + var getTextMatcher = function () { + return textMatcherState.get(); + }; + return { + getTextMatcher: getTextMatcher, + getWordCharPattern: getWordCharPattern, + markErrors: markErrors, + getLanguage: getLanguage + }; + }; + var Api = { get: get }; + + var register = function (editor, pluginUrl, startedState, textMatcherState, lastSuggestionsState, currentLanguageState) { + editor.addCommand('mceSpellCheck', function () { + Actions.spellcheck(editor, pluginUrl, startedState, textMatcherState, lastSuggestionsState, currentLanguageState); + }); + }; + var Commands = { register: register }; + + var __assign = function () { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) + if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + var spellcheckerEvents = 'SpellcheckStart SpellcheckEnd'; + var buildMenuItems = function (listName, languageValues) { + var items = []; + global$1.each(languageValues, function (languageValue) { + items.push({ + selectable: true, + text: languageValue.name, + data: languageValue.value + }); + }); + return items; + }; + var getItems = function (editor) { + return global$1.map(Settings.getLanguages(editor).split(','), function (langPair) { + langPair = langPair.split('='); + return { + name: langPair[0], + value: langPair[1] + }; + }); + }; + var register$1 = function (editor, pluginUrl, startedState, textMatcherState, currentLanguageState, lastSuggestionsState) { + var languageMenuItems = buildMenuItems('Language', getItems(editor)); + var startSpellchecking = function () { + Actions.spellcheck(editor, pluginUrl, startedState, textMatcherState, lastSuggestionsState, currentLanguageState); + }; + var buttonArgs = { + tooltip: 'Spellcheck', + onAction: startSpellchecking, + icon: 'spell-check', + onSetup: function (buttonApi) { + var setButtonState = function () { + buttonApi.setActive(startedState.get()); + }; + editor.on(spellcheckerEvents, setButtonState); + return function () { + editor.off(spellcheckerEvents, setButtonState); + }; + } + }; + var splitButtonArgs = __assign(__assign({}, buttonArgs), { + type: 'splitbutton', + select: function (value) { + return value === currentLanguageState.get(); + }, + fetch: function (callback) { + var items = global$1.map(languageMenuItems, function (languageItem) { + return { + type: 'choiceitem', + value: languageItem.data, + text: languageItem.text + }; + }); + callback(items); + }, + onItemAction: function (splitButtonApi, value) { + currentLanguageState.set(value); + } + }); + if (languageMenuItems.length > 1) { + editor.ui.registry.addSplitButton('spellchecker', splitButtonArgs); + } else { + editor.ui.registry.addToggleButton('spellchecker', buttonArgs); + } + editor.ui.registry.addToggleMenuItem('spellchecker', { + text: 'Spellcheck', + onSetup: function (menuApi) { + menuApi.setActive(startedState.get()); + var setMenuItemCheck = function () { + menuApi.setActive(startedState.get()); + }; + editor.on(spellcheckerEvents, setMenuItemCheck); + return function () { + editor.off(spellcheckerEvents, setMenuItemCheck); + }; + }, + onAction: startSpellchecking + }); + }; + var Buttons = { register: register$1 }; + + var ignoreAll = true; + var getSuggestions = function (editor, pluginUrl, lastSuggestionsState, startedState, textMatcherState, currentLanguageState, word, spans) { + var items = []; + var suggestions = lastSuggestionsState.get().suggestions[word]; + global$1.each(suggestions, function (suggestion) { + items.push({ + text: suggestion, + onAction: function () { + editor.insertContent(editor.dom.encode(suggestion)); + editor.dom.remove(spans); + Actions.checkIfFinished(editor, startedState, textMatcherState); + } + }); + }); + var hasDictionarySupport = lastSuggestionsState.get().hasDictionarySupport; + if (hasDictionarySupport) { + items.push({ type: 'separator' }); + items.push({ + text: 'Add to dictionary', + onAction: function () { + Actions.addToDictionary(editor, pluginUrl, startedState, textMatcherState, currentLanguageState, word, spans); + } + }); + } + items.push.apply(items, [ + { type: 'separator' }, + { + text: 'Ignore', + onAction: function () { + Actions.ignoreWord(editor, startedState, textMatcherState, word, spans); + } + }, + { + text: 'Ignore all', + onAction: function () { + Actions.ignoreWord(editor, startedState, textMatcherState, word, spans, ignoreAll); + } + } + ]); + return items; + }; + var setup = function (editor, pluginUrl, lastSuggestionsState, startedState, textMatcherState, currentLanguageState) { + var update = function (element) { + var target = element; + if (target.className === 'mce-spellchecker-word') { + var spans = Actions.findSpansByIndex(editor, Actions.getElmIndex(target)); + if (spans.length > 0) { + var rng = editor.dom.createRng(); + rng.setStartBefore(spans[0]); + rng.setEndAfter(spans[spans.length - 1]); + editor.selection.setRng(rng); + return getSuggestions(editor, pluginUrl, lastSuggestionsState, startedState, textMatcherState, currentLanguageState, target.getAttribute('data-mce-word'), spans); + } + } else { + return []; + } + }; + editor.ui.registry.addContextMenu('spellchecker', { update: update }); + }; + var SuggestionsMenu = { setup: setup }; + + function Plugin () { + global.add('spellchecker', function (editor, pluginUrl) { + if (DetectProPlugin.hasProPlugin(editor) === false) { + var startedState = Cell(false); + var currentLanguageState = Cell(Settings.getLanguage(editor)); + var textMatcherState = Cell(null); + var lastSuggestionsState = Cell(null); + Buttons.register(editor, pluginUrl, startedState, textMatcherState, currentLanguageState, lastSuggestionsState); + SuggestionsMenu.setup(editor, pluginUrl, lastSuggestionsState, startedState, textMatcherState, currentLanguageState); + Commands.register(editor, pluginUrl, startedState, textMatcherState, lastSuggestionsState, currentLanguageState); + return Api.get(editor, startedState, lastSuggestionsState, textMatcherState, currentLanguageState, pluginUrl); + } + }); + } + + Plugin(); + +}(window)); diff --git a/lib/tinymce/js/tinymce/plugins/spellchecker/plugin.min.js b/lib/tinymce/js/tinymce/plugins/spellchecker/plugin.min.js index 88cecedf..88ec2491 100644 --- a/lib/tinymce/js/tinymce/plugins/spellchecker/plugin.min.js +++ b/lib/tinymce/js/tinymce/plugins/spellchecker/plugin.min.js @@ -1 +1,9 @@ -(function(e,t){"use strict";function n(e,t){for(var n,r=[],i=0;e.length>i;++i){if(n=s[e[i]]||o(e[i]),!n)throw"module definition dependecy not found: "+e[i];r.push(n)}t.apply(null,r)}function r(e,r,i){if("string"!=typeof e)throw"invalid module definition, module id must be defined and be a string";if(r===t)throw"invalid module definition, dependencies must be specified";if(i===t)throw"invalid module definition, definition function must be specified";n(r,function(){s[e]=i.apply(null,arguments)})}function i(e){return!!s[e]}function o(t){for(var n=e,r=t.split(/[.\/]/),i=0;r.length>i;++i){if(!n[r[i]])return;n=n[r[i]]}return n}function a(n){for(var r=0;n.length>r;r++){for(var i=e,o=n[r],a=o.split(/[.\/]/),l=0;a.length-1>l;++l)i[a[l]]===t&&(i[a[l]]={}),i=i[a[l]];i[a[a.length-1]]=s[o]}}var s={},l="tinymce/spellcheckerplugin/DomTextMatcher",c="tinymce/spellcheckerplugin/Plugin",u="tinymce/PluginManager",d="tinymce/util/Tools",f="tinymce/ui/Menu",p="tinymce/dom/DOMUtils",h="tinymce/util/JSONRequest";r(l,[],function(){return function(e,t,n){function r(e){if(!e[0])throw"findAndReplaceDOMText cannot handle zero-length matches";var t=e.index;return[t,t+e[0].length,[e[0]]]}function i(e){var t;if(3===e.nodeType)return e.data;if(g[e.nodeName])return"";if(t="",(m[e.nodeName]||v[e.nodeName])&&(t+="\n"),e=e.firstChild)do t+=i(e);while(e=e.nextSibling);return t}function o(e,t,n){var r,i,o,a,s=[],l=0,c=e,u=t.shift(),d=0;e:for(;;){if((m[c.nodeName]||v[c.nodeName])&&l++,3===c.nodeType&&(!i&&c.length+l>=u[1]?(i=c,a=u[1]-l):r&&s.push(c),!r&&c.length+l>u[0]&&(r=c,o=u[0]-l),l+=c.length),r&&i){if(c=n({startNode:r,startNodeIndex:o,endNode:i,endNodeIndex:a,innerNodes:s,match:u[2],matchIndex:d}),l-=i.length-a,r=null,i=null,s=[],u=t.shift(),d++,!u)break}else{if(!g[c.nodeName]&&c.firstChild){c=c.firstChild;continue}if(c.nextSibling){c=c.nextSibling;continue}}for(;;){if(c.nextSibling){c=c.nextSibling;break}if(c.parentNode===e)break e;c=c.parentNode}}}function a(e){var t;if("function"!=typeof e){var n=e.nodeType?e:h.createElement(e);t=function(e,t){var r=n.cloneNode(!1);return r.setAttribute("data-mce-index",t),e&&r.appendChild(h.createTextNode(e)),r}}else t=e;return function r(e){var n,r,i,o=e.startNode,a=e.endNode,s=e.matchIndex;if(o===a){var l=o;i=l.parentNode,e.startNodeIndex>0&&(n=h.createTextNode(l.data.substring(0,e.startNodeIndex)),i.insertBefore(n,l));var c=t(e.match[0],s);return i.insertBefore(c,l),e.endNodeIndexf;++f){var m=e.innerNodes[f],g=t(m.data,s);m.parentNode.replaceChild(g,m),d.push(g)}var v=t(a.data.substring(0,e.endNodeIndex),s);return i=o.parentNode,i.insertBefore(n,o),i.insertBefore(u,o),i.removeChild(o),i=a.parentNode,i.insertBefore(v,a),i.insertBefore(r,a),i.removeChild(a),v}}function s(e){var t=[];return l(function(n,r){e(n,r)&&t.push(n)}),d=t,this}function l(e){for(var t=0,n=d.length;n>t&&e(d[t],t)!==!1;t++);return this}function c(e){return d.length&&(p=d.length,o(t,d,a(e))),this}var u,d=[],f,p=0,h,m,g,v;if(h=t.ownerDocument,m=n.getBlockElements(),g=n.getWhiteSpaceElements(),v=n.getShortEndedElements(),f=i(t),f&&e.global)for(;u=e.exec(f);)d.push(r(u));return{text:f,count:p,matches:d,each:l,filter:s,mark:c}}}),r(c,[l,u,d,f,p,h],function(e,n,r,i,o,a){n.add("spellchecker",function(n){function s(e){for(var t in e)return!1;return!0}function l(e,t){var a=[],s=m[t];r.each(s,function(e){a.push({text:e,onclick:function(){n.insertContent(e),u()}})}),a.push.apply(a,[{text:"-"},{text:"Ignore",onclick:function(){f(e,t)}},{text:"Ignore all",onclick:function(){f(e,t,!0)}},{text:"Finish",onclick:p}]);var l=new i({items:a,context:"contextmenu",onhide:function(){l.remove()}});l.renderTo(document.body);var c=o.DOM.getPos(n.getContentAreaContainer()),d=n.dom.getPos(e);c.x+=d.x,c.y+=d.y,l.moveTo(c.x,c.y+e.offsetHeight)}function c(){function r(e){return n.setProgressState(!1),s(e)?(n.windowManager.alert("No misspellings found"),t):(m=e,i.filter(function(t){return!!e[t[2][0]]}).mark(n.dom.create("span",{"class":"mce-spellchecker-word","data-mce-bogus":1})),i=null,n.fire("SpellcheckStart"),t)}var i,o=[],l={};return g?(p(),t):(g=!0,i=new e(/\w+/g,n.getBody(),n.schema).each(function(e){l[e[2][0]]||(o.push(e[2][0]),l[e[2][0]]=!0)}),n.settings.spellcheck_callback=function(e,t,r){a.sendRPC({url:n.settings.spellchecker_rpc_url,method:e,params:{lang:"en",words:t},success:function(e){r(e)},error:function(e,t){n.windowManager.alert("Error: "+e+"\nData:"+t.responseText),n.setProgressState(!1),i=null}})},n.setProgressState(!0),n.settings.spellcheck_callback("spellcheck",o,r),t)}function u(){n.dom.select("span.mce-spellchecker-word").length||p()}function d(e){var t=e.parentNode;t.insertBefore(e.firstChild,e),e.parentNode.removeChild(e)}function f(e,t,i){i?r.each(n.dom.select("span.mce-spellchecker-word"),function(e){var n=e.innerText||e.textContent;n==t&&d(e)}):d(e),u()}function p(){var e,t,r;for(g=!1,r=n.getBody(),t=r.getElementsByTagName("span"),e=t.length;e--;)r=t[e],r.getAttribute("data-mce-index")&&d(r);n.fire("SpellcheckEnd")}function h(e){var t,r,i,o=-1,a,s;for(e=""+e,t=n.getBody().getElementsByTagName("span"),r=0;t.length>r&&(i=t[r],"mce-spellchecker-word"!=i.className||(o=i.getAttribute("data-mce-index"),o===e&&(o=e,a||(a=i.firstChild),s=i.firstChild),o===e||!s));r++);var l=n.dom.createRng();return l.setStart(a,0),l.setEnd(s,s.length),n.selection.setRng(l),l}var m,g;n.on("click",function(e){if("mce-spellchecker-word"==e.target.className){e.preventDefault();var t=h(e.target.getAttribute("data-mce-index"));l(e.target,""+t)}}),n.addMenuItem("spellchecker",{text:"Spellcheck",context:"tools",onclick:c,selectable:!0,onPostRender:function(){var e=this;n.on("SpellcheckStart SpellcheckEnd",function(){e.active(g)})}}),n.addButton("spellchecker",{tooltip:"Spellcheck",onclick:c,onPostRender:function(){var e=this;n.on("SpellcheckStart SpellcheckEnd",function(){e.active(g)})}})})}),a([l,c])})(this); \ No newline at end of file +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.1.6 (2020-01-28) + */ +!function(t){"use strict";var a=function(e){function t(){return n}var n=e;return{get:t,set:function(e){n=e},clone:function(){return a(t())}}},n=tinymce.util.Tools.resolve("tinymce.PluginManager"),c=function(e){return!(!/(^|[ ,])tinymcespellchecker([, ]|$)/.test(e.settings.plugins)||!n.get("tinymcespellchecker"))&&("undefined"!=typeof t.window.console&&t.window.console.log&&t.window.console.log("Spell Checker Pro is incompatible with Spell Checker plugin! Remove 'spellchecker' from the 'plugins' option."),!0)},l=tinymce.util.Tools.resolve("tinymce.util.Tools"),u=tinymce.util.Tools.resolve("tinymce.util.URI"),d=tinymce.util.Tools.resolve("tinymce.util.XHR"),f=function(e){return e.fire("SpellcheckStart")},o=function(e){return e.fire("SpellcheckEnd")},g=function(e){return e.getParam("spellchecker_languages","English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr_FR,German=de,Italian=it,Polish=pl,Portuguese=pt_BR,Spanish=es,Swedish=sv")},s=function(e){var t=e.getParam("language","en");return e.getParam("spellchecker_language",t)},h=function(e){return e.getParam("spellchecker_rpc_url")},p=function(e){return e.getParam("spellchecker_callback")},m=function(e){var t=new RegExp('[^\\s!"#$%&()*+,-./:;<=>?@[\\]^_{|}`\xa7\xa9\xab\xae\xb1\xb6\xb7\xb8\xbb\xbc\xbd\xbe\xbf\xd7\xf7\xa4\u201d\u201c\u201e\xa0\u2002\u2003\u2009]+',"g");return e.getParam("spellchecker_wordchar_pattern",t)};function b(e){return e&&1===e.nodeType&&"false"===e.contentEditable}function r(a,r){var n,o,g,h,p,i=[],v=r.dom;function c(e,t){if(!e[0])throw new Error("findAndReplaceDOMText cannot handle zero-length matches");return{start:e.index,end:e.index+e[0].length,text:e[0],data:t}}function s(e){var t=a.getElementsByTagName("*"),n=[];e="number"==typeof e?""+e:null;for(var r=0;r =c.end?(o=l,a=c.end-u):r&&s.push(l),!r&&l.length+u>c.start&&(r=l,i=c.start-u),u+=l.length),r&&o){if(l=n({startNode:r,startNodeIndex:i,endNode:o,endNodeIndex:a,innerNodes:s,match:c.text,matchIndex:d}),u-=o.length-a,o=r=null,s=[],d++,!(c=t.shift()))break}else if(h[l.nodeName]&&!g[l.nodeName]||!l.firstChild){if(l.nextSibling){l=l.nextSibling;continue}}else if(!b(l)){l=l.firstChild;continue}for(;;){if(l.nextSibling){l=l.nextSibling;break}if(l.parentNode===e)break e;l=l.parentNode}}}(a,i,function t(o){function m(e,t){var n=i[t];n.stencil||(n.stencil=o(n));var r=n.stencil.cloneNode(!1);return r.setAttribute("data-mce-index",t),e&&r.appendChild(v.doc.createTextNode(e)),r}return function(e){var t,n,r,o=e.startNode,i=e.endNode,a=e.matchIndex,c=v.doc;if(o===i){var s=o;r=s.parentNode,0 0) { - for (i = x + 1; i < el.length; i++) { - if (canSelect(el[i])) { - return el[i]; - } - } - } else { - for (i = x - 1; i >= 0; i--) { - if (canSelect(el[i])) { - return el[i]; - } - } - } - - return null; - } - - if (e.keyCode === 9) { - v = explode(editor.getParam('tab_focus', editor.getParam('tabfocus_elements', ':prev,:next'))); - - if (v.length == 1) { - v[1] = v[0]; - v[0] = ':prev'; - } - - // Find element to focus - if (e.shiftKey) { - if (v[0] == ':prev') { - el = find(-1); - } else { - el = DOM.get(v[0]); - } - } else { - if (v[1] == ':next') { - el = find(1); - } else { - el = DOM.get(v[1]); - } - } - - if (el) { - if (el.id && (editor = tinymce.get(el.id || el.name))) { - editor.focus(); - } else { - window.setTimeout(function() { - if (!tinymce.Env.webkit) { - window.focus(); - } - - el.focus(); - }, 10); - } - - e.preventDefault(); - } - } - } - - editor.on('keyup', tabCancel); - - if (tinymce.Env.gecko) { - editor.on('keypress keydown', tabHandler); - } else { - editor.on('keydown', tabHandler); - } -}); +(function (domGlobals) { + 'use strict'; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var global$1 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils'); + + var global$2 = tinymce.util.Tools.resolve('tinymce.EditorManager'); + + var global$3 = tinymce.util.Tools.resolve('tinymce.Env'); + + var global$4 = tinymce.util.Tools.resolve('tinymce.util.Delay'); + + var global$5 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + + var global$6 = tinymce.util.Tools.resolve('tinymce.util.VK'); + + var getTabFocusElements = function (editor) { + return editor.getParam('tabfocus_elements', ':prev,:next'); + }; + var getTabFocus = function (editor) { + return editor.getParam('tab_focus', getTabFocusElements(editor)); + }; + var Settings = { getTabFocus: getTabFocus }; + + var DOM = global$1.DOM; + var tabCancel = function (e) { + if (e.keyCode === global$6.TAB && !e.ctrlKey && !e.altKey && !e.metaKey) { + e.preventDefault(); + } + }; + var setup = function (editor) { + function tabHandler(e) { + var x, el, v, i; + if (e.keyCode !== global$6.TAB || e.ctrlKey || e.altKey || e.metaKey || e.isDefaultPrevented()) { + return; + } + function find(direction) { + el = DOM.select(':input:enabled,*[tabindex]:not(iframe)'); + function canSelectRecursive(e) { + return e.nodeName === 'BODY' || e.type !== 'hidden' && e.style.display !== 'none' && e.style.visibility !== 'hidden' && canSelectRecursive(e.parentNode); + } + function canSelect(el) { + return /INPUT|TEXTAREA|BUTTON/.test(el.tagName) && global$2.get(e.id) && el.tabIndex !== -1 && canSelectRecursive(el); + } + global$5.each(el, function (e, i) { + if (e.id === editor.id) { + x = i; + return false; + } + }); + if (direction > 0) { + for (i = x + 1; i < el.length; i++) { + if (canSelect(el[i])) { + return el[i]; + } + } + } else { + for (i = x - 1; i >= 0; i--) { + if (canSelect(el[i])) { + return el[i]; + } + } + } + return null; + } + v = global$5.explode(Settings.getTabFocus(editor)); + if (v.length === 1) { + v[1] = v[0]; + v[0] = ':prev'; + } + if (e.shiftKey) { + if (v[0] === ':prev') { + el = find(-1); + } else { + el = DOM.get(v[0]); + } + } else { + if (v[1] === ':next') { + el = find(1); + } else { + el = DOM.get(v[1]); + } + } + if (el) { + var focusEditor = global$2.get(el.id || el.name); + if (el.id && focusEditor) { + focusEditor.focus(); + } else { + global$4.setTimeout(function () { + if (!global$3.webkit) { + domGlobals.window.focus(); + } + el.focus(); + }, 10); + } + e.preventDefault(); + } + } + editor.on('init', function () { + if (editor.inline) { + DOM.setAttrib(editor.getBody(), 'tabIndex', null); + } + editor.on('keyup', tabCancel); + if (global$3.gecko) { + editor.on('keypress keydown', tabHandler); + } else { + editor.on('keydown', tabHandler); + } + }); + }; + var Keyboard = { setup: setup }; + + function Plugin () { + global.add('tabfocus', function (editor) { + Keyboard.setup(editor); + }); + } + + Plugin(); + +}(window)); diff --git a/lib/tinymce/js/tinymce/plugins/tabfocus/plugin.min.js b/lib/tinymce/js/tinymce/plugins/tabfocus/plugin.min.js index 68e9223c..51b9bd5b 100644 --- a/lib/tinymce/js/tinymce/plugins/tabfocus/plugin.min.js +++ b/lib/tinymce/js/tinymce/plugins/tabfocus/plugin.min.js @@ -1 +1,9 @@ -tinymce.PluginManager.add("tabfocus",function(e){function t(e){9===e.keyCode&&e.preventDefault()}function n(t){function n(t){function n(e){return"BODY"===e.nodeName||"hidden"!=e.type&&"none"!=e.style.display&&"hidden"!=e.style.visibility&&n(e.parentNode)}function o(e){return e.attributes.tabIndex.specified||"INPUT"==e.nodeName||"TEXTAREA"==e.nodeName}function c(e){return!o(e)&&"-1"!=e.getAttribute("tabindex")&&n(e)}if(l=i.select(":input:enabled,*[tabindex]:not(iframe)"),a(l,function(t,n){return t.id==e.id?(r=n,!1):void 0}),t>0){for(s=r+1;l.length>s;s++)if(c(l[s]))return l[s]}else for(s=r-1;s>=0;s--)if(c(l[s]))return l[s];return null}var r,l,c,s;9===t.keyCode&&(c=o(e.getParam("tab_focus",e.getParam("tabfocus_elements",":prev,:next"))),1==c.length&&(c[1]=c[0],c[0]=":prev"),l=t.shiftKey?":prev"==c[0]?n(-1):i.get(c[0]):":next"==c[1]?n(1):i.get(c[1]),l&&(l.id&&(e=tinymce.get(l.id||l.name))?e.focus():window.setTimeout(function(){tinymce.Env.webkit||window.focus(),l.focus()},10),t.preventDefault()))}var i=tinymce.DOM,a=tinymce.each,o=tinymce.explode;e.on("keyup",t),tinymce.Env.gecko?e.on("keypress keydown",n):e.on("keydown",n)}); \ No newline at end of file +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.1.6 (2020-01-28) + */ +!function(c){"use strict";function t(e){e.keyCode!==d.TAB||e.ctrlKey||e.altKey||e.metaKey||e.preventDefault()}var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),n=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),s=tinymce.util.Tools.resolve("tinymce.EditorManager"),a=tinymce.util.Tools.resolve("tinymce.Env"),y=tinymce.util.Tools.resolve("tinymce.util.Delay"),f=tinymce.util.Tools.resolve("tinymce.util.Tools"),d=tinymce.util.Tools.resolve("tinymce.util.VK"),m=function(e){return e.getParam("tab_focus",function(e){return e.getParam("tabfocus_elements",":prev,:next")}(e))},v=n.DOM,i=function(r){function e(n){var i,o,e,l;if(!(n.keyCode!==d.TAB||n.ctrlKey||n.altKey||n.metaKey||n.isDefaultPrevented())&&(1===(e=f.explode(m(r))).length&&(e[1]=e[0],e[0]=":prev"),o=n.shiftKey?":prev"===e[0]?u(-1):v.get(e[0]):":next"===e[1]?u(1):v.get(e[1]))){var t=s.get(o.id||o.name);o.id&&t?t.focus():y.setTimeout(function(){a.webkit||c.window.focus(),o.focus()},10),n.preventDefault()}function u(e){function t(e){return/INPUT|TEXTAREA|BUTTON/.test(e.tagName)&&s.get(n.id)&&-1!==e.tabIndex&&function t(e){return"BODY"===e.nodeName||"hidden"!==e.type&&"none"!==e.style.display&&"hidden"!==e.style.visibility&&t(e.parentNode)}(e)}if(o=v.select(":input:enabled,*[tabindex]:not(iframe)"),f.each(o,function(e,t){if(e.id===r.id)return i=t,!1}),0 0) { - rng = dom.createRng(); - node = selectedCells[0]; - endNode = selectedCells[selectedCells.length - 1]; - rng.setStartBefore(node); - rng.setEndAfter(node); - - setPoint(node, 1); - walker = new TreeWalker(node, dom.getParent(selectedCells[0], 'table')); - - do { - if (node.nodeName == 'TD' || node.nodeName == 'TH') { - if (!dom.hasClass(node, 'mce-item-selected')) { - break; - } - - lastNode = node; - } - } while ((node = walker.next())); - - setPoint(lastNode); - - sel.setRng(rng); - } - - editor.nodeChanged(); - startCell = tableGrid = startTable = null; - } - }); - - editor.on('KeyUp', function() { - clear(); - }); - - return { - clear: clear - }; - }; -}); \ No newline at end of file diff --git a/lib/tinymce/js/tinymce/plugins/table/classes/Plugin.js b/lib/tinymce/js/tinymce/plugins/table/classes/Plugin.js deleted file mode 100644 index 66e4d704..00000000 --- a/lib/tinymce/js/tinymce/plugins/table/classes/Plugin.js +++ /dev/null @@ -1,706 +0,0 @@ -/** - * Plugin.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -/** - * This class contains all core logic for the table plugin. - * - * @class tinymce.tableplugin.Plugin - * @private - */ -define("tinymce/tableplugin/Plugin", [ - "tinymce/tableplugin/TableGrid", - "tinymce/tableplugin/Quirks", - "tinymce/tableplugin/CellSelection", - "tinymce/util/Tools", - "tinymce/dom/TreeWalker", - "tinymce/Env", - "tinymce/PluginManager" -], function(TableGrid, Quirks, CellSelection, Tools, TreeWalker, Env, PluginManager) { - var each = Tools.each; - - function Plugin(editor) { - var winMan, clipboardRows, self = this; // Might be selected cells on reload - - function removePxSuffix(size) { - return size ? size.replace(/px$/, '') : ""; - } - - function addSizeSuffix(size) { - if (/^[0-9]+$/.test(size)) { - size += "px"; - } - - return size; - } - - function tableDialog() { - var dom = editor.dom, tableElm, data; - - tableElm = editor.dom.getParent(editor.selection.getNode(), 'table'); - - data = { - width: removePxSuffix(dom.getStyle(tableElm, 'width') || dom.getAttrib(tableElm, 'width')), - height: removePxSuffix(dom.getStyle(tableElm, 'height') || dom.getAttrib(tableElm, 'height')), - cellspacing: dom.getAttrib(tableElm, 'cellspacing'), - cellpadding: dom.getAttrib(tableElm, 'cellpadding'), - border: dom.getAttrib(tableElm, 'border'), - caption: !!dom.select('caption', tableElm)[0] - }; - - each('left center right'.split(' '), function(name) { - if (editor.formatter.matchNode(tableElm, 'align' + name)) { - data.align = name; - } - }); - - editor.windowManager.open({ - title: "Table properties", - items: { - type: 'form', - layout: 'grid', - columns: 2, - data: data, - defaults: { - type: 'textbox', - maxWidth: 50 - }, - items: [ - {label: 'Cols', name: 'cols'}, - {label: 'Rows', name: 'rows'}, - {label: 'Width', name: 'width'}, - {label: 'Height', name: 'height'}, - {label: 'Cell spacing', name: 'cellspacing'}, - {label: 'Cell padding', name: 'cellpadding'}, - {label: 'Border', name: 'border'}, - {label: 'Caption', name: 'caption', type: 'checkbox'}, - { - label: 'Alignment', - minWidth: 90, - name: 'align', - type: 'listbox', - text: 'None', - maxWidth: null, - values: [ - {text: 'None', value: ''}, - {text: 'Left', value: 'left'}, - {text: 'Center', value: 'center'}, - {text: 'Right', value: 'right'} - ] - } - ] - }, - - onsubmit: function() { - var data = this.toJSON(), captionElm; - - editor.undoManager.transact(function() { - editor.dom.setAttribs(tableElm, { - cellspacing: data.cellspacing, - cellpadding: data.cellpadding, - border: data.border - }); - - editor.dom.setStyles(tableElm, { - width: addSizeSuffix(data.width), - height: addSizeSuffix(data.height) - }); - - // Toggle caption on/off - captionElm = dom.select('caption', tableElm)[0]; - - if (captionElm && !data.caption) { - dom.remove(captionElm); - } - - if (!captionElm && data.caption) { - captionElm = dom.create('caption'); - - if (!Env.ie) { - captionElm.innerHTML = '
'; - } - - tableElm.insertBefore(captionElm, tableElm.firstChild); - } - - // Apply/remove alignment - if (data.align) { - editor.formatter.apply('align' + data.align, {}, tableElm); - } else { - each('left center right'.split(' '), function(name) { - editor.formatter.remove('align' + name, {}, tableElm); - }); - } - - editor.focus(); - editor.addVisual(); - }); - } - }); - } - - function mergeDialog(grid, cell) { - editor.windowManager.open({ - title: "Merge cells", - body: [ - {label: 'Columns', name: 'cols', type: 'textbox', size: 5}, - {label: 'Rows', name: 'rows', type: 'textbox', size: 5} - ], - onsubmit: function() { - var data = this.toJSON(); - - editor.undoManager.transact(function() { - grid.merge(cell, data.cols, data.rows); - }); - } - }); - } - - function cellDialog() { - var dom = editor.dom, cellElm, data, cells = []; - - // Get selected cells or the current cell - cells = editor.dom.select('td.mce-item-selected,th.mce-item-selected'); - cellElm = editor.dom.getParent(editor.selection.getNode(), 'td,th'); - if (!cells.length && cellElm) { - cells.push(cellElm); - } - - cellElm = cellElm || cells[0]; - - data = { - width: removePxSuffix(dom.getStyle(cellElm, 'width') || dom.getAttrib(cellElm, 'width')), - height: removePxSuffix(dom.getStyle(cellElm, 'height') || dom.getAttrib(cellElm, 'height')), - scope: dom.getAttrib(cellElm, 'scope') - }; - - data.type = cellElm.nodeName.toLowerCase(); - - each('left center right'.split(' '), function(name) { - if (editor.formatter.matchNode(cellElm, 'align' + name)) { - data.align = name; - } - }); - - editor.windowManager.open({ - title: "Cell properties", - items: { - type: 'form', - data: data, - layout: 'grid', - columns: 2, - defaults: { - type: 'textbox', - maxWidth: 50 - }, - items: [ - {label: 'Width', name: 'width'}, - {label: 'Height', name: 'height'}, - { - label: 'Cell type', - name: 'type', - type: 'listbox', - text: 'None', - minWidth: 90, - maxWidth: null, - menu: [ - {text: 'Cell', value: 'td'}, - {text: 'Header cell', value: 'th'} - ] - }, - { - label: 'Scope', - name: 'scope', - type: 'listbox', - text: 'None', - minWidth: 90, - maxWidth: null, - menu: [ - {text: 'None', value: ''}, - {text: 'Row', value: 'row'}, - {text: 'Column', value: 'col'}, - {text: 'Row group', value: 'rowgroup'}, - {text: 'Column group', value: 'colgroup'} - ] - }, - { - label: 'Alignment', - name: 'align', - type: 'listbox', - text: 'None', - minWidth: 90, - maxWidth: null, - values: [ - {text: 'None', value: ''}, - {text: 'Left', value: 'left'}, - {text: 'Center', value: 'center'}, - {text: 'Right', value: 'right'} - ] - } - ] - }, - - onsubmit: function() { - var data = this.toJSON(); - - editor.undoManager.transact(function() { - each(cells, function(cellElm) { - editor.dom.setAttrib(cellElm, 'scope', data.scope); - - editor.dom.setStyles(cellElm, { - width: addSizeSuffix(data.width), - height: addSizeSuffix(data.height) - }); - - // Switch cell type - if (data.type && cellElm.nodeName.toLowerCase() != data.type) { - cellElm = dom.rename(cellElm, data.type); - } - - // Apply/remove alignment - if (data.align) { - editor.formatter.apply('align' + data.align, {}, cellElm); - } else { - each('left center right'.split(' '), function(name) { - editor.formatter.remove('align' + name, {}, cellElm); - }); - } - }); - - editor.focus(); - }); - } - }); - } - - function rowDialog() { - var dom = editor.dom, tableElm, cellElm, rowElm, data, rows = []; - - tableElm = editor.dom.getParent(editor.selection.getNode(), 'table'); - cellElm = editor.dom.getParent(editor.selection.getNode(), 'td,th'); - - each(tableElm.rows, function(row) { - each(row.cells, function(cell) { - if (dom.hasClass(cell, 'mce-item-selected') || cell == cellElm) { - rows.push(row); - return false; - } - }); - }); - - rowElm = rows[0]; - - data = { - height: removePxSuffix(dom.getStyle(rowElm, 'height') || dom.getAttrib(rowElm, 'height')), - scope: dom.getAttrib(rowElm, 'scope') - }; - - data.type = rowElm.parentNode.nodeName.toLowerCase(); - - each('left center right'.split(' '), function(name) { - if (editor.formatter.matchNode(rowElm, 'align' + name)) { - data.align = name; - } - }); - - editor.windowManager.open({ - title: "Row properties", - items: { - type: 'form', - data: data, - columns: 2, - defaults: { - type: 'textbox' - }, - items: [ - { - type: 'listbox', - name: 'type', - label: 'Row type', - text: 'None', - maxWidth: null, - menu: [ - {text: 'header', value: 'thead'}, - {text: 'body', value: 'tbody'}, - {text: 'footer', value: 'tfoot'} - ] - }, - { - type: 'listbox', - name: 'align', - label: 'Alignment', - text: 'None', - maxWidth: null, - menu: [ - {text: 'None', value: ''}, - {text: 'Left', value: 'left'}, - {text: 'Center', value: 'center'}, - {text: 'Right', value: 'right'} - ] - }, - {label: 'Height', name: 'height'} - ] - }, - - onsubmit: function() { - var data = this.toJSON(), tableElm, oldParentElm, parentElm; - - editor.undoManager.transact(function() { - each(rows, function(rowElm) { - editor.dom.setAttrib(rowElm, 'scope', data.scope); - - editor.dom.setStyles(rowElm, { - height: addSizeSuffix(data.height) - }); - - if (data.type != rowElm.parentNode.nodeName.toLowerCase()) { - tableElm = dom.getParent(rowElm, 'table'); - - oldParentElm = rowElm.parentNode; - parentElm = dom.select(tableElm, data.type)[0]; - if (!parentElm) { - parentElm = dom.create(data.type); - if (tableElm.firstChild) { - tableElm.insertBefore(parentElm, tableElm.firstChild); - } else { - tableElm.appendChild(parentElm); - } - } - - parentElm.insertBefore(rowElm, parentElm.firstChild); - - if (!oldParentElm.hasChildNodes()) { - dom.remove(oldParentElm); - } - } - - // Apply/remove alignment - if (data.align) { - editor.formatter.apply('align' + data.align, {}, rowElm); - } else { - each('left center right'.split(' '), function(name) { - editor.formatter.remove('align' + name, {}, rowElm); - }); - } - }); - - editor.focus(); - }); - } - }); - } - - function cmd(command) { - return function() { - editor.execCommand(command); - }; - } - - function insertTable(cols, rows) { - var y, x, html; - - html = ''; - - for (y = 0; y < rows; y++) { - html += '
'; - - editor.insertContent(html); - } - - function postRender() { - /*jshint validthis:true*/ - var self = this; - - function bindStateListener() { - self.disabled(!editor.dom.getParent(editor.selection.getNode(), 'table')); - - editor.selection.selectorChanged('table', function(state) { - self.disabled(!state); - }); - } - - if (editor.initialized) { - bindStateListener(); - } else { - editor.on('init', bindStateListener); - } - } - - // Register buttons - each([ - ['table', 'Insert/edit table', 'mceInsertTable'], - ['delete_table', 'Delete table', 'mceTableDelete'], - ['delete_col', 'Delete column', 'mceTableDeleteCol'], - ['delete_row', 'Delete row', 'mceTableDeleteRow'], - ['col_after', 'Insert column after', 'mceTableInsertColAfter'], - ['col_before', 'Insert column before', 'mceTableInsertColBefore'], - ['row_after', 'Insert row after', 'mceTableInsertRowAfter'], - ['row_before', 'Insert row before', 'mceTableInsertRowBefore'], - ['row_props', 'Row properties', 'mceTableRowProps'], - ['cell_props', 'Cell properties', 'mceTableCellProps'], - ['split_cells', 'Split cells', 'mceTableSplitCells'], - ['merge_cells', 'Merge cells', 'mceTableMergeCells'] - ], function(c) { - editor.addButton(c[0], { - title : c[1], - cmd : c[2], - onPostRender: postRender - }); - }); - - function generateTableGrid() { - var html = ''; - - html = ''; - - for (x = 0; x < cols; x++) { - html += ' '; - } - - html += '' + (Env.ie ? " " : ' '; - } - - html += '
') + ''; - - for (var y = 0; y < 10; y++) { - html += '
'; - - html += ''; - - for (var x = 0; x < 10; x++) { - html += ' '; - } - - html += ''; - } - - html += ' 0 x 0'; - - return html; - } - - editor.addMenuItem('inserttable', { - text: 'Insert table', - icon: 'table', - context: 'table', - onhide: function() { - editor.dom.removeClass(this.menu.items()[0].getEl().getElementsByTagName('a'), 'mce-active'); - }, - menu: [ - { - type: 'container', - html: generateTableGrid(), - - onmousemove: function(e) { - var target = e.target; - - if (target.nodeName == 'A') { - var table = editor.dom.getParent(target, 'table'); - var pos = target.getAttribute('data-mce-index'); - - if (pos != this.lastPos) { - pos = pos.split(','); - - pos[0] = parseInt(pos[0], 10); - pos[1] = parseInt(pos[1], 10); - - for (var y = 0; y < 10; y++) { - for (var x = 0; x < 10; x++) { - editor.dom.toggleClass( - table.rows[y].childNodes[x].firstChild, - 'mce-active', - x <= pos[0] && y <= pos[1] - ); - } - } - - table.nextSibling.innerHTML = (pos[0] + 1) + ' x '+ (pos[1] + 1); - this.lastPos = pos; - } - } - }, - - onclick: function(e) { - if (e.target.nodeName == 'A' && this.lastPos) { - e.preventDefault(); - - insertTable(this.lastPos[0] + 1, this.lastPos[1] + 1); - - // TODO: Maybe rework this? - this.parent().cancel(); // Close parent menu as if it was a click - } - } - } - ] - }); - - editor.addMenuItem('tableprops', { - text: 'Table properties', - context: 'table', - onPostRender: postRender, - onclick: tableDialog - }); - - editor.addMenuItem('deletetable', { - text: 'Delete table', - context: 'table', - onPostRender: postRender, - cmd: 'mceTableDelete' - }); - - editor.addMenuItem('cell', { - separator: 'before', - text: 'Cell', - context: 'table', - menu: [ - {text: 'Cell properties', onclick: cmd('mceTableCellProps'), onPostRender: postRender}, - {text: 'Merge cells', onclick: cmd('mceTableMergeCells'), onPostRender: postRender}, - {text: 'Split cell', onclick: cmd('mceTableSplitCells'), onPostRender: postRender} - ] - }); - - editor.addMenuItem('row', { - text: 'Row', - context: 'table', - menu: [ - {text: 'Insert row before', onclick: cmd('mceTableInsertRowBefore'), onPostRender: postRender}, - {text: 'Insert row after', onclick: cmd('mceTableInsertRowAfter'), onPostRender: postRender}, - {text: 'Delete row', onclick: cmd('mceTableDeleteRow'), onPostRender: postRender}, - {text: 'Row properties', onclick: cmd('mceTableRowProps'), onPostRender: postRender}, - {text: '-'}, - {text: 'Cut row', onclick: cmd('mceTableCutRow'), onPostRender: postRender}, - {text: 'Copy row', onclick: cmd('mceTableCopyRow'), onPostRender: postRender}, - {text: 'Paste row before', onclick: cmd('mceTablePasteRowBefore'), onPostRender: postRender}, - {text: 'Paste row after', onclick: cmd('mceTablePasteRowAfter'), onPostRender: postRender} - ] - }); - - editor.addMenuItem('column', { - text: 'Column', - context: 'table', - menu: [ - {text: 'Insert column before', onclick: cmd('mceTableInsertColBefore'), onPostRender: postRender}, - {text: 'Insert column after', onclick: cmd('mceTableInsertColAfter'), onPostRender: postRender}, - {text: 'Delete column', onclick: cmd('mceTableDeleteCol'), onPostRender: postRender} - ] - }); - - // Select whole table is a table border is clicked - if (!Env.isIE) { - editor.on('click', function(e) { - e = e.target; - - if (e.nodeName === 'TABLE') { - editor.selection.select(e); - editor.nodeChanged(); - } - }); - } - - self.quirks = new Quirks(editor); - - editor.on('Init', function() { - winMan = editor.windowManager; - self.cellSelection = new CellSelection(editor); - }); - - // Register action commands - each({ - mceTableSplitCells: function(grid) { - grid.split(); - }, - - mceTableMergeCells: function(grid) { - var rowSpan, colSpan, cell; - - cell = editor.dom.getParent(editor.selection.getNode(), 'th,td'); - if (cell) { - rowSpan = cell.rowSpan; - colSpan = cell.colSpan; - } - - if (!editor.dom.select('td.mce-item-selected,th.mce-item-selected').length) { - mergeDialog(grid, cell); - } else { - grid.merge(); - } - }, - - mceTableInsertRowBefore: function(grid) { - grid.insertRow(true); - }, - - mceTableInsertRowAfter: function(grid) { - grid.insertRow(); - }, - - mceTableInsertColBefore: function(grid) { - grid.insertCol(true); - }, - - mceTableInsertColAfter: function(grid) { - grid.insertCol(); - }, - - mceTableDeleteCol: function(grid) { - grid.deleteCols(); - }, - - mceTableDeleteRow: function(grid) { - grid.deleteRows(); - }, - - mceTableCutRow: function(grid) { - clipboardRows = grid.cutRows(); - }, - - mceTableCopyRow: function(grid) { - clipboardRows = grid.copyRows(); - }, - - mceTablePasteRowBefore: function(grid) { - grid.pasteRows(clipboardRows, true); - }, - - mceTablePasteRowAfter: function(grid) { - grid.pasteRows(clipboardRows); - }, - - mceTableDelete: function(grid) { - grid.deleteTable(); - } - }, function(func, name) { - editor.addCommand(name, function() { - var grid = new TableGrid(editor.selection); - - if (grid) { - func(grid); - editor.execCommand('mceRepaint'); - self.cellSelection.clear(); - } - }); - }); - - // Register dialog commands - each({ - mceInsertTable: function() { - tableDialog(); - }, - - mceTableRowProps: rowDialog, - mceTableCellProps: cellDialog - }, function(func, name) { - editor.addCommand(name, function(ui, val) { - func(val); - }); - }); - } - - PluginManager.add('table', Plugin); -}); diff --git a/lib/tinymce/js/tinymce/plugins/table/classes/Quirks.js b/lib/tinymce/js/tinymce/plugins/table/classes/Quirks.js deleted file mode 100644 index dec47aff..00000000 --- a/lib/tinymce/js/tinymce/plugins/table/classes/Quirks.js +++ /dev/null @@ -1,340 +0,0 @@ -/** - * Quirks.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -/** - * This class includes fixes for various browser quirks. - * - * @class tinymce.tableplugin.Quirks - * @private - */ -define("tinymce/tableplugin/Quirks", [ - "tinymce/util/VK", - "tinymce/Env", - "tinymce/util/Tools" -], function(VK, Env, Tools) { - var each = Tools.each; - - function getSpanVal(td, name) { - return parseInt(td.getAttribute(name) || 1, 10); - } - - return function(editor) { - /** - * Fixed caret movement around tables on WebKit. - */ - function moveWebKitSelection() { - function eventHandler(e) { - var key = e.keyCode; - - function handle(upBool, sourceNode) { - var siblingDirection = upBool ? 'previousSibling' : 'nextSibling'; - var currentRow = editor.dom.getParent(sourceNode, 'tr'); - var siblingRow = currentRow[siblingDirection]; - - if (siblingRow) { - moveCursorToRow(editor, sourceNode, siblingRow, upBool); - e.preventDefault(); - return true; - } else { - var tableNode = editor.dom.getParent(currentRow, 'table'); - var middleNode = currentRow.parentNode; - var parentNodeName = middleNode.nodeName.toLowerCase(); - if (parentNodeName === 'tbody' || parentNodeName === (upBool ? 'tfoot' : 'thead')) { - var targetParent = getTargetParent(upBool, tableNode, middleNode, 'tbody'); - if (targetParent !== null) { - return moveToRowInTarget(upBool, targetParent, sourceNode); - } - } - return escapeTable(upBool, currentRow, siblingDirection, tableNode); - } - } - - function getTargetParent(upBool, topNode, secondNode, nodeName) { - var tbodies = editor.dom.select('>' + nodeName, topNode); - var position = tbodies.indexOf(secondNode); - if (upBool && position === 0 || !upBool && position === tbodies.length - 1) { - return getFirstHeadOrFoot(upBool, topNode); - } else if (position === -1) { - var topOrBottom = secondNode.tagName.toLowerCase() === 'thead' ? 0 : tbodies.length - 1; - return tbodies[topOrBottom]; - } else { - return tbodies[position + (upBool ? -1 : 1)]; - } - } - - function getFirstHeadOrFoot(upBool, parent) { - var tagName = upBool ? 'thead' : 'tfoot'; - var headOrFoot = editor.dom.select('>' + tagName, parent); - return headOrFoot.length !== 0 ? headOrFoot[0] : null; - } - - function moveToRowInTarget(upBool, targetParent, sourceNode) { - var targetRow = getChildForDirection(targetParent, upBool); - - if (targetRow) { - moveCursorToRow(editor, sourceNode, targetRow, upBool); - } - - e.preventDefault(); - return true; - } - - function escapeTable(upBool, currentRow, siblingDirection, table) { - var tableSibling = table[siblingDirection]; - - if (tableSibling) { - moveCursorToStartOfElement(tableSibling); - return true; - } else { - var parentCell = editor.dom.getParent(table, 'td,th'); - if (parentCell) { - return handle(upBool, parentCell, e); - } else { - var backUpSibling = getChildForDirection(currentRow, !upBool); - moveCursorToStartOfElement(backUpSibling); - e.preventDefault(); - return false; - } - } - } - - function getChildForDirection(parent, up) { - var child = parent && parent[up ? 'lastChild' : 'firstChild']; - // BR is not a valid table child to return in this case we return the table cell - return child && child.nodeName === 'BR' ? editor.dom.getParent(child, 'td,th') : child; - } - - function moveCursorToStartOfElement(n) { - editor.selection.setCursorLocation(n, 0); - } - - function isVerticalMovement() { - return key == VK.UP || key == VK.DOWN; - } - - function isInTable(editor) { - var node = editor.selection.getNode(); - var currentRow = editor.dom.getParent(node, 'tr'); - return currentRow !== null; - } - - function columnIndex(column) { - var colIndex = 0; - var c = column; - while (c.previousSibling) { - c = c.previousSibling; - colIndex = colIndex + getSpanVal(c, "colspan"); - } - return colIndex; - } - - function findColumn(rowElement, columnIndex) { - var c = 0, r = 0; - - each(rowElement.children, function(cell, i) { - c = c + getSpanVal(cell, "colspan"); - r = i; - if (c > columnIndex) { - return false; - } - }); - return r; - } - - function moveCursorToRow(ed, node, row, upBool) { - var srcColumnIndex = columnIndex(editor.dom.getParent(node, 'td,th')); - var tgtColumnIndex = findColumn(row, srcColumnIndex); - var tgtNode = row.childNodes[tgtColumnIndex]; - var rowCellTarget = getChildForDirection(tgtNode, upBool); - moveCursorToStartOfElement(rowCellTarget || tgtNode); - } - - function shouldFixCaret(preBrowserNode) { - var newNode = editor.selection.getNode(); - var newParent = editor.dom.getParent(newNode, 'td,th'); - var oldParent = editor.dom.getParent(preBrowserNode, 'td,th'); - - return newParent && newParent !== oldParent && checkSameParentTable(newParent, oldParent); - } - - function checkSameParentTable(nodeOne, NodeTwo) { - return editor.dom.getParent(nodeOne, 'TABLE') === editor.dom.getParent(NodeTwo, 'TABLE'); - } - - if (isVerticalMovement() && isInTable(editor)) { - var preBrowserNode = editor.selection.getNode(); - setTimeout(function() { - if (shouldFixCaret(preBrowserNode)) { - handle(!e.shiftKey && key === VK.UP, preBrowserNode, e); - } - }, 0); - } - } - - editor.on('KeyDown', function(e) { - eventHandler(e); - }); - } - - function fixBeforeTableCaretBug() { - // Checks if the selection/caret is at the start of the specified block element - function isAtStart(rng, par) { - var doc = par.ownerDocument, rng2 = doc.createRange(), elm; - - rng2.setStartBefore(par); - rng2.setEnd(rng.endContainer, rng.endOffset); - - elm = doc.createElement('body'); - elm.appendChild(rng2.cloneContents()); - - // Check for text characters of other elements that should be treated as content - return elm.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi, '-').replace(/<[^>]+>/g, '').length === 0; - } - - // Fixes an bug where it's impossible to place the caret before a table in Gecko - // this fix solves it by detecting when the caret is at the beginning of such a table - // and then manually moves the caret infront of the table - editor.on('KeyDown', function(e) { - var rng, table, dom = editor.dom; - - // On gecko it's not possible to place the caret before a table - if (e.keyCode == 37 || e.keyCode == 38) { - rng = editor.selection.getRng(); - table = dom.getParent(rng.startContainer, 'table'); - - if (table && editor.getBody().firstChild == table) { - if (isAtStart(rng, table)) { - rng = dom.createRng(); - - rng.setStartBefore(table); - rng.setEndBefore(table); - - editor.selection.setRng(rng); - - e.preventDefault(); - } - } - } - }); - } - - // Fixes an issue on Gecko where it's impossible to place the caret behind a table - // This fix will force a paragraph element after the table but only when the forced_root_block setting is enabled - function fixTableCaretPos() { - editor.on('KeyDown SetContent VisualAid', function() { - var last; - - // Skip empty text nodes from the end - for (last = editor.getBody().lastChild; last; last = last.previousSibling) { - if (last.nodeType == 3) { - if (last.nodeValue.length > 0) { - break; - } - } else if (last.nodeType == 1 && !last.getAttribute('data-mce-bogus')) { - break; - } - } - - if (last && last.nodeName == 'TABLE') { - if (editor.settings.forced_root_block) { - editor.dom.add( - editor.getBody(), - editor.settings.forced_root_block, - null, - Env.ie ? ' ' : '
' - ); - } else { - editor.dom.add(editor.getBody(), 'br', {'data-mce-bogus': '1'}); - } - } - }); - - editor.on('PreProcess', function(o) { - var last = o.node.lastChild; - - if (last && (last.nodeName == "BR" || (last.childNodes.length == 1 && - (last.firstChild.nodeName == 'BR' || last.firstChild.nodeValue == '\u00a0'))) && - last.previousSibling && last.previousSibling.nodeName == "TABLE") { - editor.dom.remove(last); - } - }); - } - - // this nasty hack is here to work around some WebKit selection bugs. - function fixTableCellSelection() { - function tableCellSelected(ed, rng, n, currentCell) { - // The decision of when a table cell is selected is somewhat involved. The fact that this code is - // required is actually a pointer to the root cause of this bug. A cell is selected when the start - // and end offsets are 0, the start container is a text, and the selection node is either a TR (most cases) - // or the parent of the table (in the case of the selection containing the last cell of a table). - var TEXT_NODE = 3, table = ed.dom.getParent(rng.startContainer, 'TABLE'); - var tableParent, allOfCellSelected, tableCellSelection; - - if (table) { - tableParent = table.parentNode; - } - - allOfCellSelected =rng.startContainer.nodeType == TEXT_NODE && - rng.startOffset === 0 && - rng.endOffset === 0 && - currentCell && - (n.nodeName == "TR" || n == tableParent); - - tableCellSelection = (n.nodeName == "TD" || n.nodeName == "TH") && !currentCell; - - return allOfCellSelected || tableCellSelection; - } - - function fixSelection() { - var rng = editor.selection.getRng(); - var n = editor.selection.getNode(); - var currentCell = editor.dom.getParent(rng.startContainer, 'TD,TH'); - - if (!tableCellSelected(editor, rng, n, currentCell)) { - return; - } - - if (!currentCell) { - currentCell=n; - } - - // Get the very last node inside the table cell - var end = currentCell.lastChild; - while (end.lastChild) { - end = end.lastChild; - } - - // Select the entire table cell. Nothing outside of the table cell should be selected. - rng.setEnd(end, end.nodeValue.length); - editor.selection.setRng(rng); - } - - editor.on('KeyDown', function() { - fixSelection(); - }); - - editor.on('MouseDown', function(e) { - if (e.button != 2) { - fixSelection(); - } - }); - } - - if (Env.webkit) { - moveWebKitSelection(); - fixTableCellSelection(); - } - - if (Env.gecko) { - fixBeforeTableCaretBug(); - fixTableCaretPos(); - } - }; -}); \ No newline at end of file diff --git a/lib/tinymce/js/tinymce/plugins/table/classes/TableGrid.js b/lib/tinymce/js/tinymce/plugins/table/classes/TableGrid.js deleted file mode 100644 index 40950fa2..00000000 --- a/lib/tinymce/js/tinymce/plugins/table/classes/TableGrid.js +++ /dev/null @@ -1,811 +0,0 @@ -/** - * TableGrid.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -/** - * This class creates a grid out of a table element. This - * makes it a whole lot easier to handle complex tables with - * col/row spans. - * - * @class tinymce.tableplugin.TableGrid - * @private - */ -define("tinymce/tableplugin/TableGrid", [ - "tinymce/util/Tools", - "tinymce/Env" -], function(Tools, Env) { - var each = Tools.each; - - function getSpanVal(td, name) { - return parseInt(td.getAttribute(name) || 1, 10); - } - - return function(selection, table) { - var grid, startPos, endPos, selectedCell, dom = selection.dom; - - function buildGrid() { - var startY = 0; - - grid = []; - - each(['thead', 'tbody', 'tfoot'], function(part) { - var rows = dom.select('> ' + part + ' tr', table); - - each(rows, function(tr, y) { - y += startY; - - each(dom.select('> td, > th', tr), function(td, x) { - var x2, y2, rowspan, colspan; - - // Skip over existing cells produced by rowspan - if (grid[y]) { - while (grid[y][x]) { - x++; - } - } - - // Get col/rowspan from cell - rowspan = getSpanVal(td, 'rowspan'); - colspan = getSpanVal(td, 'colspan'); - - // Fill out rowspan/colspan right and down - for (y2 = y; y2 < y + rowspan; y2++) { - if (!grid[y2]) { - grid[y2] = []; - } - - for (x2 = x; x2 < x + colspan; x2++) { - grid[y2][x2] = { - part: part, - real: y2 == y && x2 == x, - elm: td, - rowspan: rowspan, - colspan: colspan - }; - } - } - }); - }); - - startY += rows.length; - }); - } - - function cloneNode(node, children) { - node = node.cloneNode(children); - node.removeAttribute('id'); - - return node; - } - - function getCell(x, y) { - var row; - - row = grid[y]; - if (row) { - return row[x]; - } - } - - function setSpanVal(td, name, val) { - if (td) { - val = parseInt(val, 10); - - if (val === 1) { - td.removeAttribute(name, 1); - } else { - td.setAttribute(name, val, 1); - } - } - } - - function isCellSelected(cell) { - return cell && (dom.hasClass(cell.elm, 'mce-item-selected') || cell == selectedCell); - } - - function getSelectedRows() { - var rows = []; - - each(table.rows, function(row) { - each(row.cells, function(cell) { - if (dom.hasClass(cell, 'mce-item-selected') || cell == selectedCell.elm) { - rows.push(row); - return false; - } - }); - }); - - return rows; - } - - function deleteTable() { - var rng = dom.createRng(); - - rng.setStartAfter(table); - rng.setEndAfter(table); - - selection.setRng(rng); - - dom.remove(table); - } - - function cloneCell(cell) { - var formatNode; - - // Clone formats - Tools.walk(cell, function(node) { - var curNode; - - if (node.nodeType == 3) { - each(dom.getParents(node.parentNode, null, cell).reverse(), function(node) { - node = cloneNode(node, false); - - if (!formatNode) { - formatNode = curNode = node; - } else if (curNode) { - curNode.appendChild(node); - } - - curNode = node; - }); - - // Add something to the inner node - if (curNode) { - curNode.innerHTML = Env.ie ? ' ' : '
'; - } - - return false; - } - }, 'childNodes'); - - cell = cloneNode(cell, false); - setSpanVal(cell, 'rowSpan', 1); - setSpanVal(cell, 'colSpan', 1); - - if (formatNode) { - cell.appendChild(formatNode); - } else { - if (!Env.ie) { - cell.innerHTML = '
'; - } - } - - return cell; - } - - function cleanup() { - var rng = dom.createRng(), row; - - // Empty rows - each(dom.select('tr', table), function(tr) { - if (tr.cells.length === 0) { - dom.remove(tr); - } - }); - - // Empty table - if (dom.select('tr', table).length === 0) { - rng.setStartAfter(table); - rng.setEndAfter(table); - selection.setRng(rng); - dom.remove(table); - return; - } - - // Empty header/body/footer - each(dom.select('thead,tbody,tfoot', table), function(part) { - if (part.rows.length === 0) { - dom.remove(part); - } - }); - - // Restore selection to start position if it still exists - buildGrid(); - - // Restore the selection to the closest table position - row = grid[Math.min(grid.length - 1, startPos.y)]; - if (row) { - selection.select(row[Math.min(row.length - 1, startPos.x)].elm, true); - selection.collapse(true); - } - } - - function fillLeftDown(x, y, rows, cols) { - var tr, x2, r, c, cell; - - tr = grid[y][x].elm.parentNode; - for (r = 1; r <= rows; r++) { - tr = dom.getNext(tr, 'tr'); - - if (tr) { - // Loop left to find real cell - for (x2 = x; x2 >= 0; x2--) { - cell = grid[y + r][x2].elm; - - if (cell.parentNode == tr) { - // Append clones after - for (c = 1; c <= cols; c++) { - dom.insertAfter(cloneCell(cell), cell); - } - - break; - } - } - - if (x2 == -1) { - // Insert nodes before first cell - for (c = 1; c <= cols; c++) { - tr.insertBefore(cloneCell(tr.cells[0]), tr.cells[0]); - } - } - } - } - } - - function split() { - each(grid, function(row, y) { - each(row, function(cell, x) { - var colSpan, rowSpan, i; - - if (isCellSelected(cell)) { - cell = cell.elm; - colSpan = getSpanVal(cell, 'colspan'); - rowSpan = getSpanVal(cell, 'rowspan'); - - if (colSpan > 1 || rowSpan > 1) { - setSpanVal(cell, 'rowSpan', 1); - setSpanVal(cell, 'colSpan', 1); - - // Insert cells right - for (i = 0; i < colSpan - 1; i++) { - dom.insertAfter(cloneCell(cell), cell); - } - - fillLeftDown(x, y, rowSpan - 1, colSpan); - } - } - }); - }); - } - - function merge(cell, cols, rows) { - var pos, startX, startY, endX, endY, x, y, startCell, endCell, children, count; - - // Use specified cell and cols/rows - if (cell) { - pos = getPos(cell); - startX = pos.x; - startY = pos.y; - endX = startX + (cols - 1); - endY = startY + (rows - 1); - } else { - startPos = endPos = null; - - // Calculate start/end pos by checking for selected cells in grid works better with context menu - each(grid, function(row, y) { - each(row, function(cell, x) { - if (isCellSelected(cell)) { - if (!startPos) { - startPos = {x: x, y: y}; - } - - endPos = {x: x, y: y}; - } - }); - }); - - // Use selection - startX = startPos.x; - startY = startPos.y; - endX = endPos.x; - endY = endPos.y; - } - - // Find start/end cells - startCell = getCell(startX, startY); - endCell = getCell(endX, endY); - - // Check if the cells exists and if they are of the same part for example tbody = tbody - if (startCell && endCell && startCell.part == endCell.part) { - // Split and rebuild grid - split(); - buildGrid(); - - // Set row/col span to start cell - startCell = getCell(startX, startY).elm; - setSpanVal(startCell, 'colSpan', (endX - startX) + 1); - setSpanVal(startCell, 'rowSpan', (endY - startY) + 1); - - // Remove other cells and add it's contents to the start cell - for (y = startY; y <= endY; y++) { - for (x = startX; x <= endX; x++) { - if (!grid[y] || !grid[y][x]) { - continue; - } - - cell = grid[y][x].elm; - - /*jshint loopfunc:true */ - if (cell != startCell) { - // Move children to startCell - children = Tools.grep(cell.childNodes); - each(children, function(node) { - startCell.appendChild(node); - }); - - // Remove bogus nodes if there is children in the target cell - if (children.length) { - children = Tools.grep(startCell.childNodes); - count = 0; - each(children, function(node) { - if (node.nodeName == 'BR' && dom.getAttrib(node, 'data-mce-bogus') && count++ < children.length - 1) { - startCell.removeChild(node); - } - }); - } - - dom.remove(cell); - } - } - } - - // Remove empty rows etc and restore caret location - cleanup(); - } - } - - function insertRow(before) { - var posY, cell, lastCell, x, rowElm, newRow, newCell, otherCell, rowSpan; - - // Find first/last row - each(grid, function(row, y) { - each(row, function(cell) { - if (isCellSelected(cell)) { - cell = cell.elm; - rowElm = cell.parentNode; - newRow = cloneNode(rowElm, false); - posY = y; - - if (before) { - return false; - } - } - }); - - if (before) { - return !posY; - } - }); - - for (x = 0; x < grid[0].length; x++) { - // Cell not found could be because of an invalid table structure - if (!grid[posY][x]) { - continue; - } - - cell = grid[posY][x].elm; - - if (cell != lastCell) { - if (!before) { - rowSpan = getSpanVal(cell, 'rowspan'); - if (rowSpan > 1) { - setSpanVal(cell, 'rowSpan', rowSpan + 1); - continue; - } - } else { - // Check if cell above can be expanded - if (posY > 0 && grid[posY - 1][x]) { - otherCell = grid[posY - 1][x].elm; - rowSpan = getSpanVal(otherCell, 'rowSpan'); - if (rowSpan > 1) { - setSpanVal(otherCell, 'rowSpan', rowSpan + 1); - continue; - } - } - } - - // Insert new cell into new row - newCell = cloneCell(cell); - setSpanVal(newCell, 'colSpan', cell.colSpan); - - newRow.appendChild(newCell); - - lastCell = cell; - } - } - - if (newRow.hasChildNodes()) { - if (!before) { - dom.insertAfter(newRow, rowElm); - } else { - rowElm.parentNode.insertBefore(newRow, rowElm); - } - } - } - - function insertCol(before) { - var posX, lastCell; - - // Find first/last column - each(grid, function(row) { - each(row, function(cell, x) { - if (isCellSelected(cell)) { - posX = x; - - if (before) { - return false; - } - } - }); - - if (before) { - return !posX; - } - }); - - each(grid, function(row, y) { - var cell, rowSpan, colSpan; - - if (!row[posX]) { - return; - } - - cell = row[posX].elm; - if (cell != lastCell) { - colSpan = getSpanVal(cell, 'colspan'); - rowSpan = getSpanVal(cell, 'rowspan'); - - if (colSpan == 1) { - if (!before) { - dom.insertAfter(cloneCell(cell), cell); - fillLeftDown(posX, y, rowSpan - 1, colSpan); - } else { - cell.parentNode.insertBefore(cloneCell(cell), cell); - fillLeftDown(posX, y, rowSpan - 1, colSpan); - } - } else { - setSpanVal(cell, 'colSpan', cell.colSpan + 1); - } - - lastCell = cell; - } - }); - } - - function deleteCols() { - var cols = []; - - // Get selected column indexes - each(grid, function(row) { - each(row, function(cell, x) { - if (isCellSelected(cell) && Tools.inArray(cols, x) === -1) { - each(grid, function(row) { - var cell = row[x].elm, colSpan; - - colSpan = getSpanVal(cell, 'colSpan'); - - if (colSpan > 1) { - setSpanVal(cell, 'colSpan', colSpan - 1); - } else { - dom.remove(cell); - } - }); - - cols.push(x); - } - }); - }); - - cleanup(); - } - - function deleteRows() { - var rows; - - function deleteRow(tr) { - var nextTr, pos, lastCell; - - nextTr = dom.getNext(tr, 'tr'); - - // Move down row spanned cells - each(tr.cells, function(cell) { - var rowSpan = getSpanVal(cell, 'rowSpan'); - - if (rowSpan > 1) { - setSpanVal(cell, 'rowSpan', rowSpan - 1); - pos = getPos(cell); - fillLeftDown(pos.x, pos.y, 1, 1); - } - }); - - // Delete cells - pos = getPos(tr.cells[0]); - each(grid[pos.y], function(cell) { - var rowSpan; - - cell = cell.elm; - - if (cell != lastCell) { - rowSpan = getSpanVal(cell, 'rowSpan'); - - if (rowSpan <= 1) { - dom.remove(cell); - } else { - setSpanVal(cell, 'rowSpan', rowSpan - 1); - } - - lastCell = cell; - } - }); - } - - // Get selected rows and move selection out of scope - rows = getSelectedRows(); - - // Delete all selected rows - each(rows.reverse(), function(tr) { - deleteRow(tr); - }); - - cleanup(); - } - - function cutRows() { - var rows = getSelectedRows(); - - dom.remove(rows); - cleanup(); - - return rows; - } - - function copyRows() { - var rows = getSelectedRows(); - - each(rows, function(row, i) { - rows[i] = cloneNode(row, true); - }); - - return rows; - } - - function pasteRows(rows, before) { - var selectedRows = getSelectedRows(), - targetRow = selectedRows[before ? 0 : selectedRows.length - 1], - targetCellCount = targetRow.cells.length; - - // Nothing to paste - if (!rows) { - return; - } - - // Calc target cell count - each(grid, function(row) { - var match; - - targetCellCount = 0; - each(row, function(cell) { - if (cell.real) { - targetCellCount += cell.colspan; - } - - if (cell.elm.parentNode == targetRow) { - match = 1; - } - }); - - if (match) { - return false; - } - }); - - if (!before) { - rows.reverse(); - } - - each(rows, function(row) { - var i, cellCount = row.cells.length, cell; - - // Remove col/rowspans - for (i = 0; i < cellCount; i++) { - cell = row.cells[i]; - setSpanVal(cell, 'colSpan', 1); - setSpanVal(cell, 'rowSpan', 1); - } - - // Needs more cells - for (i = cellCount; i < targetCellCount; i++) { - row.appendChild(cloneCell(row.cells[cellCount - 1])); - } - - // Needs less cells - for (i = targetCellCount; i < cellCount; i++) { - dom.remove(row.cells[i]); - } - - // Add before/after - if (before) { - targetRow.parentNode.insertBefore(row, targetRow); - } else { - dom.insertAfter(row, targetRow); - } - }); - - // Remove current selection - dom.removeClass(dom.select('td.mce-item-selected,th.mce-item-selected'), 'mce-item-selected'); - } - - function getPos(target) { - var pos; - - each(grid, function(row, y) { - each(row, function(cell, x) { - if (cell.elm == target) { - pos = {x : x, y : y}; - return false; - } - }); - - return !pos; - }); - - return pos; - } - - function setStartCell(cell) { - startPos = getPos(cell); - } - - function findEndPos() { - var maxX, maxY; - - maxX = maxY = 0; - - each(grid, function(row, y) { - each(row, function(cell, x) { - var colSpan, rowSpan; - - if (isCellSelected(cell)) { - cell = grid[y][x]; - - if (x > maxX) { - maxX = x; - } - - if (y > maxY) { - maxY = y; - } - - if (cell.real) { - colSpan = cell.colspan - 1; - rowSpan = cell.rowspan - 1; - - if (colSpan) { - if (x + colSpan > maxX) { - maxX = x + colSpan; - } - } - - if (rowSpan) { - if (y + rowSpan > maxY) { - maxY = y + rowSpan; - } - } - } - } - }); - }); - - return {x : maxX, y : maxY}; - } - - function setEndCell(cell) { - var startX, startY, endX, endY, maxX, maxY, colSpan, rowSpan, x, y; - - endPos = getPos(cell); - - if (startPos && endPos) { - // Get start/end positions - startX = Math.min(startPos.x, endPos.x); - startY = Math.min(startPos.y, endPos.y); - endX = Math.max(startPos.x, endPos.x); - endY = Math.max(startPos.y, endPos.y); - - // Expand end positon to include spans - maxX = endX; - maxY = endY; - - // Expand startX - for (y = startY; y <= maxY; y++) { - cell = grid[y][startX]; - - if (!cell.real) { - if (startX - (cell.colspan - 1) < startX) { - startX -= cell.colspan - 1; - } - } - } - - // Expand startY - for (x = startX; x <= maxX; x++) { - cell = grid[startY][x]; - - if (!cell.real) { - if (startY - (cell.rowspan - 1) < startY) { - startY -= cell.rowspan - 1; - } - } - } - - // Find max X, Y - for (y = startY; y <= endY; y++) { - for (x = startX; x <= endX; x++) { - cell = grid[y][x]; - - if (cell.real) { - colSpan = cell.colspan - 1; - rowSpan = cell.rowspan - 1; - - if (colSpan) { - if (x + colSpan > maxX) { - maxX = x + colSpan; - } - } - - if (rowSpan) { - if (y + rowSpan > maxY) { - maxY = y + rowSpan; - } - } - } - } - } - - // Remove current selection - dom.removeClass(dom.select('td.mce-item-selected,th.mce-item-selected'), 'mce-item-selected'); - - // Add new selection - for (y = startY; y <= maxY; y++) { - for (x = startX; x <= maxX; x++) { - if (grid[y][x]) { - dom.addClass(grid[y][x].elm, 'mce-item-selected'); - } - } - } - } - } - - table = table || dom.getParent(selection.getNode(), 'table'); - - buildGrid(); - - selectedCell = dom.getParent(selection.getStart(), 'th,td'); - if (selectedCell) { - startPos = getPos(selectedCell); - endPos = findEndPos(); - selectedCell = getCell(startPos.x, startPos.y); - } - - Tools.extend(this, { - deleteTable: deleteTable, - split: split, - merge: merge, - insertRow: insertRow, - insertCol: insertCol, - deleteCols: deleteCols, - deleteRows: deleteRows, - cutRows: cutRows, - copyRows: copyRows, - pasteRows: pasteRows, - getPos: getPos, - setStartCell: setStartCell, - setEndCell: setEndCell - }); - }; -}); \ No newline at end of file diff --git a/lib/tinymce/js/tinymce/plugins/table/plugin.dev.js b/lib/tinymce/js/tinymce/plugins/table/plugin.dev.js deleted file mode 100644 index 83da5cea..00000000 --- a/lib/tinymce/js/tinymce/plugins/table/plugin.dev.js +++ /dev/null @@ -1,119 +0,0 @@ -/** - * Inline development version. Only to be used while developing since it uses document.write to load scripts. - */ - -/*jshint smarttabs:true, undef:true, latedef:true, curly:true, bitwise:true, camelcase:true */ -/*globals $code */ - -(function(exports) { - "use strict"; - - var html = "", baseDir; - var modules = {}, exposedModules = [], moduleCount = 0; - - var scripts = document.getElementsByTagName('script'); - for (var i = 0; i < scripts.length; i++) { - var src = scripts[i].src; - - if (src.indexOf('/plugin.dev.js') != -1) { - baseDir = src.substring(0, src.lastIndexOf('/')); - } - } - - function require(ids, callback) { - var module, defs = []; - - for (var i = 0; i < ids.length; ++i) { - module = modules[ids[i]] || resolve(ids[i]); - if (!module) { - throw 'module definition dependecy not found: ' + ids[i]; - } - - defs.push(module); - } - - callback.apply(null, defs); - } - - function resolve(id) { - var target = exports; - var fragments = id.split(/[.\/]/); - - for (var fi = 0; fi < fragments.length; ++fi) { - if (!target[fragments[fi]]) { - return; - } - - target = target[fragments[fi]]; - } - - return target; - } - - function register(id) { - var target = exports; - var fragments = id.split(/[.\/]/); - - for (var fi = 0; fi < fragments.length - 1; ++fi) { - if (target[fragments[fi]] === undefined) { - target[fragments[fi]] = {}; - } - - target = target[fragments[fi]]; - } - - target[fragments[fragments.length - 1]] = modules[id]; - } - - function define(id, dependencies, definition) { - if (typeof id !== 'string') { - throw 'invalid module definition, module id must be defined and be a string'; - } - - if (dependencies === undefined) { - throw 'invalid module definition, dependencies must be specified'; - } - - if (definition === undefined) { - throw 'invalid module definition, definition function must be specified'; - } - - require(dependencies, function() { - modules[id] = definition.apply(null, arguments); - }); - - if (--moduleCount === 0) { - for (var i = 0; i < exposedModules.length; i++) { - register(exposedModules[i]); - } - } - } - - function expose(ids) { - exposedModules = ids; - } - - function writeScripts() { - document.write(html); - } - - function load(path) { - html += '\n'; - moduleCount++; - } - - // Expose globally - exports.define = define; - exports.require = require; - - expose(["tinymce/tableplugin/TableGrid","tinymce/tableplugin/Quirks","tinymce/tableplugin/CellSelection","tinymce/tableplugin/Plugin"]); - - load('classes/TableGrid.js'); - load('classes/Quirks.js'); - load('classes/CellSelection.js'); - load('classes/Plugin.js'); - - writeScripts(); -})(this); - -// $hash: e4bdae6ca54498d0dabca12fdf4a2caf \ No newline at end of file diff --git a/lib/tinymce/js/tinymce/plugins/table/plugin.js b/lib/tinymce/js/tinymce/plugins/table/plugin.js index e7bbfe4d..29638341 100644 --- a/lib/tinymce/js/tinymce/plugins/table/plugin.js +++ b/lib/tinymce/js/tinymce/plugins/table/plugin.js @@ -1,2114 +1,9499 @@ /** - * Compiled inline version. (Library mode) - */ - -/*jshint smarttabs:true, undef:true, latedef:true, curly:true, bitwise:true, camelcase:true */ -/*globals $code */ - -(function(exports, undefined) { - "use strict"; - - var modules = {}; - - function require(ids, callback) { - var module, defs = []; - - for (var i = 0; i < ids.length; ++i) { - module = modules[ids[i]] || resolve(ids[i]); - if (!module) { - throw 'module definition dependecy not found: ' + ids[i]; - } - - defs.push(module); - } - - callback.apply(null, defs); - } - - function define(id, dependencies, definition) { - if (typeof id !== 'string') { - throw 'invalid module definition, module id must be defined and be a string'; - } - - if (dependencies === undefined) { - throw 'invalid module definition, dependencies must be specified'; - } - - if (definition === undefined) { - throw 'invalid module definition, definition function must be specified'; - } - - require(dependencies, function() { - modules[id] = definition.apply(null, arguments); - }); - } - - function defined(id) { - return !!modules[id]; - } - - function resolve(id) { - var target = exports; - var fragments = id.split(/[.\/]/); - - for (var fi = 0; fi < fragments.length; ++fi) { - if (!target[fragments[fi]]) { - return; - } - - target = target[fragments[fi]]; - } - - return target; - } - - function expose(ids) { - for (var i = 0; i < ids.length; i++) { - var target = exports; - var id = ids[i]; - var fragments = id.split(/[.\/]/); - - for (var fi = 0; fi < fragments.length - 1; ++fi) { - if (target[fragments[fi]] === undefined) { - target[fragments[fi]] = {}; - } - - target = target[fragments[fi]]; - } - - target[fragments[fragments.length - 1]] = modules[id]; - } - } - -// Included from: js/tinymce/plugins/table/classes/TableGrid.js - -/** - * TableGrid.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -/** - * This class creates a grid out of a table element. This - * makes it a whole lot easier to handle complex tables with - * col/row spans. - * - * @class tinymce.tableplugin.TableGrid - * @private - */ -define("tinymce/tableplugin/TableGrid", [ - "tinymce/util/Tools", - "tinymce/Env" -], function(Tools, Env) { - var each = Tools.each; - - function getSpanVal(td, name) { - return parseInt(td.getAttribute(name) || 1, 10); - } - - return function(selection, table) { - var grid, startPos, endPos, selectedCell, dom = selection.dom; - - function buildGrid() { - var startY = 0; - - grid = []; - - each(['thead', 'tbody', 'tfoot'], function(part) { - var rows = dom.select('> ' + part + ' tr', table); - - each(rows, function(tr, y) { - y += startY; - - each(dom.select('> td, > th', tr), function(td, x) { - var x2, y2, rowspan, colspan; - - // Skip over existing cells produced by rowspan - if (grid[y]) { - while (grid[y][x]) { - x++; - } - } - - // Get col/rowspan from cell - rowspan = getSpanVal(td, 'rowspan'); - colspan = getSpanVal(td, 'colspan'); - - // Fill out rowspan/colspan right and down - for (y2 = y; y2 < y + rowspan; y2++) { - if (!grid[y2]) { - grid[y2] = []; - } - - for (x2 = x; x2 < x + colspan; x2++) { - grid[y2][x2] = { - part: part, - real: y2 == y && x2 == x, - elm: td, - rowspan: rowspan, - colspan: colspan - }; - } - } - }); - }); - - startY += rows.length; - }); - } - - function cloneNode(node, children) { - node = node.cloneNode(children); - node.removeAttribute('id'); - - return node; - } - - function getCell(x, y) { - var row; - - row = grid[y]; - if (row) { - return row[x]; - } - } - - function setSpanVal(td, name, val) { - if (td) { - val = parseInt(val, 10); - - if (val === 1) { - td.removeAttribute(name, 1); - } else { - td.setAttribute(name, val, 1); - } - } - } - - function isCellSelected(cell) { - return cell && (dom.hasClass(cell.elm, 'mce-item-selected') || cell == selectedCell); - } - - function getSelectedRows() { - var rows = []; - - each(table.rows, function(row) { - each(row.cells, function(cell) { - if (dom.hasClass(cell, 'mce-item-selected') || cell == selectedCell.elm) { - rows.push(row); - return false; - } - }); - }); - - return rows; - } - - function deleteTable() { - var rng = dom.createRng(); - - rng.setStartAfter(table); - rng.setEndAfter(table); - - selection.setRng(rng); - - dom.remove(table); - } - - function cloneCell(cell) { - var formatNode; - - // Clone formats - Tools.walk(cell, function(node) { - var curNode; - - if (node.nodeType == 3) { - each(dom.getParents(node.parentNode, null, cell).reverse(), function(node) { - node = cloneNode(node, false); - - if (!formatNode) { - formatNode = curNode = node; - } else if (curNode) { - curNode.appendChild(node); - } - - curNode = node; - }); - - // Add something to the inner node - if (curNode) { - curNode.innerHTML = Env.ie ? ' ' : '
'; - } - - return false; - } - }, 'childNodes'); - - cell = cloneNode(cell, false); - setSpanVal(cell, 'rowSpan', 1); - setSpanVal(cell, 'colSpan', 1); - - if (formatNode) { - cell.appendChild(formatNode); - } else { - if (!Env.ie) { - cell.innerHTML = '
'; - } - } - - return cell; - } - - function cleanup() { - var rng = dom.createRng(), row; - - // Empty rows - each(dom.select('tr', table), function(tr) { - if (tr.cells.length === 0) { - dom.remove(tr); - } - }); - - // Empty table - if (dom.select('tr', table).length === 0) { - rng.setStartAfter(table); - rng.setEndAfter(table); - selection.setRng(rng); - dom.remove(table); - return; - } - - // Empty header/body/footer - each(dom.select('thead,tbody,tfoot', table), function(part) { - if (part.rows.length === 0) { - dom.remove(part); - } - }); - - // Restore selection to start position if it still exists - buildGrid(); - - // Restore the selection to the closest table position - row = grid[Math.min(grid.length - 1, startPos.y)]; - if (row) { - selection.select(row[Math.min(row.length - 1, startPos.x)].elm, true); - selection.collapse(true); - } - } - - function fillLeftDown(x, y, rows, cols) { - var tr, x2, r, c, cell; - - tr = grid[y][x].elm.parentNode; - for (r = 1; r <= rows; r++) { - tr = dom.getNext(tr, 'tr'); - - if (tr) { - // Loop left to find real cell - for (x2 = x; x2 >= 0; x2--) { - cell = grid[y + r][x2].elm; - - if (cell.parentNode == tr) { - // Append clones after - for (c = 1; c <= cols; c++) { - dom.insertAfter(cloneCell(cell), cell); - } - - break; - } - } - - if (x2 == -1) { - // Insert nodes before first cell - for (c = 1; c <= cols; c++) { - tr.insertBefore(cloneCell(tr.cells[0]), tr.cells[0]); - } - } - } - } - } - - function split() { - each(grid, function(row, y) { - each(row, function(cell, x) { - var colSpan, rowSpan, i; - - if (isCellSelected(cell)) { - cell = cell.elm; - colSpan = getSpanVal(cell, 'colspan'); - rowSpan = getSpanVal(cell, 'rowspan'); - - if (colSpan > 1 || rowSpan > 1) { - setSpanVal(cell, 'rowSpan', 1); - setSpanVal(cell, 'colSpan', 1); - - // Insert cells right - for (i = 0; i < colSpan - 1; i++) { - dom.insertAfter(cloneCell(cell), cell); - } - - fillLeftDown(x, y, rowSpan - 1, colSpan); - } - } - }); - }); - } - - function merge(cell, cols, rows) { - var pos, startX, startY, endX, endY, x, y, startCell, endCell, children, count; - - // Use specified cell and cols/rows - if (cell) { - pos = getPos(cell); - startX = pos.x; - startY = pos.y; - endX = startX + (cols - 1); - endY = startY + (rows - 1); - } else { - startPos = endPos = null; - - // Calculate start/end pos by checking for selected cells in grid works better with context menu - each(grid, function(row, y) { - each(row, function(cell, x) { - if (isCellSelected(cell)) { - if (!startPos) { - startPos = {x: x, y: y}; - } - - endPos = {x: x, y: y}; - } - }); - }); - - // Use selection - startX = startPos.x; - startY = startPos.y; - endX = endPos.x; - endY = endPos.y; - } - - // Find start/end cells - startCell = getCell(startX, startY); - endCell = getCell(endX, endY); - - // Check if the cells exists and if they are of the same part for example tbody = tbody - if (startCell && endCell && startCell.part == endCell.part) { - // Split and rebuild grid - split(); - buildGrid(); - - // Set row/col span to start cell - startCell = getCell(startX, startY).elm; - setSpanVal(startCell, 'colSpan', (endX - startX) + 1); - setSpanVal(startCell, 'rowSpan', (endY - startY) + 1); - - // Remove other cells and add it's contents to the start cell - for (y = startY; y <= endY; y++) { - for (x = startX; x <= endX; x++) { - if (!grid[y] || !grid[y][x]) { - continue; - } - - cell = grid[y][x].elm; - - /*jshint loopfunc:true */ - if (cell != startCell) { - // Move children to startCell - children = Tools.grep(cell.childNodes); - each(children, function(node) { - startCell.appendChild(node); - }); - - // Remove bogus nodes if there is children in the target cell - if (children.length) { - children = Tools.grep(startCell.childNodes); - count = 0; - each(children, function(node) { - if (node.nodeName == 'BR' && dom.getAttrib(node, 'data-mce-bogus') && count++ < children.length - 1) { - startCell.removeChild(node); - } - }); - } - - dom.remove(cell); - } - } - } - - // Remove empty rows etc and restore caret location - cleanup(); - } - } - - function insertRow(before) { - var posY, cell, lastCell, x, rowElm, newRow, newCell, otherCell, rowSpan; - - // Find first/last row - each(grid, function(row, y) { - each(row, function(cell) { - if (isCellSelected(cell)) { - cell = cell.elm; - rowElm = cell.parentNode; - newRow = cloneNode(rowElm, false); - posY = y; - - if (before) { - return false; - } - } - }); - - if (before) { - return !posY; - } - }); - - for (x = 0; x < grid[0].length; x++) { - // Cell not found could be because of an invalid table structure - if (!grid[posY][x]) { - continue; - } - - cell = grid[posY][x].elm; - - if (cell != lastCell) { - if (!before) { - rowSpan = getSpanVal(cell, 'rowspan'); - if (rowSpan > 1) { - setSpanVal(cell, 'rowSpan', rowSpan + 1); - continue; - } - } else { - // Check if cell above can be expanded - if (posY > 0 && grid[posY - 1][x]) { - otherCell = grid[posY - 1][x].elm; - rowSpan = getSpanVal(otherCell, 'rowSpan'); - if (rowSpan > 1) { - setSpanVal(otherCell, 'rowSpan', rowSpan + 1); - continue; - } - } - } - - // Insert new cell into new row - newCell = cloneCell(cell); - setSpanVal(newCell, 'colSpan', cell.colSpan); - - newRow.appendChild(newCell); - - lastCell = cell; - } - } - - if (newRow.hasChildNodes()) { - if (!before) { - dom.insertAfter(newRow, rowElm); - } else { - rowElm.parentNode.insertBefore(newRow, rowElm); - } - } - } - - function insertCol(before) { - var posX, lastCell; - - // Find first/last column - each(grid, function(row) { - each(row, function(cell, x) { - if (isCellSelected(cell)) { - posX = x; - - if (before) { - return false; - } - } - }); - - if (before) { - return !posX; - } - }); - - each(grid, function(row, y) { - var cell, rowSpan, colSpan; - - if (!row[posX]) { - return; - } - - cell = row[posX].elm; - if (cell != lastCell) { - colSpan = getSpanVal(cell, 'colspan'); - rowSpan = getSpanVal(cell, 'rowspan'); - - if (colSpan == 1) { - if (!before) { - dom.insertAfter(cloneCell(cell), cell); - fillLeftDown(posX, y, rowSpan - 1, colSpan); - } else { - cell.parentNode.insertBefore(cloneCell(cell), cell); - fillLeftDown(posX, y, rowSpan - 1, colSpan); - } - } else { - setSpanVal(cell, 'colSpan', cell.colSpan + 1); - } - - lastCell = cell; - } - }); - } - - function deleteCols() { - var cols = []; - - // Get selected column indexes - each(grid, function(row) { - each(row, function(cell, x) { - if (isCellSelected(cell) && Tools.inArray(cols, x) === -1) { - each(grid, function(row) { - var cell = row[x].elm, colSpan; - - colSpan = getSpanVal(cell, 'colSpan'); - - if (colSpan > 1) { - setSpanVal(cell, 'colSpan', colSpan - 1); - } else { - dom.remove(cell); - } - }); - - cols.push(x); - } - }); - }); - - cleanup(); - } - - function deleteRows() { - var rows; - - function deleteRow(tr) { - var nextTr, pos, lastCell; - - nextTr = dom.getNext(tr, 'tr'); - - // Move down row spanned cells - each(tr.cells, function(cell) { - var rowSpan = getSpanVal(cell, 'rowSpan'); - - if (rowSpan > 1) { - setSpanVal(cell, 'rowSpan', rowSpan - 1); - pos = getPos(cell); - fillLeftDown(pos.x, pos.y, 1, 1); - } - }); - - // Delete cells - pos = getPos(tr.cells[0]); - each(grid[pos.y], function(cell) { - var rowSpan; - - cell = cell.elm; - - if (cell != lastCell) { - rowSpan = getSpanVal(cell, 'rowSpan'); - - if (rowSpan <= 1) { - dom.remove(cell); - } else { - setSpanVal(cell, 'rowSpan', rowSpan - 1); - } - - lastCell = cell; - } - }); - } - - // Get selected rows and move selection out of scope - rows = getSelectedRows(); - - // Delete all selected rows - each(rows.reverse(), function(tr) { - deleteRow(tr); - }); - - cleanup(); - } - - function cutRows() { - var rows = getSelectedRows(); - - dom.remove(rows); - cleanup(); - - return rows; - } - - function copyRows() { - var rows = getSelectedRows(); - - each(rows, function(row, i) { - rows[i] = cloneNode(row, true); - }); - - return rows; - } - - function pasteRows(rows, before) { - var selectedRows = getSelectedRows(), - targetRow = selectedRows[before ? 0 : selectedRows.length - 1], - targetCellCount = targetRow.cells.length; - - // Nothing to paste - if (!rows) { - return; - } - - // Calc target cell count - each(grid, function(row) { - var match; - - targetCellCount = 0; - each(row, function(cell) { - if (cell.real) { - targetCellCount += cell.colspan; - } - - if (cell.elm.parentNode == targetRow) { - match = 1; - } - }); - - if (match) { - return false; - } - }); - - if (!before) { - rows.reverse(); - } - - each(rows, function(row) { - var i, cellCount = row.cells.length, cell; - - // Remove col/rowspans - for (i = 0; i < cellCount; i++) { - cell = row.cells[i]; - setSpanVal(cell, 'colSpan', 1); - setSpanVal(cell, 'rowSpan', 1); - } - - // Needs more cells - for (i = cellCount; i < targetCellCount; i++) { - row.appendChild(cloneCell(row.cells[cellCount - 1])); - } - - // Needs less cells - for (i = targetCellCount; i < cellCount; i++) { - dom.remove(row.cells[i]); - } - - // Add before/after - if (before) { - targetRow.parentNode.insertBefore(row, targetRow); - } else { - dom.insertAfter(row, targetRow); - } - }); - - // Remove current selection - dom.removeClass(dom.select('td.mce-item-selected,th.mce-item-selected'), 'mce-item-selected'); - } - - function getPos(target) { - var pos; - - each(grid, function(row, y) { - each(row, function(cell, x) { - if (cell.elm == target) { - pos = {x : x, y : y}; - return false; - } - }); - - return !pos; - }); - - return pos; - } - - function setStartCell(cell) { - startPos = getPos(cell); - } - - function findEndPos() { - var maxX, maxY; - - maxX = maxY = 0; - - each(grid, function(row, y) { - each(row, function(cell, x) { - var colSpan, rowSpan; - - if (isCellSelected(cell)) { - cell = grid[y][x]; - - if (x > maxX) { - maxX = x; - } - - if (y > maxY) { - maxY = y; - } - - if (cell.real) { - colSpan = cell.colspan - 1; - rowSpan = cell.rowspan - 1; - - if (colSpan) { - if (x + colSpan > maxX) { - maxX = x + colSpan; - } - } - - if (rowSpan) { - if (y + rowSpan > maxY) { - maxY = y + rowSpan; - } - } - } - } - }); - }); - - return {x : maxX, y : maxY}; - } - - function setEndCell(cell) { - var startX, startY, endX, endY, maxX, maxY, colSpan, rowSpan, x, y; - - endPos = getPos(cell); - - if (startPos && endPos) { - // Get start/end positions - startX = Math.min(startPos.x, endPos.x); - startY = Math.min(startPos.y, endPos.y); - endX = Math.max(startPos.x, endPos.x); - endY = Math.max(startPos.y, endPos.y); - - // Expand end positon to include spans - maxX = endX; - maxY = endY; - - // Expand startX - for (y = startY; y <= maxY; y++) { - cell = grid[y][startX]; - - if (!cell.real) { - if (startX - (cell.colspan - 1) < startX) { - startX -= cell.colspan - 1; - } - } - } - - // Expand startY - for (x = startX; x <= maxX; x++) { - cell = grid[startY][x]; - - if (!cell.real) { - if (startY - (cell.rowspan - 1) < startY) { - startY -= cell.rowspan - 1; - } - } - } - - // Find max X, Y - for (y = startY; y <= endY; y++) { - for (x = startX; x <= endX; x++) { - cell = grid[y][x]; - - if (cell.real) { - colSpan = cell.colspan - 1; - rowSpan = cell.rowspan - 1; - - if (colSpan) { - if (x + colSpan > maxX) { - maxX = x + colSpan; - } - } - - if (rowSpan) { - if (y + rowSpan > maxY) { - maxY = y + rowSpan; - } - } - } - } - } - - // Remove current selection - dom.removeClass(dom.select('td.mce-item-selected,th.mce-item-selected'), 'mce-item-selected'); - - // Add new selection - for (y = startY; y <= maxY; y++) { - for (x = startX; x <= maxX; x++) { - if (grid[y][x]) { - dom.addClass(grid[y][x].elm, 'mce-item-selected'); - } - } - } - } - } - - table = table || dom.getParent(selection.getNode(), 'table'); - - buildGrid(); - - selectedCell = dom.getParent(selection.getStart(), 'th,td'); - if (selectedCell) { - startPos = getPos(selectedCell); - endPos = findEndPos(); - selectedCell = getCell(startPos.x, startPos.y); - } - - Tools.extend(this, { - deleteTable: deleteTable, - split: split, - merge: merge, - insertRow: insertRow, - insertCol: insertCol, - deleteCols: deleteCols, - deleteRows: deleteRows, - cutRows: cutRows, - copyRows: copyRows, - pasteRows: pasteRows, - getPos: getPos, - setStartCell: setStartCell, - setEndCell: setEndCell - }); - }; -}); - -// Included from: js/tinymce/plugins/table/classes/Quirks.js - -/** - * Quirks.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -/** - * This class includes fixes for various browser quirks. - * - * @class tinymce.tableplugin.Quirks - * @private - */ -define("tinymce/tableplugin/Quirks", [ - "tinymce/util/VK", - "tinymce/Env", - "tinymce/util/Tools" -], function(VK, Env, Tools) { - var each = Tools.each; - - function getSpanVal(td, name) { - return parseInt(td.getAttribute(name) || 1, 10); - } - - return function(editor) { - /** - * Fixed caret movement around tables on WebKit. - */ - function moveWebKitSelection() { - function eventHandler(e) { - var key = e.keyCode; - - function handle(upBool, sourceNode) { - var siblingDirection = upBool ? 'previousSibling' : 'nextSibling'; - var currentRow = editor.dom.getParent(sourceNode, 'tr'); - var siblingRow = currentRow[siblingDirection]; - - if (siblingRow) { - moveCursorToRow(editor, sourceNode, siblingRow, upBool); - e.preventDefault(); - return true; - } else { - var tableNode = editor.dom.getParent(currentRow, 'table'); - var middleNode = currentRow.parentNode; - var parentNodeName = middleNode.nodeName.toLowerCase(); - if (parentNodeName === 'tbody' || parentNodeName === (upBool ? 'tfoot' : 'thead')) { - var targetParent = getTargetParent(upBool, tableNode, middleNode, 'tbody'); - if (targetParent !== null) { - return moveToRowInTarget(upBool, targetParent, sourceNode); - } - } - return escapeTable(upBool, currentRow, siblingDirection, tableNode); - } - } - - function getTargetParent(upBool, topNode, secondNode, nodeName) { - var tbodies = editor.dom.select('>' + nodeName, topNode); - var position = tbodies.indexOf(secondNode); - if (upBool && position === 0 || !upBool && position === tbodies.length - 1) { - return getFirstHeadOrFoot(upBool, topNode); - } else if (position === -1) { - var topOrBottom = secondNode.tagName.toLowerCase() === 'thead' ? 0 : tbodies.length - 1; - return tbodies[topOrBottom]; - } else { - return tbodies[position + (upBool ? -1 : 1)]; - } - } - - function getFirstHeadOrFoot(upBool, parent) { - var tagName = upBool ? 'thead' : 'tfoot'; - var headOrFoot = editor.dom.select('>' + tagName, parent); - return headOrFoot.length !== 0 ? headOrFoot[0] : null; - } - - function moveToRowInTarget(upBool, targetParent, sourceNode) { - var targetRow = getChildForDirection(targetParent, upBool); - - if (targetRow) { - moveCursorToRow(editor, sourceNode, targetRow, upBool); - } - - e.preventDefault(); - return true; - } - - function escapeTable(upBool, currentRow, siblingDirection, table) { - var tableSibling = table[siblingDirection]; - - if (tableSibling) { - moveCursorToStartOfElement(tableSibling); - return true; - } else { - var parentCell = editor.dom.getParent(table, 'td,th'); - if (parentCell) { - return handle(upBool, parentCell, e); - } else { - var backUpSibling = getChildForDirection(currentRow, !upBool); - moveCursorToStartOfElement(backUpSibling); - e.preventDefault(); - return false; - } - } - } - - function getChildForDirection(parent, up) { - var child = parent && parent[up ? 'lastChild' : 'firstChild']; - // BR is not a valid table child to return in this case we return the table cell - return child && child.nodeName === 'BR' ? editor.dom.getParent(child, 'td,th') : child; - } - - function moveCursorToStartOfElement(n) { - editor.selection.setCursorLocation(n, 0); - } - - function isVerticalMovement() { - return key == VK.UP || key == VK.DOWN; - } - - function isInTable(editor) { - var node = editor.selection.getNode(); - var currentRow = editor.dom.getParent(node, 'tr'); - return currentRow !== null; - } - - function columnIndex(column) { - var colIndex = 0; - var c = column; - while (c.previousSibling) { - c = c.previousSibling; - colIndex = colIndex + getSpanVal(c, "colspan"); - } - return colIndex; - } - - function findColumn(rowElement, columnIndex) { - var c = 0, r = 0; - - each(rowElement.children, function(cell, i) { - c = c + getSpanVal(cell, "colspan"); - r = i; - if (c > columnIndex) { - return false; - } - }); - return r; - } - - function moveCursorToRow(ed, node, row, upBool) { - var srcColumnIndex = columnIndex(editor.dom.getParent(node, 'td,th')); - var tgtColumnIndex = findColumn(row, srcColumnIndex); - var tgtNode = row.childNodes[tgtColumnIndex]; - var rowCellTarget = getChildForDirection(tgtNode, upBool); - moveCursorToStartOfElement(rowCellTarget || tgtNode); - } - - function shouldFixCaret(preBrowserNode) { - var newNode = editor.selection.getNode(); - var newParent = editor.dom.getParent(newNode, 'td,th'); - var oldParent = editor.dom.getParent(preBrowserNode, 'td,th'); - - return newParent && newParent !== oldParent && checkSameParentTable(newParent, oldParent); - } - - function checkSameParentTable(nodeOne, NodeTwo) { - return editor.dom.getParent(nodeOne, 'TABLE') === editor.dom.getParent(NodeTwo, 'TABLE'); - } - - if (isVerticalMovement() && isInTable(editor)) { - var preBrowserNode = editor.selection.getNode(); - setTimeout(function() { - if (shouldFixCaret(preBrowserNode)) { - handle(!e.shiftKey && key === VK.UP, preBrowserNode, e); - } - }, 0); - } - } - - editor.on('KeyDown', function(e) { - eventHandler(e); - }); - } - - function fixBeforeTableCaretBug() { - // Checks if the selection/caret is at the start of the specified block element - function isAtStart(rng, par) { - var doc = par.ownerDocument, rng2 = doc.createRange(), elm; - - rng2.setStartBefore(par); - rng2.setEnd(rng.endContainer, rng.endOffset); - - elm = doc.createElement('body'); - elm.appendChild(rng2.cloneContents()); - - // Check for text characters of other elements that should be treated as content - return elm.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi, '-').replace(/<[^>]+>/g, '').length === 0; - } - - // Fixes an bug where it's impossible to place the caret before a table in Gecko - // this fix solves it by detecting when the caret is at the beginning of such a table - // and then manually moves the caret infront of the table - editor.on('KeyDown', function(e) { - var rng, table, dom = editor.dom; - - // On gecko it's not possible to place the caret before a table - if (e.keyCode == 37 || e.keyCode == 38) { - rng = editor.selection.getRng(); - table = dom.getParent(rng.startContainer, 'table'); - - if (table && editor.getBody().firstChild == table) { - if (isAtStart(rng, table)) { - rng = dom.createRng(); - - rng.setStartBefore(table); - rng.setEndBefore(table); - - editor.selection.setRng(rng); - - e.preventDefault(); - } - } - } - }); - } - - // Fixes an issue on Gecko where it's impossible to place the caret behind a table - // This fix will force a paragraph element after the table but only when the forced_root_block setting is enabled - function fixTableCaretPos() { - editor.on('KeyDown SetContent VisualAid', function() { - var last; - - // Skip empty text nodes from the end - for (last = editor.getBody().lastChild; last; last = last.previousSibling) { - if (last.nodeType == 3) { - if (last.nodeValue.length > 0) { - break; - } - } else if (last.nodeType == 1 && !last.getAttribute('data-mce-bogus')) { - break; - } - } - - if (last && last.nodeName == 'TABLE') { - if (editor.settings.forced_root_block) { - editor.dom.add( - editor.getBody(), - editor.settings.forced_root_block, - null, - Env.ie ? ' ' : '
' - ); - } else { - editor.dom.add(editor.getBody(), 'br', {'data-mce-bogus': '1'}); - } - } - }); - - editor.on('PreProcess', function(o) { - var last = o.node.lastChild; - - if (last && (last.nodeName == "BR" || (last.childNodes.length == 1 && - (last.firstChild.nodeName == 'BR' || last.firstChild.nodeValue == '\u00a0'))) && - last.previousSibling && last.previousSibling.nodeName == "TABLE") { - editor.dom.remove(last); - } - }); - } - - // this nasty hack is here to work around some WebKit selection bugs. - function fixTableCellSelection() { - function tableCellSelected(ed, rng, n, currentCell) { - // The decision of when a table cell is selected is somewhat involved. The fact that this code is - // required is actually a pointer to the root cause of this bug. A cell is selected when the start - // and end offsets are 0, the start container is a text, and the selection node is either a TR (most cases) - // or the parent of the table (in the case of the selection containing the last cell of a table). - var TEXT_NODE = 3, table = ed.dom.getParent(rng.startContainer, 'TABLE'); - var tableParent, allOfCellSelected, tableCellSelection; - - if (table) { - tableParent = table.parentNode; - } - - allOfCellSelected =rng.startContainer.nodeType == TEXT_NODE && - rng.startOffset === 0 && - rng.endOffset === 0 && - currentCell && - (n.nodeName == "TR" || n == tableParent); - - tableCellSelection = (n.nodeName == "TD" || n.nodeName == "TH") && !currentCell; - - return allOfCellSelected || tableCellSelection; - } - - function fixSelection() { - var rng = editor.selection.getRng(); - var n = editor.selection.getNode(); - var currentCell = editor.dom.getParent(rng.startContainer, 'TD,TH'); - - if (!tableCellSelected(editor, rng, n, currentCell)) { - return; - } - - if (!currentCell) { - currentCell=n; - } - - // Get the very last node inside the table cell - var end = currentCell.lastChild; - while (end.lastChild) { - end = end.lastChild; - } - - // Select the entire table cell. Nothing outside of the table cell should be selected. - rng.setEnd(end, end.nodeValue.length); - editor.selection.setRng(rng); - } - - editor.on('KeyDown', function() { - fixSelection(); - }); - - editor.on('MouseDown', function(e) { - if (e.button != 2) { - fixSelection(); - } - }); - } - - if (Env.webkit) { - moveWebKitSelection(); - fixTableCellSelection(); - } - - if (Env.gecko) { - fixBeforeTableCaretBug(); - fixTableCaretPos(); - } - }; -}); - -// Included from: js/tinymce/plugins/table/classes/CellSelection.js - -/** - * CellSelection.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -/** - * This class handles table cell selection by faking it using a css class that gets applied - * to cells when dragging the mouse from one cell to another. - * - * @class tinymce.tableplugin.CellSelection - * @private - */ -define("tinymce/tableplugin/CellSelection", [ - "tinymce/tableplugin/TableGrid", - "tinymce/dom/TreeWalker", - "tinymce/util/Tools" -], function(TableGrid, TreeWalker, Tools) { - return function(editor) { - var dom = editor.dom, tableGrid, startCell, startTable, hasCellSelection = true; - - function clear() { - // Restore selection possibilities - editor.getBody().style.webkitUserSelect = ''; - - if (hasCellSelection) { - editor.dom.removeClass( - editor.dom.select('td.mce-item-selected,th.mce-item-selected'), - 'mce-item-selected' - ); - - hasCellSelection = false; - } - } - - // Add cell selection logic - editor.on('MouseDown', function(e) { - if (e.button != 2) { - clear(); - - startCell = dom.getParent(e.target, 'td,th'); - startTable = dom.getParent(startCell, 'table'); - } - }); - - dom.bind(editor.getDoc(), 'mouseover', function(e) { - var sel, table, target = e.target; - - if (startCell && (tableGrid || target != startCell) && (target.nodeName == 'TD' || target.nodeName == 'TH')) { - table = dom.getParent(target, 'table'); - if (table == startTable) { - if (!tableGrid) { - tableGrid = new TableGrid(editor.selection, table); - tableGrid.setStartCell(startCell); - - editor.getBody().style.webkitUserSelect = 'none'; - } - - tableGrid.setEndCell(target); - hasCellSelection = true; - } - - // Remove current selection - sel = editor.selection.getSel(); - - try { - if (sel.removeAllRanges) { - sel.removeAllRanges(); - } else { - sel.empty(); - } - } catch (ex) { - // IE9 might throw errors here - } - - e.preventDefault(); - } - }); - - editor.on('MouseUp', function() { - var rng, sel = editor.selection, selectedCells, walker, node, lastNode, endNode; - - function setPoint(node, start) { - var walker = new TreeWalker(node, node); - - do { - // Text node - if (node.nodeType == 3 && Tools.trim(node.nodeValue).length !== 0) { - if (start) { - rng.setStart(node, 0); - } else { - rng.setEnd(node, node.nodeValue.length); - } - - return; - } - - // BR element - if (node.nodeName == 'BR') { - if (start) { - rng.setStartBefore(node); - } else { - rng.setEndBefore(node); - } - - return; - } - } while ((node = (start ? walker.next() : walker.prev()))); - } - - // Move selection to startCell - if (startCell) { - if (tableGrid) { - editor.getBody().style.webkitUserSelect = ''; - } - - // Try to expand text selection as much as we can only Gecko supports cell selection - selectedCells = dom.select('td.mce-item-selected,th.mce-item-selected'); - if (selectedCells.length > 0) { - rng = dom.createRng(); - node = selectedCells[0]; - endNode = selectedCells[selectedCells.length - 1]; - rng.setStartBefore(node); - rng.setEndAfter(node); - - setPoint(node, 1); - walker = new TreeWalker(node, dom.getParent(selectedCells[0], 'table')); - - do { - if (node.nodeName == 'TD' || node.nodeName == 'TH') { - if (!dom.hasClass(node, 'mce-item-selected')) { - break; - } - - lastNode = node; - } - } while ((node = walker.next())); - - setPoint(lastNode); - - sel.setRng(rng); - } - - editor.nodeChanged(); - startCell = tableGrid = startTable = null; - } - }); - - editor.on('KeyUp', function() { - clear(); - }); - - return { - clear: clear - }; - }; -}); - -// Included from: js/tinymce/plugins/table/classes/Plugin.js - -/** - * Plugin.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ - -/** - * This class contains all core logic for the table plugin. + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ * - * @class tinymce.tableplugin.Plugin - * @private + * Version: 5.1.6 (2020-01-28) */ -define("tinymce/tableplugin/Plugin", [ - "tinymce/tableplugin/TableGrid", - "tinymce/tableplugin/Quirks", - "tinymce/tableplugin/CellSelection", - "tinymce/util/Tools", - "tinymce/dom/TreeWalker", - "tinymce/Env", - "tinymce/PluginManager" -], function(TableGrid, Quirks, CellSelection, Tools, TreeWalker, Env, PluginManager) { - var each = Tools.each; - - function Plugin(editor) { - var winMan, clipboardRows, self = this; // Might be selected cells on reload - - function removePxSuffix(size) { - return size ? size.replace(/px$/, '') : ""; - } - - function addSizeSuffix(size) { - if (/^[0-9]+$/.test(size)) { - size += "px"; - } - - return size; - } - - function tableDialog() { - var dom = editor.dom, tableElm, data; - - tableElm = editor.dom.getParent(editor.selection.getNode(), 'table'); - - data = { - width: removePxSuffix(dom.getStyle(tableElm, 'width') || dom.getAttrib(tableElm, 'width')), - height: removePxSuffix(dom.getStyle(tableElm, 'height') || dom.getAttrib(tableElm, 'height')), - cellspacing: dom.getAttrib(tableElm, 'cellspacing'), - cellpadding: dom.getAttrib(tableElm, 'cellpadding'), - border: dom.getAttrib(tableElm, 'border'), - caption: !!dom.select('caption', tableElm)[0] - }; - - each('left center right'.split(' '), function(name) { - if (editor.formatter.matchNode(tableElm, 'align' + name)) { - data.align = name; - } - }); - - editor.windowManager.open({ - title: "Table properties", - items: { - type: 'form', - layout: 'grid', - columns: 2, - data: data, - defaults: { - type: 'textbox', - maxWidth: 50 - }, - items: [ - {label: 'Cols', name: 'cols'}, - {label: 'Rows', name: 'rows'}, - {label: 'Width', name: 'width'}, - {label: 'Height', name: 'height'}, - {label: 'Cell spacing', name: 'cellspacing'}, - {label: 'Cell padding', name: 'cellpadding'}, - {label: 'Border', name: 'border'}, - {label: 'Caption', name: 'caption', type: 'checkbox'}, - { - label: 'Alignment', - minWidth: 90, - name: 'align', - type: 'listbox', - text: 'None', - maxWidth: null, - values: [ - {text: 'None', value: ''}, - {text: 'Left', value: 'left'}, - {text: 'Center', value: 'center'}, - {text: 'Right', value: 'right'} - ] - } - ] - }, - - onsubmit: function() { - var data = this.toJSON(), captionElm; - - editor.undoManager.transact(function() { - editor.dom.setAttribs(tableElm, { - cellspacing: data.cellspacing, - cellpadding: data.cellpadding, - border: data.border - }); - - editor.dom.setStyles(tableElm, { - width: addSizeSuffix(data.width), - height: addSizeSuffix(data.height) - }); - - // Toggle caption on/off - captionElm = dom.select('caption', tableElm)[0]; - - if (captionElm && !data.caption) { - dom.remove(captionElm); - } - - if (!captionElm && data.caption) { - captionElm = dom.create('caption'); - - if (!Env.ie) { - captionElm.innerHTML = '
'; - } - - tableElm.insertBefore(captionElm, tableElm.firstChild); - } - - // Apply/remove alignment - if (data.align) { - editor.formatter.apply('align' + data.align, {}, tableElm); - } else { - each('left center right'.split(' '), function(name) { - editor.formatter.remove('align' + name, {}, tableElm); - }); - } - - editor.focus(); - editor.addVisual(); - }); - } - }); - } - - function mergeDialog(grid, cell) { - editor.windowManager.open({ - title: "Merge cells", - body: [ - {label: 'Columns', name: 'cols', type: 'textbox', size: 5}, - {label: 'Rows', name: 'rows', type: 'textbox', size: 5} - ], - onsubmit: function() { - var data = this.toJSON(); - - editor.undoManager.transact(function() { - grid.merge(cell, data.cols, data.rows); - }); - } - }); - } - - function cellDialog() { - var dom = editor.dom, cellElm, data, cells = []; - - // Get selected cells or the current cell - cells = editor.dom.select('td.mce-item-selected,th.mce-item-selected'); - cellElm = editor.dom.getParent(editor.selection.getNode(), 'td,th'); - if (!cells.length && cellElm) { - cells.push(cellElm); - } - - cellElm = cellElm || cells[0]; - - data = { - width: removePxSuffix(dom.getStyle(cellElm, 'width') || dom.getAttrib(cellElm, 'width')), - height: removePxSuffix(dom.getStyle(cellElm, 'height') || dom.getAttrib(cellElm, 'height')), - scope: dom.getAttrib(cellElm, 'scope') - }; - - data.type = cellElm.nodeName.toLowerCase(); - - each('left center right'.split(' '), function(name) { - if (editor.formatter.matchNode(cellElm, 'align' + name)) { - data.align = name; - } - }); - - editor.windowManager.open({ - title: "Cell properties", - items: { - type: 'form', - data: data, - layout: 'grid', - columns: 2, - defaults: { - type: 'textbox', - maxWidth: 50 - }, - items: [ - {label: 'Width', name: 'width'}, - {label: 'Height', name: 'height'}, - { - label: 'Cell type', - name: 'type', - type: 'listbox', - text: 'None', - minWidth: 90, - maxWidth: null, - menu: [ - {text: 'Cell', value: 'td'}, - {text: 'Header cell', value: 'th'} - ] - }, - { - label: 'Scope', - name: 'scope', - type: 'listbox', - text: 'None', - minWidth: 90, - maxWidth: null, - menu: [ - {text: 'None', value: ''}, - {text: 'Row', value: 'row'}, - {text: 'Column', value: 'col'}, - {text: 'Row group', value: 'rowgroup'}, - {text: 'Column group', value: 'colgroup'} - ] - }, - { - label: 'Alignment', - name: 'align', - type: 'listbox', - text: 'None', - minWidth: 90, - maxWidth: null, - values: [ - {text: 'None', value: ''}, - {text: 'Left', value: 'left'}, - {text: 'Center', value: 'center'}, - {text: 'Right', value: 'right'} - ] - } - ] - }, - - onsubmit: function() { - var data = this.toJSON(); - - editor.undoManager.transact(function() { - each(cells, function(cellElm) { - editor.dom.setAttrib(cellElm, 'scope', data.scope); - - editor.dom.setStyles(cellElm, { - width: addSizeSuffix(data.width), - height: addSizeSuffix(data.height) - }); - - // Switch cell type - if (data.type && cellElm.nodeName.toLowerCase() != data.type) { - cellElm = dom.rename(cellElm, data.type); - } - - // Apply/remove alignment - if (data.align) { - editor.formatter.apply('align' + data.align, {}, cellElm); - } else { - each('left center right'.split(' '), function(name) { - editor.formatter.remove('align' + name, {}, cellElm); - }); - } - }); - - editor.focus(); - }); - } - }); - } - - function rowDialog() { - var dom = editor.dom, tableElm, cellElm, rowElm, data, rows = []; - - tableElm = editor.dom.getParent(editor.selection.getNode(), 'table'); - cellElm = editor.dom.getParent(editor.selection.getNode(), 'td,th'); - - each(tableElm.rows, function(row) { - each(row.cells, function(cell) { - if (dom.hasClass(cell, 'mce-item-selected') || cell == cellElm) { - rows.push(row); - return false; - } - }); - }); - - rowElm = rows[0]; - - data = { - height: removePxSuffix(dom.getStyle(rowElm, 'height') || dom.getAttrib(rowElm, 'height')), - scope: dom.getAttrib(rowElm, 'scope') - }; - - data.type = rowElm.parentNode.nodeName.toLowerCase(); - - each('left center right'.split(' '), function(name) { - if (editor.formatter.matchNode(rowElm, 'align' + name)) { - data.align = name; - } - }); - - editor.windowManager.open({ - title: "Row properties", - items: { - type: 'form', - data: data, - columns: 2, - defaults: { - type: 'textbox' - }, - items: [ - { - type: 'listbox', - name: 'type', - label: 'Row type', - text: 'None', - maxWidth: null, - menu: [ - {text: 'header', value: 'thead'}, - {text: 'body', value: 'tbody'}, - {text: 'footer', value: 'tfoot'} - ] - }, - { - type: 'listbox', - name: 'align', - label: 'Alignment', - text: 'None', - maxWidth: null, - menu: [ - {text: 'None', value: ''}, - {text: 'Left', value: 'left'}, - {text: 'Center', value: 'center'}, - {text: 'Right', value: 'right'} - ] - }, - {label: 'Height', name: 'height'} - ] - }, - - onsubmit: function() { - var data = this.toJSON(), tableElm, oldParentElm, parentElm; - - editor.undoManager.transact(function() { - each(rows, function(rowElm) { - editor.dom.setAttrib(rowElm, 'scope', data.scope); - - editor.dom.setStyles(rowElm, { - height: addSizeSuffix(data.height) - }); - - if (data.type != rowElm.parentNode.nodeName.toLowerCase()) { - tableElm = dom.getParent(rowElm, 'table'); - - oldParentElm = rowElm.parentNode; - parentElm = dom.select(tableElm, data.type)[0]; - if (!parentElm) { - parentElm = dom.create(data.type); - if (tableElm.firstChild) { - tableElm.insertBefore(parentElm, tableElm.firstChild); - } else { - tableElm.appendChild(parentElm); - } - } - - parentElm.insertBefore(rowElm, parentElm.firstChild); - - if (!oldParentElm.hasChildNodes()) { - dom.remove(oldParentElm); - } - } - - // Apply/remove alignment - if (data.align) { - editor.formatter.apply('align' + data.align, {}, rowElm); - } else { - each('left center right'.split(' '), function(name) { - editor.formatter.remove('align' + name, {}, rowElm); - }); - } - }); - - editor.focus(); - }); - } - }); - } - - function cmd(command) { - return function() { - editor.execCommand(command); - }; - } - - function insertTable(cols, rows) { - var y, x, html; - - html = ''; - - for (y = 0; y < rows; y++) { - html += '
'; - - editor.insertContent(html); - } - - function postRender() { - /*jshint validthis:true*/ - var self = this; - - function bindStateListener() { - self.disabled(!editor.dom.getParent(editor.selection.getNode(), 'table')); - - editor.selection.selectorChanged('table', function(state) { - self.disabled(!state); - }); - } - - if (editor.initialized) { - bindStateListener(); - } else { - editor.on('init', bindStateListener); - } - } - - // Register buttons - each([ - ['table', 'Insert/edit table', 'mceInsertTable'], - ['delete_table', 'Delete table', 'mceTableDelete'], - ['delete_col', 'Delete column', 'mceTableDeleteCol'], - ['delete_row', 'Delete row', 'mceTableDeleteRow'], - ['col_after', 'Insert column after', 'mceTableInsertColAfter'], - ['col_before', 'Insert column before', 'mceTableInsertColBefore'], - ['row_after', 'Insert row after', 'mceTableInsertRowAfter'], - ['row_before', 'Insert row before', 'mceTableInsertRowBefore'], - ['row_props', 'Row properties', 'mceTableRowProps'], - ['cell_props', 'Cell properties', 'mceTableCellProps'], - ['split_cells', 'Split cells', 'mceTableSplitCells'], - ['merge_cells', 'Merge cells', 'mceTableMergeCells'] - ], function(c) { - editor.addButton(c[0], { - title : c[1], - cmd : c[2], - onPostRender: postRender - }); - }); - - function generateTableGrid() { - var html = ''; - - html = ''; - - for (x = 0; x < cols; x++) { - html += ' '; - } - - html += '' + (Env.ie ? " " : ' '; - } - - html += '
') + ''; - - for (var y = 0; y < 10; y++) { - html += '
'; - - html += ''; - - for (var x = 0; x < 10; x++) { - html += ' '; - } - - html += ''; - } - - html += ' 0 x 0'; - - return html; - } - - editor.addMenuItem('inserttable', { - text: 'Insert table', - icon: 'table', - context: 'table', - onhide: function() { - editor.dom.removeClass(this.menu.items()[0].getEl().getElementsByTagName('a'), 'mce-active'); - }, - menu: [ - { - type: 'container', - html: generateTableGrid(), - - onmousemove: function(e) { - var target = e.target; - - if (target.nodeName == 'A') { - var table = editor.dom.getParent(target, 'table'); - var pos = target.getAttribute('data-mce-index'); - - if (pos != this.lastPos) { - pos = pos.split(','); - - pos[0] = parseInt(pos[0], 10); - pos[1] = parseInt(pos[1], 10); - - for (var y = 0; y < 10; y++) { - for (var x = 0; x < 10; x++) { - editor.dom.toggleClass( - table.rows[y].childNodes[x].firstChild, - 'mce-active', - x <= pos[0] && y <= pos[1] - ); - } - } - - table.nextSibling.innerHTML = (pos[0] + 1) + ' x '+ (pos[1] + 1); - this.lastPos = pos; - } - } - }, - - onclick: function(e) { - if (e.target.nodeName == 'A' && this.lastPos) { - e.preventDefault(); - - insertTable(this.lastPos[0] + 1, this.lastPos[1] + 1); - - // TODO: Maybe rework this? - this.parent().cancel(); // Close parent menu as if it was a click - } - } - } - ] - }); - - editor.addMenuItem('tableprops', { - text: 'Table properties', - context: 'table', - onPostRender: postRender, - onclick: tableDialog - }); - - editor.addMenuItem('deletetable', { - text: 'Delete table', - context: 'table', - onPostRender: postRender, - cmd: 'mceTableDelete' - }); - - editor.addMenuItem('cell', { - separator: 'before', - text: 'Cell', - context: 'table', - menu: [ - {text: 'Cell properties', onclick: cmd('mceTableCellProps'), onPostRender: postRender}, - {text: 'Merge cells', onclick: cmd('mceTableMergeCells'), onPostRender: postRender}, - {text: 'Split cell', onclick: cmd('mceTableSplitCells'), onPostRender: postRender} - ] - }); - - editor.addMenuItem('row', { - text: 'Row', - context: 'table', - menu: [ - {text: 'Insert row before', onclick: cmd('mceTableInsertRowBefore'), onPostRender: postRender}, - {text: 'Insert row after', onclick: cmd('mceTableInsertRowAfter'), onPostRender: postRender}, - {text: 'Delete row', onclick: cmd('mceTableDeleteRow'), onPostRender: postRender}, - {text: 'Row properties', onclick: cmd('mceTableRowProps'), onPostRender: postRender}, - {text: '-'}, - {text: 'Cut row', onclick: cmd('mceTableCutRow'), onPostRender: postRender}, - {text: 'Copy row', onclick: cmd('mceTableCopyRow'), onPostRender: postRender}, - {text: 'Paste row before', onclick: cmd('mceTablePasteRowBefore'), onPostRender: postRender}, - {text: 'Paste row after', onclick: cmd('mceTablePasteRowAfter'), onPostRender: postRender} - ] - }); - - editor.addMenuItem('column', { - text: 'Column', - context: 'table', - menu: [ - {text: 'Insert column before', onclick: cmd('mceTableInsertColBefore'), onPostRender: postRender}, - {text: 'Insert column after', onclick: cmd('mceTableInsertColAfter'), onPostRender: postRender}, - {text: 'Delete column', onclick: cmd('mceTableDeleteCol'), onPostRender: postRender} - ] - }); - - // Select whole table is a table border is clicked - if (!Env.isIE) { - editor.on('click', function(e) { - e = e.target; - - if (e.nodeName === 'TABLE') { - editor.selection.select(e); - editor.nodeChanged(); - } - }); - } - - self.quirks = new Quirks(editor); - - editor.on('Init', function() { - winMan = editor.windowManager; - self.cellSelection = new CellSelection(editor); - }); - - // Register action commands - each({ - mceTableSplitCells: function(grid) { - grid.split(); - }, - - mceTableMergeCells: function(grid) { - var rowSpan, colSpan, cell; - - cell = editor.dom.getParent(editor.selection.getNode(), 'th,td'); - if (cell) { - rowSpan = cell.rowSpan; - colSpan = cell.colSpan; - } - - if (!editor.dom.select('td.mce-item-selected,th.mce-item-selected').length) { - mergeDialog(grid, cell); - } else { - grid.merge(); - } - }, - - mceTableInsertRowBefore: function(grid) { - grid.insertRow(true); - }, - - mceTableInsertRowAfter: function(grid) { - grid.insertRow(); - }, - - mceTableInsertColBefore: function(grid) { - grid.insertCol(true); - }, - - mceTableInsertColAfter: function(grid) { - grid.insertCol(); - }, - - mceTableDeleteCol: function(grid) { - grid.deleteCols(); - }, - - mceTableDeleteRow: function(grid) { - grid.deleteRows(); - }, - - mceTableCutRow: function(grid) { - clipboardRows = grid.cutRows(); - }, - - mceTableCopyRow: function(grid) { - clipboardRows = grid.copyRows(); - }, - - mceTablePasteRowBefore: function(grid) { - grid.pasteRows(clipboardRows, true); - }, - - mceTablePasteRowAfter: function(grid) { - grid.pasteRows(clipboardRows); - }, - - mceTableDelete: function(grid) { - grid.deleteTable(); - } - }, function(func, name) { - editor.addCommand(name, function() { - var grid = new TableGrid(editor.selection); - - if (grid) { - func(grid); - editor.execCommand('mceRepaint'); - self.cellSelection.clear(); - } - }); - }); - - // Register dialog commands - each({ - mceInsertTable: function() { - tableDialog(); - }, - - mceTableRowProps: rowDialog, - mceTableCellProps: cellDialog - }, function(func, name) { - editor.addCommand(name, function(ui, val) { - func(val); - }); - }); - } - - PluginManager.add('table', Plugin); -}); - -expose(["tinymce/tableplugin/TableGrid","tinymce/tableplugin/Quirks","tinymce/tableplugin/CellSelection","tinymce/tableplugin/Plugin"]); -})(this); \ No newline at end of file +(function (domGlobals) { + 'use strict'; + + var Cell = function (initial) { + var value = initial; + var get = function () { + return value; + }; + var set = function (v) { + value = v; + }; + var clone = function () { + return Cell(get()); + }; + return { + get: get, + set: set, + clone: clone + }; + }; + + var noop = function () { + }; + var compose = function (fa, fb) { + return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + return fa(fb.apply(null, args)); + }; + }; + var constant = function (value) { + return function () { + return value; + }; + }; + var identity = function (x) { + return x; + }; + function curry(fn) { + var initialArgs = []; + for (var _i = 1; _i < arguments.length; _i++) { + initialArgs[_i - 1] = arguments[_i]; + } + return function () { + var restArgs = []; + for (var _i = 0; _i < arguments.length; _i++) { + restArgs[_i] = arguments[_i]; + } + var all = initialArgs.concat(restArgs); + return fn.apply(null, all); + }; + } + var not = function (f) { + return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + return !f.apply(null, args); + }; + }; + var die = function (msg) { + return function () { + throw new Error(msg); + }; + }; + var never = constant(false); + var always = constant(true); + + var none = function () { + return NONE; + }; + var NONE = function () { + var eq = function (o) { + return o.isNone(); + }; + var call = function (thunk) { + return thunk(); + }; + var id = function (n) { + return n; + }; + var me = { + fold: function (n, s) { + return n(); + }, + is: never, + isSome: never, + isNone: always, + getOr: id, + getOrThunk: call, + getOrDie: function (msg) { + throw new Error(msg || 'error: getOrDie called on none.'); + }, + getOrNull: constant(null), + getOrUndefined: constant(undefined), + or: id, + orThunk: call, + map: none, + each: noop, + bind: none, + exists: never, + forall: always, + filter: none, + equals: eq, + equals_: eq, + toArray: function () { + return []; + }, + toString: constant('none()') + }; + if (Object.freeze) { + Object.freeze(me); + } + return me; + }(); + var some = function (a) { + var constant_a = constant(a); + var self = function () { + return me; + }; + var bind = function (f) { + return f(a); + }; + var me = { + fold: function (n, s) { + return s(a); + }, + is: function (v) { + return a === v; + }, + isSome: always, + isNone: never, + getOr: constant_a, + getOrThunk: constant_a, + getOrDie: constant_a, + getOrNull: constant_a, + getOrUndefined: constant_a, + or: self, + orThunk: self, + map: function (f) { + return some(f(a)); + }, + each: function (f) { + f(a); + }, + bind: bind, + exists: bind, + forall: bind, + filter: function (f) { + return f(a) ? me : NONE; + }, + toArray: function () { + return [a]; + }, + toString: function () { + return 'some(' + a + ')'; + }, + equals: function (o) { + return o.is(a); + }, + equals_: function (o, elementEq) { + return o.fold(never, function (b) { + return elementEq(a, b); + }); + } + }; + return me; + }; + var from = function (value) { + return value === null || value === undefined ? NONE : some(value); + }; + var Option = { + some: some, + none: none, + from: from + }; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var typeOf = function (x) { + if (x === null) { + return 'null'; + } + var t = typeof x; + if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) { + return 'array'; + } + if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) { + return 'string'; + } + return t; + }; + var isType = function (type) { + return function (value) { + return typeOf(value) === type; + }; + }; + var isString = isType('string'); + var isArray = isType('array'); + var isBoolean = isType('boolean'); + var isFunction = isType('function'); + var isNumber = isType('number'); + + var nativeSlice = Array.prototype.slice; + var nativeIndexOf = Array.prototype.indexOf; + var nativePush = Array.prototype.push; + var rawIndexOf = function (ts, t) { + return nativeIndexOf.call(ts, t); + }; + var contains = function (xs, x) { + return rawIndexOf(xs, x) > -1; + }; + var exists = function (xs, pred) { + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + if (pred(x, i)) { + return true; + } + } + return false; + }; + var map = function (xs, f) { + var len = xs.length; + var r = new Array(len); + for (var i = 0; i < len; i++) { + var x = xs[i]; + r[i] = f(x, i); + } + return r; + }; + var each = function (xs, f) { + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + f(x, i); + } + }; + var eachr = function (xs, f) { + for (var i = xs.length - 1; i >= 0; i--) { + var x = xs[i]; + f(x, i); + } + }; + var filter = function (xs, pred) { + var r = []; + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + if (pred(x, i)) { + r.push(x); + } + } + return r; + }; + var foldr = function (xs, f, acc) { + eachr(xs, function (x) { + acc = f(acc, x); + }); + return acc; + }; + var foldl = function (xs, f, acc) { + each(xs, function (x) { + acc = f(acc, x); + }); + return acc; + }; + var find = function (xs, pred) { + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + if (pred(x, i)) { + return Option.some(x); + } + } + return Option.none(); + }; + var findIndex = function (xs, pred) { + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + if (pred(x, i)) { + return Option.some(i); + } + } + return Option.none(); + }; + var flatten = function (xs) { + var r = []; + for (var i = 0, len = xs.length; i < len; ++i) { + if (!isArray(xs[i])) { + throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs); + } + nativePush.apply(r, xs[i]); + } + return r; + }; + var bind = function (xs, f) { + var output = map(xs, f); + return flatten(output); + }; + var forall = function (xs, pred) { + for (var i = 0, len = xs.length; i < len; ++i) { + var x = xs[i]; + if (pred(x, i) !== true) { + return false; + } + } + return true; + }; + var reverse = function (xs) { + var r = nativeSlice.call(xs, 0); + r.reverse(); + return r; + }; + var last = function (xs) { + return xs.length === 0 ? Option.none() : Option.some(xs[xs.length - 1]); + }; + var from$1 = isFunction(Array.from) ? Array.from : function (x) { + return nativeSlice.call(x); + }; + + var keys = Object.keys; + var hasOwnProperty = Object.hasOwnProperty; + var each$1 = function (obj, f) { + var props = keys(obj); + for (var k = 0, len = props.length; k < len; k++) { + var i = props[k]; + var x = obj[i]; + f(x, i); + } + }; + var map$1 = function (obj, f) { + return tupleMap(obj, function (x, i) { + return { + k: i, + v: f(x, i) + }; + }); + }; + var tupleMap = function (obj, f) { + var r = {}; + each$1(obj, function (x, i) { + var tuple = f(x, i); + r[tuple.k] = tuple.v; + }); + return r; + }; + var get = function (obj, key) { + return has(obj, key) ? Option.from(obj[key]) : Option.none(); + }; + var has = function (obj, key) { + return hasOwnProperty.call(obj, key); + }; + + var Immutable = function () { + var fields = []; + for (var _i = 0; _i < arguments.length; _i++) { + fields[_i] = arguments[_i]; + } + return function () { + var values = []; + for (var _i = 0; _i < arguments.length; _i++) { + values[_i] = arguments[_i]; + } + if (fields.length !== values.length) { + throw new Error('Wrong number of arguments to struct. Expected "[' + fields.length + ']", got ' + values.length + ' arguments'); + } + var struct = {}; + each(fields, function (name, i) { + struct[name] = constant(values[i]); + }); + return struct; + }; + }; + + var sort = function (arr) { + return arr.slice(0).sort(); + }; + var reqMessage = function (required, keys) { + throw new Error('All required keys (' + sort(required).join(', ') + ') were not specified. Specified keys were: ' + sort(keys).join(', ') + '.'); + }; + var unsuppMessage = function (unsupported) { + throw new Error('Unsupported keys for object: ' + sort(unsupported).join(', ')); + }; + var validateStrArr = function (label, array) { + if (!isArray(array)) { + throw new Error('The ' + label + ' fields must be an array. Was: ' + array + '.'); + } + each(array, function (a) { + if (!isString(a)) { + throw new Error('The value ' + a + ' in the ' + label + ' fields was not a string.'); + } + }); + }; + var invalidTypeMessage = function (incorrect, type) { + throw new Error('All values need to be of type: ' + type + '. Keys (' + sort(incorrect).join(', ') + ') were not.'); + }; + var checkDupes = function (everything) { + var sorted = sort(everything); + var dupe = find(sorted, function (s, i) { + return i < sorted.length - 1 && s === sorted[i + 1]; + }); + dupe.each(function (d) { + throw new Error('The field: ' + d + ' occurs more than once in the combined fields: [' + sorted.join(', ') + '].'); + }); + }; + + var MixedBag = function (required, optional) { + var everything = required.concat(optional); + if (everything.length === 0) { + throw new Error('You must specify at least one required or optional field.'); + } + validateStrArr('required', required); + validateStrArr('optional', optional); + checkDupes(everything); + return function (obj) { + var keys$1 = keys(obj); + var allReqd = forall(required, function (req) { + return contains(keys$1, req); + }); + if (!allReqd) { + reqMessage(required, keys$1); + } + var unsupported = filter(keys$1, function (key) { + return !contains(everything, key); + }); + if (unsupported.length > 0) { + unsuppMessage(unsupported); + } + var r = {}; + each(required, function (req) { + r[req] = constant(obj[req]); + }); + each(optional, function (opt) { + r[opt] = constant(Object.prototype.hasOwnProperty.call(obj, opt) ? Option.some(obj[opt]) : Option.none()); + }); + return r; + }; + }; + + var ATTRIBUTE = domGlobals.Node.ATTRIBUTE_NODE; + var CDATA_SECTION = domGlobals.Node.CDATA_SECTION_NODE; + var COMMENT = domGlobals.Node.COMMENT_NODE; + var DOCUMENT = domGlobals.Node.DOCUMENT_NODE; + var DOCUMENT_TYPE = domGlobals.Node.DOCUMENT_TYPE_NODE; + var DOCUMENT_FRAGMENT = domGlobals.Node.DOCUMENT_FRAGMENT_NODE; + var ELEMENT = domGlobals.Node.ELEMENT_NODE; + var TEXT = domGlobals.Node.TEXT_NODE; + var PROCESSING_INSTRUCTION = domGlobals.Node.PROCESSING_INSTRUCTION_NODE; + var ENTITY_REFERENCE = domGlobals.Node.ENTITY_REFERENCE_NODE; + var ENTITY = domGlobals.Node.ENTITY_NODE; + var NOTATION = domGlobals.Node.NOTATION_NODE; + + var Global = typeof domGlobals.window !== 'undefined' ? domGlobals.window : Function('return this;')(); + + var name = function (element) { + var r = element.dom().nodeName; + return r.toLowerCase(); + }; + var type = function (element) { + return element.dom().nodeType; + }; + var isType$1 = function (t) { + return function (element) { + return type(element) === t; + }; + }; + var isComment = function (element) { + return type(element) === COMMENT || name(element) === '#comment'; + }; + var isElement = isType$1(ELEMENT); + var isText = isType$1(TEXT); + + var rawSet = function (dom, key, value) { + if (isString(value) || isBoolean(value) || isNumber(value)) { + dom.setAttribute(key, value + ''); + } else { + domGlobals.console.error('Invalid call to Attr.set. Key ', key, ':: Value ', value, ':: Element ', dom); + throw new Error('Attribute value was not simple'); + } + }; + var set = function (element, key, value) { + rawSet(element.dom(), key, value); + }; + var setAll = function (element, attrs) { + var dom = element.dom(); + each$1(attrs, function (v, k) { + rawSet(dom, k, v); + }); + }; + var get$1 = function (element, key) { + var v = element.dom().getAttribute(key); + return v === null ? undefined : v; + }; + var has$1 = function (element, key) { + var dom = element.dom(); + return dom && dom.hasAttribute ? dom.hasAttribute(key) : false; + }; + var remove = function (element, key) { + element.dom().removeAttribute(key); + }; + var clone = function (element) { + return foldl(element.dom().attributes, function (acc, attr) { + acc[attr.name] = attr.value; + return acc; + }, {}); + }; + + var checkRange = function (str, substr, start) { + if (substr === '') { + return true; + } + if (str.length < substr.length) { + return false; + } + var x = str.substr(start, start + substr.length); + return x === substr; + }; + var contains$1 = function (str, substr) { + return str.indexOf(substr) !== -1; + }; + var startsWith = function (str, prefix) { + return checkRange(str, prefix, 0); + }; + var endsWith = function (str, suffix) { + return checkRange(str, suffix, str.length - suffix.length); + }; + var trim = function (str) { + return str.replace(/^\s+|\s+$/g, ''); + }; + + var isSupported = function (dom) { + return dom.style !== undefined && isFunction(dom.style.getPropertyValue); + }; + + var cached = function (f) { + var called = false; + var r; + return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + if (!called) { + called = true; + r = f.apply(null, args); + } + return r; + }; + }; + + var fromHtml = function (html, scope) { + var doc = scope || domGlobals.document; + var div = doc.createElement('div'); + div.innerHTML = html; + if (!div.hasChildNodes() || div.childNodes.length > 1) { + domGlobals.console.error('HTML does not have a single root node', html); + throw new Error('HTML must have a single root node'); + } + return fromDom(div.childNodes[0]); + }; + var fromTag = function (tag, scope) { + var doc = scope || domGlobals.document; + var node = doc.createElement(tag); + return fromDom(node); + }; + var fromText = function (text, scope) { + var doc = scope || domGlobals.document; + var node = doc.createTextNode(text); + return fromDom(node); + }; + var fromDom = function (node) { + if (node === null || node === undefined) { + throw new Error('Node cannot be null or undefined'); + } + return { dom: constant(node) }; + }; + var fromPoint = function (docElm, x, y) { + var doc = docElm.dom(); + return Option.from(doc.elementFromPoint(x, y)).map(fromDom); + }; + var Element = { + fromHtml: fromHtml, + fromTag: fromTag, + fromText: fromText, + fromDom: fromDom, + fromPoint: fromPoint + }; + + var inBody = function (element) { + var dom = isText(element) ? element.dom().parentNode : element.dom(); + return dom !== undefined && dom !== null && dom.ownerDocument.body.contains(dom); + }; + var body = cached(function () { + return getBody(Element.fromDom(domGlobals.document)); + }); + var getBody = function (doc) { + var b = doc.dom().body; + if (b === null || b === undefined) { + throw new Error('Body is not available yet'); + } + return Element.fromDom(b); + }; + + var internalSet = function (dom, property, value) { + if (!isString(value)) { + domGlobals.console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom); + throw new Error('CSS value must be a string: ' + value); + } + if (isSupported(dom)) { + dom.style.setProperty(property, value); + } + }; + var internalRemove = function (dom, property) { + if (isSupported(dom)) { + dom.style.removeProperty(property); + } + }; + var set$1 = function (element, property, value) { + var dom = element.dom(); + internalSet(dom, property, value); + }; + var setAll$1 = function (element, css) { + var dom = element.dom(); + each$1(css, function (v, k) { + internalSet(dom, k, v); + }); + }; + var get$2 = function (element, property) { + var dom = element.dom(); + var styles = domGlobals.window.getComputedStyle(dom); + var r = styles.getPropertyValue(property); + var v = r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r; + return v === null ? undefined : v; + }; + var getUnsafeProperty = function (dom, property) { + return isSupported(dom) ? dom.style.getPropertyValue(property) : ''; + }; + var getRaw = function (element, property) { + var dom = element.dom(); + var raw = getUnsafeProperty(dom, property); + return Option.from(raw).filter(function (r) { + return r.length > 0; + }); + }; + var remove$1 = function (element, property) { + var dom = element.dom(); + internalRemove(dom, property); + if (has$1(element, 'style') && trim(get$1(element, 'style')) === '') { + remove(element, 'style'); + } + }; + var copy = function (source, target) { + var sourceDom = source.dom(); + var targetDom = target.dom(); + if (isSupported(sourceDom) && isSupported(targetDom)) { + targetDom.style.cssText = sourceDom.style.cssText; + } + }; + + var compareDocumentPosition = function (a, b, match) { + return (a.compareDocumentPosition(b) & match) !== 0; + }; + var documentPositionPreceding = function (a, b) { + return compareDocumentPosition(a, b, domGlobals.Node.DOCUMENT_POSITION_PRECEDING); + }; + var documentPositionContainedBy = function (a, b) { + return compareDocumentPosition(a, b, domGlobals.Node.DOCUMENT_POSITION_CONTAINED_BY); + }; + var Node = { + documentPositionPreceding: documentPositionPreceding, + documentPositionContainedBy: documentPositionContainedBy + }; + + var __assign = function () { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) + if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + var firstMatch = function (regexes, s) { + for (var i = 0; i < regexes.length; i++) { + var x = regexes[i]; + if (x.test(s)) { + return x; + } + } + return undefined; + }; + var find$1 = function (regexes, agent) { + var r = firstMatch(regexes, agent); + if (!r) { + return { + major: 0, + minor: 0 + }; + } + var group = function (i) { + return Number(agent.replace(r, '$' + i)); + }; + return nu(group(1), group(2)); + }; + var detect = function (versionRegexes, agent) { + var cleanedAgent = String(agent).toLowerCase(); + if (versionRegexes.length === 0) { + return unknown(); + } + return find$1(versionRegexes, cleanedAgent); + }; + var unknown = function () { + return nu(0, 0); + }; + var nu = function (major, minor) { + return { + major: major, + minor: minor + }; + }; + var Version = { + nu: nu, + detect: detect, + unknown: unknown + }; + + var edge = 'Edge'; + var chrome = 'Chrome'; + var ie = 'IE'; + var opera = 'Opera'; + var firefox = 'Firefox'; + var safari = 'Safari'; + var isBrowser = function (name, current) { + return function () { + return current === name; + }; + }; + var unknown$1 = function () { + return nu$1({ + current: undefined, + version: Version.unknown() + }); + }; + var nu$1 = function (info) { + var current = info.current; + var version = info.version; + return { + current: current, + version: version, + isEdge: isBrowser(edge, current), + isChrome: isBrowser(chrome, current), + isIE: isBrowser(ie, current), + isOpera: isBrowser(opera, current), + isFirefox: isBrowser(firefox, current), + isSafari: isBrowser(safari, current) + }; + }; + var Browser = { + unknown: unknown$1, + nu: nu$1, + edge: constant(edge), + chrome: constant(chrome), + ie: constant(ie), + opera: constant(opera), + firefox: constant(firefox), + safari: constant(safari) + }; + + var windows = 'Windows'; + var ios = 'iOS'; + var android = 'Android'; + var linux = 'Linux'; + var osx = 'OSX'; + var solaris = 'Solaris'; + var freebsd = 'FreeBSD'; + var chromeos = 'ChromeOS'; + var isOS = function (name, current) { + return function () { + return current === name; + }; + }; + var unknown$2 = function () { + return nu$2({ + current: undefined, + version: Version.unknown() + }); + }; + var nu$2 = function (info) { + var current = info.current; + var version = info.version; + return { + current: current, + version: version, + isWindows: isOS(windows, current), + isiOS: isOS(ios, current), + isAndroid: isOS(android, current), + isOSX: isOS(osx, current), + isLinux: isOS(linux, current), + isSolaris: isOS(solaris, current), + isFreeBSD: isOS(freebsd, current), + isChromeOS: isOS(chromeos, current) + }; + }; + var OperatingSystem = { + unknown: unknown$2, + nu: nu$2, + windows: constant(windows), + ios: constant(ios), + android: constant(android), + linux: constant(linux), + osx: constant(osx), + solaris: constant(solaris), + freebsd: constant(freebsd), + chromeos: constant(chromeos) + }; + + var DeviceType = function (os, browser, userAgent, mediaMatch) { + var isiPad = os.isiOS() && /ipad/i.test(userAgent) === true; + var isiPhone = os.isiOS() && !isiPad; + var isMobile = os.isiOS() || os.isAndroid(); + var isTouch = isMobile || mediaMatch('(pointer:coarse)'); + var isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)'); + var isPhone = isiPhone || isMobile && !isTablet; + var iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false; + var isDesktop = !isPhone && !isTablet && !iOSwebview; + return { + isiPad: constant(isiPad), + isiPhone: constant(isiPhone), + isTablet: constant(isTablet), + isPhone: constant(isPhone), + isTouch: constant(isTouch), + isAndroid: os.isAndroid, + isiOS: os.isiOS, + isWebView: constant(iOSwebview), + isDesktop: constant(isDesktop) + }; + }; + + var detect$1 = function (candidates, userAgent) { + var agent = String(userAgent).toLowerCase(); + return find(candidates, function (candidate) { + return candidate.search(agent); + }); + }; + var detectBrowser = function (browsers, userAgent) { + return detect$1(browsers, userAgent).map(function (browser) { + var version = Version.detect(browser.versionRegexes, userAgent); + return { + current: browser.name, + version: version + }; + }); + }; + var detectOs = function (oses, userAgent) { + return detect$1(oses, userAgent).map(function (os) { + var version = Version.detect(os.versionRegexes, userAgent); + return { + current: os.name, + version: version + }; + }); + }; + var UaString = { + detectBrowser: detectBrowser, + detectOs: detectOs + }; + + var normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/; + var checkContains = function (target) { + return function (uastring) { + return contains$1(uastring, target); + }; + }; + var browsers = [ + { + name: 'Edge', + versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/], + search: function (uastring) { + return contains$1(uastring, 'edge/') && contains$1(uastring, 'chrome') && contains$1(uastring, 'safari') && contains$1(uastring, 'applewebkit'); + } + }, + { + name: 'Chrome', + versionRegexes: [ + /.*?chrome\/([0-9]+)\.([0-9]+).*/, + normalVersionRegex + ], + search: function (uastring) { + return contains$1(uastring, 'chrome') && !contains$1(uastring, 'chromeframe'); + } + }, + { + name: 'IE', + versionRegexes: [ + /.*?msie\ ?([0-9]+)\.([0-9]+).*/, + /.*?rv:([0-9]+)\.([0-9]+).*/ + ], + search: function (uastring) { + return contains$1(uastring, 'msie') || contains$1(uastring, 'trident'); + } + }, + { + name: 'Opera', + versionRegexes: [ + normalVersionRegex, + /.*?opera\/([0-9]+)\.([0-9]+).*/ + ], + search: checkContains('opera') + }, + { + name: 'Firefox', + versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/], + search: checkContains('firefox') + }, + { + name: 'Safari', + versionRegexes: [ + normalVersionRegex, + /.*?cpu os ([0-9]+)_([0-9]+).*/ + ], + search: function (uastring) { + return (contains$1(uastring, 'safari') || contains$1(uastring, 'mobile/')) && contains$1(uastring, 'applewebkit'); + } + } + ]; + var oses = [ + { + name: 'Windows', + search: checkContains('win'), + versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/] + }, + { + name: 'iOS', + search: function (uastring) { + return contains$1(uastring, 'iphone') || contains$1(uastring, 'ipad'); + }, + versionRegexes: [ + /.*?version\/\ ?([0-9]+)\.([0-9]+).*/, + /.*cpu os ([0-9]+)_([0-9]+).*/, + /.*cpu iphone os ([0-9]+)_([0-9]+).*/ + ] + }, + { + name: 'Android', + search: checkContains('android'), + versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/] + }, + { + name: 'OSX', + search: checkContains('mac os x'), + versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/] + }, + { + name: 'Linux', + search: checkContains('linux'), + versionRegexes: [] + }, + { + name: 'Solaris', + search: checkContains('sunos'), + versionRegexes: [] + }, + { + name: 'FreeBSD', + search: checkContains('freebsd'), + versionRegexes: [] + }, + { + name: 'ChromeOS', + search: checkContains('cros'), + versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/] + } + ]; + var PlatformInfo = { + browsers: constant(browsers), + oses: constant(oses) + }; + + var detect$2 = function (userAgent, mediaMatch) { + var browsers = PlatformInfo.browsers(); + var oses = PlatformInfo.oses(); + var browser = UaString.detectBrowser(browsers, userAgent).fold(Browser.unknown, Browser.nu); + var os = UaString.detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu); + var deviceType = DeviceType(os, browser, userAgent, mediaMatch); + return { + browser: browser, + os: os, + deviceType: deviceType + }; + }; + var PlatformDetection = { detect: detect$2 }; + + var mediaMatch = function (query) { + return domGlobals.window.matchMedia(query).matches; + }; + var platform = Cell(PlatformDetection.detect(domGlobals.navigator.userAgent, mediaMatch)); + var detect$3 = function () { + return platform.get(); + }; + + var ELEMENT$1 = ELEMENT; + var DOCUMENT$1 = DOCUMENT; + var is = function (element, selector) { + var dom = element.dom(); + if (dom.nodeType !== ELEMENT$1) { + return false; + } else { + var elem = dom; + if (elem.matches !== undefined) { + return elem.matches(selector); + } else if (elem.msMatchesSelector !== undefined) { + return elem.msMatchesSelector(selector); + } else if (elem.webkitMatchesSelector !== undefined) { + return elem.webkitMatchesSelector(selector); + } else if (elem.mozMatchesSelector !== undefined) { + return elem.mozMatchesSelector(selector); + } else { + throw new Error('Browser lacks native selectors'); + } + } + }; + var bypassSelector = function (dom) { + return dom.nodeType !== ELEMENT$1 && dom.nodeType !== DOCUMENT$1 || dom.childElementCount === 0; + }; + var all = function (selector, scope) { + var base = scope === undefined ? domGlobals.document : scope.dom(); + return bypassSelector(base) ? [] : map(base.querySelectorAll(selector), Element.fromDom); + }; + var one = function (selector, scope) { + var base = scope === undefined ? domGlobals.document : scope.dom(); + return bypassSelector(base) ? Option.none() : Option.from(base.querySelector(selector)).map(Element.fromDom); + }; + + var eq = function (e1, e2) { + return e1.dom() === e2.dom(); + }; + var regularContains = function (e1, e2) { + var d1 = e1.dom(); + var d2 = e2.dom(); + return d1 === d2 ? false : d1.contains(d2); + }; + var ieContains = function (e1, e2) { + return Node.documentPositionContainedBy(e1.dom(), e2.dom()); + }; + var browser = detect$3().browser; + var contains$2 = browser.isIE() ? ieContains : regularContains; + var is$1 = is; + + var owner = function (element) { + return Element.fromDom(element.dom().ownerDocument); + }; + var defaultView = function (element) { + return Element.fromDom(element.dom().ownerDocument.defaultView); + }; + var parent = function (element) { + return Option.from(element.dom().parentNode).map(Element.fromDom); + }; + var parents = function (element, isRoot) { + var stop = isFunction(isRoot) ? isRoot : never; + var dom = element.dom(); + var ret = []; + while (dom.parentNode !== null && dom.parentNode !== undefined) { + var rawParent = dom.parentNode; + var p = Element.fromDom(rawParent); + ret.push(p); + if (stop(p) === true) { + break; + } else { + dom = rawParent; + } + } + return ret; + }; + var prevSibling = function (element) { + return Option.from(element.dom().previousSibling).map(Element.fromDom); + }; + var nextSibling = function (element) { + return Option.from(element.dom().nextSibling).map(Element.fromDom); + }; + var children = function (element) { + return map(element.dom().childNodes, Element.fromDom); + }; + var child = function (element, index) { + var cs = element.dom().childNodes; + return Option.from(cs[index]).map(Element.fromDom); + }; + var firstChild = function (element) { + return child(element, 0); + }; + var spot = Immutable('element', 'offset'); + + var before = function (marker, element) { + var parent$1 = parent(marker); + parent$1.each(function (v) { + v.dom().insertBefore(element.dom(), marker.dom()); + }); + }; + var after = function (marker, element) { + var sibling = nextSibling(marker); + sibling.fold(function () { + var parent$1 = parent(marker); + parent$1.each(function (v) { + append(v, element); + }); + }, function (v) { + before(v, element); + }); + }; + var prepend = function (parent, element) { + var firstChild$1 = firstChild(parent); + firstChild$1.fold(function () { + append(parent, element); + }, function (v) { + parent.dom().insertBefore(element.dom(), v.dom()); + }); + }; + var append = function (parent, element) { + parent.dom().appendChild(element.dom()); + }; + var wrap = function (element, wrapper) { + before(element, wrapper); + append(wrapper, element); + }; + + var before$1 = function (marker, elements) { + each(elements, function (x) { + before(marker, x); + }); + }; + var after$1 = function (marker, elements) { + each(elements, function (x, i) { + var e = i === 0 ? marker : elements[i - 1]; + after(e, x); + }); + }; + var append$1 = function (parent, elements) { + each(elements, function (x) { + append(parent, x); + }); + }; + + var empty = function (element) { + element.dom().textContent = ''; + each(children(element), function (rogue) { + remove$2(rogue); + }); + }; + var remove$2 = function (element) { + var dom = element.dom(); + if (dom.parentNode !== null) { + dom.parentNode.removeChild(dom); + } + }; + var unwrap = function (wrapper) { + var children$1 = children(wrapper); + if (children$1.length > 0) { + before$1(wrapper, children$1); + } + remove$2(wrapper); + }; + + var dimension = Immutable('width', 'height'); + var dimensions = Immutable('width', 'height'); + var grid = Immutable('rows', 'columns'); + var address = Immutable('row', 'column'); + var coords = Immutable('x', 'y'); + var detail = Immutable('element', 'rowspan', 'colspan'); + var detailnew = Immutable('element', 'rowspan', 'colspan', 'isNew'); + var extended = Immutable('element', 'rowspan', 'colspan', 'row', 'column'); + var rowdata = Immutable('element', 'cells', 'section'); + var elementnew = Immutable('element', 'isNew'); + var rowdatanew = Immutable('element', 'cells', 'section', 'isNew'); + var rowcells = Immutable('cells', 'section'); + var rowdetails = Immutable('details', 'section'); + var bounds = Immutable('startRow', 'startCol', 'finishRow', 'finishCol'); + + var ancestors = function (scope, predicate, isRoot) { + return filter(parents(scope, isRoot), predicate); + }; + var children$1 = function (scope, predicate) { + return filter(children(scope), predicate); + }; + var descendants = function (scope, predicate) { + var result = []; + each(children(scope), function (x) { + if (predicate(x)) { + result = result.concat([x]); + } + result = result.concat(descendants(x, predicate)); + }); + return result; + }; + + var ancestors$1 = function (scope, selector, isRoot) { + return ancestors(scope, function (e) { + return is(e, selector); + }, isRoot); + }; + var children$2 = function (scope, selector) { + return children$1(scope, function (e) { + return is(e, selector); + }); + }; + var descendants$1 = function (scope, selector) { + return all(selector, scope); + }; + + function ClosestOrAncestor (is, ancestor, scope, a, isRoot) { + return is(scope, a) ? Option.some(scope) : isFunction(isRoot) && isRoot(scope) ? Option.none() : ancestor(scope, a, isRoot); + } + + var ancestor = function (scope, predicate, isRoot) { + var element = scope.dom(); + var stop = isFunction(isRoot) ? isRoot : constant(false); + while (element.parentNode) { + element = element.parentNode; + var el = Element.fromDom(element); + if (predicate(el)) { + return Option.some(el); + } else if (stop(el)) { + break; + } + } + return Option.none(); + }; + var closest = function (scope, predicate, isRoot) { + var is = function (s, test) { + return test(s); + }; + return ClosestOrAncestor(is, ancestor, scope, predicate, isRoot); + }; + var child$1 = function (scope, predicate) { + var pred = function (node) { + return predicate(Element.fromDom(node)); + }; + var result = find(scope.dom().childNodes, pred); + return result.map(Element.fromDom); + }; + var descendant = function (scope, predicate) { + var descend = function (node) { + for (var i = 0; i < node.childNodes.length; i++) { + var child_1 = Element.fromDom(node.childNodes[i]); + if (predicate(child_1)) { + return Option.some(child_1); + } + var res = descend(node.childNodes[i]); + if (res.isSome()) { + return res; + } + } + return Option.none(); + }; + return descend(scope.dom()); + }; + + var ancestor$1 = function (scope, selector, isRoot) { + return ancestor(scope, function (e) { + return is(e, selector); + }, isRoot); + }; + var child$2 = function (scope, selector) { + return child$1(scope, function (e) { + return is(e, selector); + }); + }; + var descendant$1 = function (scope, selector) { + return one(selector, scope); + }; + var closest$1 = function (scope, selector, isRoot) { + return ClosestOrAncestor(is, ancestor$1, scope, selector, isRoot); + }; + + var firstLayer = function (scope, selector) { + return filterFirstLayer(scope, selector, constant(true)); + }; + var filterFirstLayer = function (scope, selector, predicate) { + return bind(children(scope), function (x) { + return is(x, selector) ? predicate(x) ? [x] : [] : filterFirstLayer(x, selector, predicate); + }); + }; + var LayerSelector = { + firstLayer: firstLayer, + filterFirstLayer: filterFirstLayer + }; + + var lookup = function (tags, element, isRoot) { + if (isRoot === void 0) { + isRoot = never; + } + if (isRoot(element)) { + return Option.none(); + } + if (contains(tags, name(element))) { + return Option.some(element); + } + var isRootOrUpperTable = function (elm) { + return is(elm, 'table') || isRoot(elm); + }; + return ancestor$1(element, tags.join(','), isRootOrUpperTable); + }; + var cell = function (element, isRoot) { + return lookup([ + 'td', + 'th' + ], element, isRoot); + }; + var cells = function (ancestor) { + return LayerSelector.firstLayer(ancestor, 'th,td'); + }; + var notCell = function (element, isRoot) { + return lookup([ + 'caption', + 'tr', + 'tbody', + 'tfoot', + 'thead' + ], element, isRoot); + }; + var neighbours = function (selector, element) { + return parent(element).map(function (parent) { + return children$2(parent, selector); + }); + }; + var neighbourCells = curry(neighbours, 'th,td'); + var neighbourRows = curry(neighbours, 'tr'); + var firstCell = function (ancestor) { + return descendant$1(ancestor, 'th,td'); + }; + var table = function (element, isRoot) { + return closest$1(element, 'table', isRoot); + }; + var row = function (element, isRoot) { + return lookup(['tr'], element, isRoot); + }; + var rows = function (ancestor) { + return LayerSelector.firstLayer(ancestor, 'tr'); + }; + var attr = function (element, property) { + return parseInt(get$1(element, property), 10); + }; + var grid$1 = function (element, rowProp, colProp) { + var rowsCount = attr(element, rowProp); + var cols = attr(element, colProp); + return grid(rowsCount, cols); + }; + var TableLookup = { + cell: cell, + firstCell: firstCell, + cells: cells, + neighbourCells: neighbourCells, + table: table, + row: row, + rows: rows, + notCell: notCell, + neighbourRows: neighbourRows, + attr: attr, + grid: grid$1 + }; + + var fromTable = function (table) { + var rows = TableLookup.rows(table); + return map(rows, function (row) { + var element = row; + var parent$1 = parent(element); + var parentSection = parent$1.map(function (p) { + var parentName = name(p); + return parentName === 'tfoot' || parentName === 'thead' || parentName === 'tbody' ? parentName : 'tbody'; + }).getOr('tbody'); + var cells = map(TableLookup.cells(row), function (cell) { + var rowspan = has$1(cell, 'rowspan') ? parseInt(get$1(cell, 'rowspan'), 10) : 1; + var colspan = has$1(cell, 'colspan') ? parseInt(get$1(cell, 'colspan'), 10) : 1; + return detail(cell, rowspan, colspan); + }); + return rowdata(element, cells, parentSection); + }); + }; + var fromPastedRows = function (rows, example) { + return map(rows, function (row) { + var cells = map(TableLookup.cells(row), function (cell) { + var rowspan = has$1(cell, 'rowspan') ? parseInt(get$1(cell, 'rowspan'), 10) : 1; + var colspan = has$1(cell, 'colspan') ? parseInt(get$1(cell, 'colspan'), 10) : 1; + return detail(cell, rowspan, colspan); + }); + return rowdata(row, cells, example.section()); + }); + }; + var DetailsList = { + fromTable: fromTable, + fromPastedRows: fromPastedRows + }; + + var key = function (row, column) { + return row + ',' + column; + }; + var getAt = function (warehouse, row, column) { + var raw = warehouse.access()[key(row, column)]; + return raw !== undefined ? Option.some(raw) : Option.none(); + }; + var findItem = function (warehouse, item, comparator) { + var filtered = filterItems(warehouse, function (detail) { + return comparator(item, detail.element()); + }); + return filtered.length > 0 ? Option.some(filtered[0]) : Option.none(); + }; + var filterItems = function (warehouse, predicate) { + var all = bind(warehouse.all(), function (r) { + return r.cells(); + }); + return filter(all, predicate); + }; + var generate = function (list) { + var access = {}; + var cells = []; + var maxRows = list.length; + var maxColumns = 0; + each(list, function (details, r) { + var currentRow = []; + each(details.cells(), function (detail) { + var start = 0; + while (access[key(r, start)] !== undefined) { + start++; + } + var current = extended(detail.element(), detail.rowspan(), detail.colspan(), r, start); + for (var i = 0; i < detail.colspan(); i++) { + for (var j = 0; j < detail.rowspan(); j++) { + var cr = r + j; + var cc = start + i; + var newpos = key(cr, cc); + access[newpos] = current; + maxColumns = Math.max(maxColumns, cc + 1); + } + } + currentRow.push(current); + }); + cells.push(rowdata(details.element(), currentRow, details.section())); + }); + var grid$1 = grid(maxRows, maxColumns); + return { + grid: constant(grid$1), + access: constant(access), + all: constant(cells) + }; + }; + var justCells = function (warehouse) { + var rows = map(warehouse.all(), function (w) { + return w.cells(); + }); + return flatten(rows); + }; + var Warehouse = { + generate: generate, + getAt: getAt, + findItem: findItem, + filterItems: filterItems, + justCells: justCells + }; + + var statsStruct = Immutable('minRow', 'minCol', 'maxRow', 'maxCol'); + var findSelectedStats = function (house, isSelected) { + var totalColumns = house.grid().columns(); + var totalRows = house.grid().rows(); + var minRow = totalRows; + var minCol = totalColumns; + var maxRow = 0; + var maxCol = 0; + each$1(house.access(), function (detail) { + if (isSelected(detail)) { + var startRow = detail.row(); + var endRow = startRow + detail.rowspan() - 1; + var startCol = detail.column(); + var endCol = startCol + detail.colspan() - 1; + if (startRow < minRow) { + minRow = startRow; + } else if (endRow > maxRow) { + maxRow = endRow; + } + if (startCol < minCol) { + minCol = startCol; + } else if (endCol > maxCol) { + maxCol = endCol; + } + } + }); + return statsStruct(minRow, minCol, maxRow, maxCol); + }; + var makeCell = function (list, seenSelected, rowIndex) { + var row = list[rowIndex].element(); + var td = Element.fromTag('td'); + append(td, Element.fromTag('br')); + var f = seenSelected ? append : prepend; + f(row, td); + }; + var fillInGaps = function (list, house, stats, isSelected) { + var totalColumns = house.grid().columns(); + var totalRows = house.grid().rows(); + for (var i = 0; i < totalRows; i++) { + var seenSelected = false; + for (var j = 0; j < totalColumns; j++) { + if (!(i < stats.minRow() || i > stats.maxRow() || j < stats.minCol() || j > stats.maxCol())) { + var needCell = Warehouse.getAt(house, i, j).filter(isSelected).isNone(); + if (needCell) { + makeCell(list, seenSelected, i); + } else { + seenSelected = true; + } + } + } + } + }; + var clean = function (table, stats) { + var emptyRows = filter(LayerSelector.firstLayer(table, 'tr'), function (row) { + return row.dom().childElementCount === 0; + }); + each(emptyRows, remove$2); + if (stats.minCol() === stats.maxCol() || stats.minRow() === stats.maxRow()) { + each(LayerSelector.firstLayer(table, 'th,td'), function (cell) { + remove(cell, 'rowspan'); + remove(cell, 'colspan'); + }); + } + remove(table, 'width'); + remove(table, 'height'); + remove$1(table, 'width'); + remove$1(table, 'height'); + }; + var extract = function (table, selectedSelector) { + var isSelected = function (detail) { + return is(detail.element(), selectedSelector); + }; + var list = DetailsList.fromTable(table); + var house = Warehouse.generate(list); + var stats = findSelectedStats(house, isSelected); + var selector = 'th:not(' + selectedSelector + ')' + ',td:not(' + selectedSelector + ')'; + var unselectedCells = LayerSelector.filterFirstLayer(table, 'th,td', function (cell) { + return is(cell, selector); + }); + each(unselectedCells, remove$2); + fillInGaps(list, house, stats, isSelected); + clean(table, stats); + return table; + }; + var CopySelected = { extract: extract }; + + function NodeValue (is, name) { + var get = function (element) { + if (!is(element)) { + throw new Error('Can only get ' + name + ' value of a ' + name + ' node'); + } + return getOption(element).getOr(''); + }; + var getOption = function (element) { + return is(element) ? Option.from(element.dom().nodeValue) : Option.none(); + }; + var set = function (element, value) { + if (!is(element)) { + throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node'); + } + element.dom().nodeValue = value; + }; + return { + get: get, + getOption: getOption, + set: set + }; + } + + var api = NodeValue(isText, 'text'); + var get$3 = function (element) { + return api.get(element); + }; + var getOption = function (element) { + return api.getOption(element); + }; + var set$2 = function (element, value) { + api.set(element, value); + }; + + var getEnd = function (element) { + return name(element) === 'img' ? 1 : getOption(element).fold(function () { + return children(element).length; + }, function (v) { + return v.length; + }); + }; + var NBSP = '\xA0'; + var isTextNodeWithCursorPosition = function (el) { + return getOption(el).filter(function (text) { + return text.trim().length !== 0 || text.indexOf(NBSP) > -1; + }).isSome(); + }; + var elementsWithCursorPosition = [ + 'img', + 'br' + ]; + var isCursorPosition = function (elem) { + var hasCursorPosition = isTextNodeWithCursorPosition(elem); + return hasCursorPosition || contains(elementsWithCursorPosition, name(elem)); + }; + + var first = function (element) { + return descendant(element, isCursorPosition); + }; + var last$1 = function (element) { + return descendantRtl(element, isCursorPosition); + }; + var descendantRtl = function (scope, predicate) { + var descend = function (element) { + var children$1 = children(element); + for (var i = children$1.length - 1; i >= 0; i--) { + var child = children$1[i]; + if (predicate(child)) { + return Option.some(child); + } + var res = descend(child); + if (res.isSome()) { + return res; + } + } + return Option.none(); + }; + return descend(scope); + }; + + var clone$1 = function (original, isDeep) { + return Element.fromDom(original.dom().cloneNode(isDeep)); + }; + var shallow = function (original) { + return clone$1(original, false); + }; + var deep = function (original) { + return clone$1(original, true); + }; + var shallowAs = function (original, tag) { + var nu = Element.fromTag(tag); + var attributes = clone(original); + setAll(nu, attributes); + return nu; + }; + var copy$1 = function (original, tag) { + var nu = shallowAs(original, tag); + var cloneChildren = children(deep(original)); + append$1(nu, cloneChildren); + return nu; + }; + + var createCell = function () { + var td = Element.fromTag('td'); + append(td, Element.fromTag('br')); + return td; + }; + var replace = function (cell, tag, attrs) { + var replica = copy$1(cell, tag); + each$1(attrs, function (v, k) { + if (v === null) { + remove(replica, k); + } else { + set(replica, k, v); + } + }); + return replica; + }; + var pasteReplace = function (cell) { + return cell; + }; + var newRow = function (doc) { + return function () { + return Element.fromTag('tr', doc.dom()); + }; + }; + var cloneFormats = function (oldCell, newCell, formats) { + var first$1 = first(oldCell); + return first$1.map(function (firstText) { + var formatSelector = formats.join(','); + var parents = ancestors$1(firstText, formatSelector, function (element) { + return eq(element, oldCell); + }); + return foldr(parents, function (last, parent) { + var clonedFormat = shallow(parent); + remove(clonedFormat, 'contenteditable'); + append(last, clonedFormat); + return clonedFormat; + }, newCell); + }).getOr(newCell); + }; + var cellOperations = function (mutate, doc, formatsToClone) { + var newCell = function (prev) { + var docu = owner(prev.element()); + var td = Element.fromTag(name(prev.element()), docu.dom()); + var formats = formatsToClone.getOr([ + 'strong', + 'em', + 'b', + 'i', + 'span', + 'font', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'p', + 'div' + ]); + var lastNode = formats.length > 0 ? cloneFormats(prev.element(), td, formats) : td; + append(lastNode, Element.fromTag('br')); + copy(prev.element(), td); + remove$1(td, 'height'); + if (prev.colspan() !== 1) { + remove$1(prev.element(), 'width'); + } + mutate(prev.element(), td); + return td; + }; + return { + row: newRow(doc), + cell: newCell, + replace: replace, + gap: createCell + }; + }; + var paste = function (doc) { + return { + row: newRow(doc), + cell: createCell, + replace: pasteReplace, + gap: createCell + }; + }; + var TableFill = { + cellOperations: cellOperations, + paste: paste + }; + + var fromHtml$1 = function (html, scope) { + var doc = scope || domGlobals.document; + var div = doc.createElement('div'); + div.innerHTML = html; + return children(Element.fromDom(div)); + }; + + var inSelection = function (bounds, detail) { + var leftEdge = detail.column(); + var rightEdge = detail.column() + detail.colspan() - 1; + var topEdge = detail.row(); + var bottomEdge = detail.row() + detail.rowspan() - 1; + return leftEdge <= bounds.finishCol() && rightEdge >= bounds.startCol() && (topEdge <= bounds.finishRow() && bottomEdge >= bounds.startRow()); + }; + var isWithin = function (bounds, detail) { + return detail.column() >= bounds.startCol() && detail.column() + detail.colspan() - 1 <= bounds.finishCol() && detail.row() >= bounds.startRow() && detail.row() + detail.rowspan() - 1 <= bounds.finishRow(); + }; + var isRectangular = function (warehouse, bounds) { + var isRect = true; + var detailIsWithin = curry(isWithin, bounds); + for (var i = bounds.startRow(); i <= bounds.finishRow(); i++) { + for (var j = bounds.startCol(); j <= bounds.finishCol(); j++) { + isRect = isRect && Warehouse.getAt(warehouse, i, j).exists(detailIsWithin); + } + } + return isRect ? Option.some(bounds) : Option.none(); + }; + var CellBounds = { + inSelection: inSelection, + isWithin: isWithin, + isRectangular: isRectangular + }; + + var getBounds = function (detailA, detailB) { + return bounds(Math.min(detailA.row(), detailB.row()), Math.min(detailA.column(), detailB.column()), Math.max(detailA.row() + detailA.rowspan() - 1, detailB.row() + detailB.rowspan() - 1), Math.max(detailA.column() + detailA.colspan() - 1, detailB.column() + detailB.colspan() - 1)); + }; + var getAnyBox = function (warehouse, startCell, finishCell) { + var startCoords = Warehouse.findItem(warehouse, startCell, eq); + var finishCoords = Warehouse.findItem(warehouse, finishCell, eq); + return startCoords.bind(function (sc) { + return finishCoords.map(function (fc) { + return getBounds(sc, fc); + }); + }); + }; + var getBox = function (warehouse, startCell, finishCell) { + return getAnyBox(warehouse, startCell, finishCell).bind(function (bounds) { + return CellBounds.isRectangular(warehouse, bounds); + }); + }; + var CellGroup = { + getAnyBox: getAnyBox, + getBox: getBox + }; + + var moveBy = function (warehouse, cell, row, column) { + return Warehouse.findItem(warehouse, cell, eq).bind(function (detail) { + var startRow = row > 0 ? detail.row() + detail.rowspan() - 1 : detail.row(); + var startCol = column > 0 ? detail.column() + detail.colspan() - 1 : detail.column(); + var dest = Warehouse.getAt(warehouse, startRow + row, startCol + column); + return dest.map(function (d) { + return d.element(); + }); + }); + }; + var intercepts = function (warehouse, start, finish) { + return CellGroup.getAnyBox(warehouse, start, finish).map(function (bounds) { + var inside = Warehouse.filterItems(warehouse, curry(CellBounds.inSelection, bounds)); + return map(inside, function (detail) { + return detail.element(); + }); + }); + }; + var parentCell = function (warehouse, innerCell) { + var isContainedBy = function (c1, c2) { + return contains$2(c2, c1); + }; + return Warehouse.findItem(warehouse, innerCell, isContainedBy).map(function (detail) { + return detail.element(); + }); + }; + var CellFinder = { + moveBy: moveBy, + intercepts: intercepts, + parentCell: parentCell + }; + + var moveBy$1 = function (cell, deltaRow, deltaColumn) { + return TableLookup.table(cell).bind(function (table) { + var warehouse = getWarehouse(table); + return CellFinder.moveBy(warehouse, cell, deltaRow, deltaColumn); + }); + }; + var intercepts$1 = function (table, first, last) { + var warehouse = getWarehouse(table); + return CellFinder.intercepts(warehouse, first, last); + }; + var nestedIntercepts = function (table, first, firstTable, last, lastTable) { + var warehouse = getWarehouse(table); + var optStartCell = eq(table, firstTable) ? Option.some(first) : CellFinder.parentCell(warehouse, first); + var optLastCell = eq(table, lastTable) ? Option.some(last) : CellFinder.parentCell(warehouse, last); + return optStartCell.bind(function (startCell) { + return optLastCell.bind(function (lastCell) { + return CellFinder.intercepts(warehouse, startCell, lastCell); + }); + }); + }; + var getBox$1 = function (table, first, last) { + var warehouse = getWarehouse(table); + return CellGroup.getBox(warehouse, first, last); + }; + var getWarehouse = function (table) { + var list = DetailsList.fromTable(table); + return Warehouse.generate(list); + }; + var TablePositions = { + moveBy: moveBy$1, + intercepts: intercepts$1, + nestedIntercepts: nestedIntercepts, + getBox: getBox$1 + }; + + var TagBoundaries = [ + 'body', + 'p', + 'div', + 'article', + 'aside', + 'figcaption', + 'figure', + 'footer', + 'header', + 'nav', + 'section', + 'ol', + 'ul', + 'li', + 'table', + 'thead', + 'tbody', + 'tfoot', + 'caption', + 'tr', + 'td', + 'th', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'blockquote', + 'pre', + 'address' + ]; + + function DomUniverse () { + var clone$1 = function (element) { + return Element.fromDom(element.dom().cloneNode(false)); + }; + var document = function (element) { + return element.dom().ownerDocument; + }; + var isBoundary = function (element) { + if (!isElement(element)) { + return false; + } + if (name(element) === 'body') { + return true; + } + return contains(TagBoundaries, name(element)); + }; + var isEmptyTag = function (element) { + if (!isElement(element)) { + return false; + } + return contains([ + 'br', + 'img', + 'hr', + 'input' + ], name(element)); + }; + var comparePosition = function (element, other) { + return element.dom().compareDocumentPosition(other.dom()); + }; + var copyAttributesTo = function (source, destination) { + var as = clone(source); + setAll(destination, as); + }; + return { + up: constant({ + selector: ancestor$1, + closest: closest$1, + predicate: ancestor, + all: parents + }), + down: constant({ + selector: descendants$1, + predicate: descendants + }), + styles: constant({ + get: get$2, + getRaw: getRaw, + set: set$1, + remove: remove$1 + }), + attrs: constant({ + get: get$1, + set: set, + remove: remove, + copyTo: copyAttributesTo + }), + insert: constant({ + before: before, + after: after, + afterAll: after$1, + append: append, + appendAll: append$1, + prepend: prepend, + wrap: wrap + }), + remove: constant({ + unwrap: unwrap, + remove: remove$2 + }), + create: constant({ + nu: Element.fromTag, + clone: clone$1, + text: Element.fromText + }), + query: constant({ + comparePosition: comparePosition, + prevSibling: prevSibling, + nextSibling: nextSibling + }), + property: constant({ + children: children, + name: name, + parent: parent, + document: document, + isText: isText, + isComment: isComment, + isElement: isElement, + getText: get$3, + setText: set$2, + isBoundary: isBoundary, + isEmptyTag: isEmptyTag + }), + eq: eq, + is: is$1 + }; + } + + var leftRight = Immutable('left', 'right'); + var brokenPath = Immutable('first', 'second', 'splits'); + var bisect = function (universe, parent, child) { + var children = universe.property().children(parent); + var index = findIndex(children, curry(universe.eq, child)); + return index.map(function (ind) { + return { + before: constant(children.slice(0, ind)), + after: constant(children.slice(ind + 1)) + }; + }); + }; + var breakToRight = function (universe, parent, child) { + return bisect(universe, parent, child).map(function (parts) { + var second = universe.create().clone(parent); + universe.insert().appendAll(second, parts.after()); + universe.insert().after(parent, second); + return leftRight(parent, second); + }); + }; + var breakToLeft = function (universe, parent, child) { + return bisect(universe, parent, child).map(function (parts) { + var prior = universe.create().clone(parent); + universe.insert().appendAll(prior, parts.before().concat([child])); + universe.insert().appendAll(parent, parts.after()); + universe.insert().before(parent, prior); + return leftRight(prior, parent); + }); + }; + var breakPath = function (universe, item, isTop, breaker) { + var next = function (child, group, splits) { + var fallback = brokenPath(child, Option.none(), splits); + if (isTop(child)) { + return brokenPath(child, group, splits); + } else { + return universe.property().parent(child).bind(function (parent) { + return breaker(universe, parent, child).map(function (breakage) { + var extra = [{ + first: breakage.left, + second: breakage.right + }]; + var nextChild = isTop(parent) ? parent : breakage.left(); + return next(nextChild, Option.some(breakage.right()), splits.concat(extra)); + }); + }).getOr(fallback); + } + }; + return next(item, Option.none(), []); + }; + + var all$1 = function (universe, look, elements, f) { + var head = elements[0]; + var tail = elements.slice(1); + return f(universe, look, head, tail); + }; + var oneAll = function (universe, look, elements) { + return elements.length > 0 ? all$1(universe, look, elements, unsafeOne) : Option.none(); + }; + var unsafeOne = function (universe, look, head, tail) { + var start = look(universe, head); + return foldr(tail, function (b, a) { + var current = look(universe, a); + return commonElement(universe, b, current); + }, start); + }; + var commonElement = function (universe, start, end) { + return start.bind(function (s) { + return end.filter(curry(universe.eq, s)); + }); + }; + + var eq$1 = function (universe, item) { + return curry(universe.eq, item); + }; + var unsafeSubset = function (universe, common, ps1, ps2) { + var children = universe.property().children(common); + if (universe.eq(common, ps1[0])) { + return Option.some([ps1[0]]); + } + if (universe.eq(common, ps2[0])) { + return Option.some([ps2[0]]); + } + var finder = function (ps) { + var topDown = reverse(ps); + var index = findIndex(topDown, eq$1(universe, common)).getOr(-1); + var item = index < topDown.length - 1 ? topDown[index + 1] : topDown[index]; + return findIndex(children, eq$1(universe, item)); + }; + var startIndex = finder(ps1); + var endIndex = finder(ps2); + return startIndex.bind(function (sIndex) { + return endIndex.map(function (eIndex) { + var first = Math.min(sIndex, eIndex); + var last = Math.max(sIndex, eIndex); + return children.slice(first, last + 1); + }); + }); + }; + var ancestors$2 = function (universe, start, end, isRoot) { + if (isRoot === void 0) { + isRoot = never; + } + var ps1 = [start].concat(universe.up().all(start)); + var ps2 = [end].concat(universe.up().all(end)); + var prune = function (path) { + var index = findIndex(path, isRoot); + return index.fold(function () { + return path; + }, function (ind) { + return path.slice(0, ind + 1); + }); + }; + var pruned1 = prune(ps1); + var pruned2 = prune(ps2); + var shared = find(pruned1, function (x) { + return exists(pruned2, eq$1(universe, x)); + }); + return { + firstpath: constant(pruned1), + secondpath: constant(pruned2), + shared: constant(shared) + }; + }; + var subset = function (universe, start, end) { + var ancs = ancestors$2(universe, start, end); + return ancs.shared().bind(function (shared) { + return unsafeSubset(universe, shared, ancs.firstpath(), ancs.secondpath()); + }); + }; + var SubsetFn = { + subset: subset, + ancestors: ancestors$2 + }; + + var sharedOne = oneAll; + var subset$1 = SubsetFn.subset; + var ancestors$3 = SubsetFn.ancestors; + var breakToLeft$1 = breakToLeft; + var breakToRight$1 = breakToRight; + var breakPath$1 = breakPath; + var Parent = { + sharedOne: sharedOne, + subset: subset$1, + ancestors: ancestors$3, + breakToLeft: breakToLeft$1, + breakToRight: breakToRight$1, + breakPath: breakPath$1 + }; + + var universe = DomUniverse(); + var sharedOne$1 = function (look, elements) { + return Parent.sharedOne(universe, function (_universe, element) { + return look(element); + }, elements); + }; + var subset$2 = function (start, finish) { + return Parent.subset(universe, start, finish); + }; + var ancestors$4 = function (start, finish, isRoot) { + return Parent.ancestors(universe, start, finish, isRoot); + }; + var breakToLeft$2 = function (parent, child) { + return Parent.breakToLeft(universe, parent, child); + }; + var breakToRight$2 = function (parent, child) { + return Parent.breakToRight(universe, parent, child); + }; + var breakPath$2 = function (child, isTop, breaker) { + return Parent.breakPath(universe, child, isTop, function (u, p, c) { + return breaker(p, c); + }); + }; + var DomParent = { + sharedOne: sharedOne$1, + subset: subset$2, + ancestors: ancestors$4, + breakToLeft: breakToLeft$2, + breakToRight: breakToRight$2, + breakPath: breakPath$2 + }; + + var create = MixedBag([ + 'boxes', + 'start', + 'finish' + ], []); + var Identified = { create: create }; + + var lookupTable = function (container) { + return ancestor$1(container, 'table'); + }; + var identify = function (start, finish, isRoot) { + var getIsRoot = function (rootTable) { + return function (element) { + return isRoot !== undefined && isRoot(element) || eq(element, rootTable); + }; + }; + if (eq(start, finish)) { + return Option.some(Identified.create({ + boxes: Option.some([start]), + start: start, + finish: finish + })); + } else { + return lookupTable(start).bind(function (startTable) { + return lookupTable(finish).bind(function (finishTable) { + if (eq(startTable, finishTable)) { + return Option.some(Identified.create({ + boxes: TablePositions.intercepts(startTable, start, finish), + start: start, + finish: finish + })); + } else if (contains$2(startTable, finishTable)) { + var ancestorCells = ancestors$1(finish, 'td,th', getIsRoot(startTable)); + var finishCell = ancestorCells.length > 0 ? ancestorCells[ancestorCells.length - 1] : finish; + return Option.some(Identified.create({ + boxes: TablePositions.nestedIntercepts(startTable, start, startTable, finish, finishTable), + start: start, + finish: finishCell + })); + } else if (contains$2(finishTable, startTable)) { + var ancestorCells = ancestors$1(start, 'td,th', getIsRoot(finishTable)); + var startCell = ancestorCells.length > 0 ? ancestorCells[ancestorCells.length - 1] : start; + return Option.some(Identified.create({ + boxes: TablePositions.nestedIntercepts(finishTable, start, startTable, finish, finishTable), + start: start, + finish: startCell + })); + } else { + return DomParent.ancestors(start, finish).shared().bind(function (lca) { + return closest$1(lca, 'table', isRoot).bind(function (lcaTable) { + var finishAncestorCells = ancestors$1(finish, 'td,th', getIsRoot(lcaTable)); + var finishCell = finishAncestorCells.length > 0 ? finishAncestorCells[finishAncestorCells.length - 1] : finish; + var startAncestorCells = ancestors$1(start, 'td,th', getIsRoot(lcaTable)); + var startCell = startAncestorCells.length > 0 ? startAncestorCells[startAncestorCells.length - 1] : start; + return Option.some(Identified.create({ + boxes: TablePositions.nestedIntercepts(lcaTable, start, startTable, finish, finishTable), + start: startCell, + finish: finishCell + })); + }); + }); + } + }); + }); + } + }; + var retrieve = function (container, selector) { + var sels = descendants$1(container, selector); + return sels.length > 0 ? Option.some(sels) : Option.none(); + }; + var getLast = function (boxes, lastSelectedSelector) { + return find(boxes, function (box) { + return is(box, lastSelectedSelector); + }); + }; + var getEdges = function (container, firstSelectedSelector, lastSelectedSelector) { + return descendant$1(container, firstSelectedSelector).bind(function (first) { + return descendant$1(container, lastSelectedSelector).bind(function (last) { + return DomParent.sharedOne(lookupTable, [ + first, + last + ]).map(function (tbl) { + return { + first: constant(first), + last: constant(last), + table: constant(tbl) + }; + }); + }); + }); + }; + var expandTo = function (finish, firstSelectedSelector) { + return ancestor$1(finish, 'table').bind(function (table) { + return descendant$1(table, firstSelectedSelector).bind(function (start) { + return identify(start, finish).bind(function (identified) { + return identified.boxes().map(function (boxes) { + return { + boxes: constant(boxes), + start: constant(identified.start()), + finish: constant(identified.finish()) + }; + }); + }); + }); + }); + }; + var shiftSelection = function (boxes, deltaRow, deltaColumn, firstSelectedSelector, lastSelectedSelector) { + return getLast(boxes, lastSelectedSelector).bind(function (last) { + return TablePositions.moveBy(last, deltaRow, deltaColumn).bind(function (finish) { + return expandTo(finish, firstSelectedSelector); + }); + }); + }; + var CellSelection = { + identify: identify, + retrieve: retrieve, + shiftSelection: shiftSelection, + getEdges: getEdges + }; + + var retrieve$1 = function (container, selector) { + return CellSelection.retrieve(container, selector); + }; + var retrieveBox = function (container, firstSelectedSelector, lastSelectedSelector) { + return CellSelection.getEdges(container, firstSelectedSelector, lastSelectedSelector).bind(function (edges) { + var isRoot = function (ancestor) { + return eq(container, ancestor); + }; + var firstAncestor = ancestor$1(edges.first(), 'thead,tfoot,tbody,table', isRoot); + var lastAncestor = ancestor$1(edges.last(), 'thead,tfoot,tbody,table', isRoot); + return firstAncestor.bind(function (fA) { + return lastAncestor.bind(function (lA) { + return eq(fA, lA) ? TablePositions.getBox(edges.table(), edges.first(), edges.last()) : Option.none(); + }); + }); + }); + }; + var TableSelection = { + retrieve: retrieve$1, + retrieveBox: retrieveBox + }; + + var selected = 'data-mce-selected'; + var selectedSelector = 'td[' + selected + '],th[' + selected + ']'; + var attributeSelector = '[' + selected + ']'; + var firstSelected = 'data-mce-first-selected'; + var firstSelectedSelector = 'td[' + firstSelected + '],th[' + firstSelected + ']'; + var lastSelected = 'data-mce-last-selected'; + var lastSelectedSelector = 'td[' + lastSelected + '],th[' + lastSelected + ']'; + var Ephemera = { + selected: constant(selected), + selectedSelector: constant(selectedSelector), + attributeSelector: constant(attributeSelector), + firstSelected: constant(firstSelected), + firstSelectedSelector: constant(firstSelectedSelector), + lastSelected: constant(lastSelected), + lastSelectedSelector: constant(lastSelectedSelector) + }; + + var generate$1 = function (cases) { + if (!isArray(cases)) { + throw new Error('cases must be an array'); + } + if (cases.length === 0) { + throw new Error('there must be at least one case'); + } + var constructors = []; + var adt = {}; + each(cases, function (acase, count) { + var keys$1 = keys(acase); + if (keys$1.length !== 1) { + throw new Error('one and only one name per case'); + } + var key = keys$1[0]; + var value = acase[key]; + if (adt[key] !== undefined) { + throw new Error('duplicate key detected:' + key); + } else if (key === 'cata') { + throw new Error('cannot have a case named cata (sorry)'); + } else if (!isArray(value)) { + throw new Error('case arguments must be an array'); + } + constructors.push(key); + adt[key] = function () { + var argLength = arguments.length; + if (argLength !== value.length) { + throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength); + } + var args = new Array(argLength); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i]; + } + var match = function (branches) { + var branchKeys = keys(branches); + if (constructors.length !== branchKeys.length) { + throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(',')); + } + var allReqd = forall(constructors, function (reqKey) { + return contains(branchKeys, reqKey); + }); + if (!allReqd) { + throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', ')); + } + return branches[key].apply(null, args); + }; + return { + fold: function () { + if (arguments.length !== cases.length) { + throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + arguments.length); + } + var target = arguments[count]; + return target.apply(null, args); + }, + match: match, + log: function (label) { + domGlobals.console.log(label, { + constructors: constructors, + constructor: key, + params: args + }); + } + }; + }; + }); + return adt; + }; + var Adt = { generate: generate$1 }; + + var type$1 = Adt.generate([ + { none: [] }, + { multiple: ['elements'] }, + { single: ['selection'] } + ]); + var cata = function (subject, onNone, onMultiple, onSingle) { + return subject.fold(onNone, onMultiple, onSingle); + }; + var SelectionTypes = { + cata: cata, + none: type$1.none, + multiple: type$1.multiple, + single: type$1.single + }; + + var selection = function (cell, selections) { + return SelectionTypes.cata(selections.get(), constant([]), identity, constant([cell])); + }; + var unmergable = function (cell, selections) { + var hasSpan = function (elem) { + return has$1(elem, 'rowspan') && parseInt(get$1(elem, 'rowspan'), 10) > 1 || has$1(elem, 'colspan') && parseInt(get$1(elem, 'colspan'), 10) > 1; + }; + var candidates = selection(cell, selections); + return candidates.length > 0 && forall(candidates, hasSpan) ? Option.some(candidates) : Option.none(); + }; + var mergable = function (table, selections) { + return SelectionTypes.cata(selections.get(), Option.none, function (cells, _env) { + if (cells.length === 0) { + return Option.none(); + } + return TableSelection.retrieveBox(table, Ephemera.firstSelectedSelector(), Ephemera.lastSelectedSelector()).bind(function (bounds) { + return cells.length > 1 ? Option.some({ + bounds: constant(bounds), + cells: constant(cells) + }) : Option.none(); + }); + }, Option.none); + }; + var CellOperations = { + mergable: mergable, + unmergable: unmergable, + selection: selection + }; + + var noMenu = function (cell) { + return { + element: constant(cell), + mergable: Option.none, + unmergable: Option.none, + selection: constant([cell]) + }; + }; + var forMenu = function (selections, table, cell) { + return { + element: constant(cell), + mergable: constant(CellOperations.mergable(table, selections)), + unmergable: constant(CellOperations.unmergable(cell, selections)), + selection: constant(CellOperations.selection(cell, selections)) + }; + }; + var notCell$1 = function (element) { + return noMenu(element); + }; + var paste$1 = Immutable('element', 'clipboard', 'generators'); + var pasteRows = function (selections, table, cell, clipboard, generators) { + return { + element: constant(cell), + mergable: Option.none, + unmergable: Option.none, + selection: constant(CellOperations.selection(cell, selections)), + clipboard: constant(clipboard), + generators: constant(generators) + }; + }; + var TableTargets = { + noMenu: noMenu, + forMenu: forMenu, + notCell: notCell$1, + paste: paste$1, + pasteRows: pasteRows + }; + + var extractSelected = function (cells) { + return TableLookup.table(cells[0]).map(deep).map(function (replica) { + return [CopySelected.extract(replica, Ephemera.attributeSelector())]; + }); + }; + var serializeElements = function (editor, elements) { + return map(elements, function (elm) { + return editor.selection.serializer.serialize(elm.dom(), {}); + }).join(''); + }; + var getTextContent = function (elements) { + return map(elements, function (element) { + return element.dom().innerText; + }).join(''); + }; + var registerEvents = function (editor, selections, actions, cellSelection) { + editor.on('BeforeGetContent', function (e) { + var multiCellContext = function (cells) { + e.preventDefault(); + extractSelected(cells).each(function (elements) { + e.content = e.format === 'text' ? getTextContent(elements) : serializeElements(editor, elements); + }); + }; + if (e.selection === true) { + SelectionTypes.cata(selections.get(), noop, multiCellContext, noop); + } + }); + editor.on('BeforeSetContent', function (e) { + if (e.selection === true && e.paste === true) { + var cellOpt = Option.from(editor.dom.getParent(editor.selection.getStart(), 'th,td')); + cellOpt.each(function (domCell) { + var cell = Element.fromDom(domCell); + TableLookup.table(cell).each(function (table) { + var elements = filter(fromHtml$1(e.content), function (content) { + return name(content) !== 'meta'; + }); + if (elements.length === 1 && name(elements[0]) === 'table') { + e.preventDefault(); + var doc = Element.fromDom(editor.getDoc()); + var generators = TableFill.paste(doc); + var targets = TableTargets.paste(cell, elements[0], generators); + actions.pasteCells(table, targets).each(function (rng) { + editor.selection.setRng(rng); + editor.focus(); + cellSelection.clear(table); + }); + } + }); + }); + } + }); + }; + var Clipboard = { registerEvents: registerEvents }; + + function Dimension (name, getOffset) { + var set = function (element, h) { + if (!isNumber(h) && !h.match(/^[0-9]+$/)) { + throw new Error(name + '.set accepts only positive integer values. Value was ' + h); + } + var dom = element.dom(); + if (isSupported(dom)) { + dom.style[name] = h + 'px'; + } + }; + var get = function (element) { + var r = getOffset(element); + if (r <= 0 || r === null) { + var css = get$2(element, name); + return parseFloat(css) || 0; + } + return r; + }; + var getOuter = get; + var aggregate = function (element, properties) { + return foldl(properties, function (acc, property) { + var val = get$2(element, property); + var value = val === undefined ? 0 : parseInt(val, 10); + return isNaN(value) ? acc : acc + value; + }, 0); + }; + var max = function (element, value, properties) { + var cumulativeInclusions = aggregate(element, properties); + var absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0; + return absoluteMax; + }; + return { + set: set, + get: get, + getOuter: getOuter, + aggregate: aggregate, + max: max + }; + } + + var api$1 = Dimension('height', function (element) { + var dom = element.dom(); + return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight; + }); + var get$4 = function (element) { + return api$1.get(element); + }; + var getOuter = function (element) { + return api$1.getOuter(element); + }; + + var api$2 = Dimension('width', function (element) { + return element.dom().offsetWidth; + }); + var get$5 = function (element) { + return api$2.get(element); + }; + var getOuter$1 = function (element) { + return api$2.getOuter(element); + }; + + var platform$1 = detect$3(); + var needManualCalc = function () { + return platform$1.browser.isIE() || platform$1.browser.isEdge(); + }; + var toNumber = function (px, fallback) { + var num = parseFloat(px); + return isNaN(num) ? fallback : num; + }; + var getProp = function (elm, name, fallback) { + return toNumber(get$2(elm, name), fallback); + }; + var getCalculatedHeight = function (cell) { + var paddingTop = getProp(cell, 'padding-top', 0); + var paddingBottom = getProp(cell, 'padding-bottom', 0); + var borderTop = getProp(cell, 'border-top-width', 0); + var borderBottom = getProp(cell, 'border-bottom-width', 0); + var height = cell.dom().getBoundingClientRect().height; + var boxSizing = get$2(cell, 'box-sizing'); + var borders = borderTop + borderBottom; + return boxSizing === 'border-box' ? height : height - paddingTop - paddingBottom - borders; + }; + var getWidth = function (cell) { + return getProp(cell, 'width', get$5(cell)); + }; + var getHeight = function (cell) { + return needManualCalc() ? getCalculatedHeight(cell) : getProp(cell, 'height', get$4(cell)); + }; + var RuntimeSize = { + getWidth: getWidth, + getHeight: getHeight + }; + + var genericSizeRegex = /(\d+(\.\d+)?)(\w|%)*/; + var percentageBasedSizeRegex = /(\d+(\.\d+)?)%/; + var pixelBasedSizeRegex = /(\d+(\.\d+)?)px|em/; + var setPixelWidth = function (cell, amount) { + set$1(cell, 'width', amount + 'px'); + }; + var setPercentageWidth = function (cell, amount) { + set$1(cell, 'width', amount + '%'); + }; + var setHeight = function (cell, amount) { + set$1(cell, 'height', amount + 'px'); + }; + var getHeightValue = function (cell) { + return getRaw(cell, 'height').getOrThunk(function () { + return RuntimeSize.getHeight(cell) + 'px'; + }); + }; + var convert = function (cell, number, getter, setter) { + var newSize = TableLookup.table(cell).map(function (table) { + var total = getter(table); + return Math.floor(number / 100 * total); + }).getOr(number); + setter(cell, newSize); + return newSize; + }; + var normalizePixelSize = function (value, cell, getter, setter) { + var number = parseInt(value, 10); + return endsWith(value, '%') && name(cell) !== 'table' ? convert(cell, number, getter, setter) : number; + }; + var getTotalHeight = function (cell) { + var value = getHeightValue(cell); + if (!value) { + return get$4(cell); + } + return normalizePixelSize(value, cell, get$4, setHeight); + }; + var get$6 = function (cell, type, f) { + var v = f(cell); + var span = getSpan(cell, type); + return v / span; + }; + var getSpan = function (cell, type) { + return has$1(cell, type) ? parseInt(get$1(cell, type), 10) : 1; + }; + var getRawWidth = function (element) { + var cssWidth = getRaw(element, 'width'); + return cssWidth.fold(function () { + return Option.from(get$1(element, 'width')); + }, function (width) { + return Option.some(width); + }); + }; + var normalizePercentageWidth = function (cellWidth, tableSize) { + return cellWidth / tableSize.pixelWidth() * 100; + }; + var choosePercentageSize = function (element, width, tableSize) { + var percentMatch = percentageBasedSizeRegex.exec(width); + if (percentMatch !== null) { + return parseFloat(percentMatch[1]); + } else { + var intWidth = get$5(element); + return normalizePercentageWidth(intWidth, tableSize); + } + }; + var getPercentageWidth = function (cell, tableSize) { + var width = getRawWidth(cell); + return width.fold(function () { + var intWidth = get$5(cell); + return normalizePercentageWidth(intWidth, tableSize); + }, function (w) { + return choosePercentageSize(cell, w, tableSize); + }); + }; + var normalizePixelWidth = function (cellWidth, tableSize) { + return cellWidth / 100 * tableSize.pixelWidth(); + }; + var choosePixelSize = function (element, width, tableSize) { + var pixelMatch = pixelBasedSizeRegex.exec(width); + if (pixelMatch !== null) { + return parseInt(pixelMatch[1], 10); + } + var percentMatch = percentageBasedSizeRegex.exec(width); + if (percentMatch !== null) { + var floatWidth = parseFloat(percentMatch[1]); + return normalizePixelWidth(floatWidth, tableSize); + } + return get$5(element); + }; + var getPixelWidth = function (cell, tableSize) { + var width = getRawWidth(cell); + return width.fold(function () { + return get$5(cell); + }, function (w) { + return choosePixelSize(cell, w, tableSize); + }); + }; + var getHeight$1 = function (cell) { + return get$6(cell, 'rowspan', getTotalHeight); + }; + var getGenericWidth = function (cell) { + var width = getRawWidth(cell); + return width.bind(function (w) { + var match = genericSizeRegex.exec(w); + if (match !== null) { + return Option.some({ + width: constant(parseFloat(match[1])), + unit: constant(match[3]) + }); + } else { + return Option.none(); + } + }); + }; + var setGenericWidth = function (cell, amount, unit) { + set$1(cell, 'width', amount + unit); + }; + var Sizes = { + percentageBasedSizeRegex: constant(percentageBasedSizeRegex), + pixelBasedSizeRegex: constant(pixelBasedSizeRegex), + setPixelWidth: setPixelWidth, + setPercentageWidth: setPercentageWidth, + setHeight: setHeight, + getPixelWidth: getPixelWidth, + getPercentageWidth: getPercentageWidth, + getGenericWidth: getGenericWidth, + setGenericWidth: setGenericWidth, + getHeight: getHeight$1, + getRawWidth: getRawWidth + }; + + var halve = function (main, other) { + var width = Sizes.getGenericWidth(main); + width.each(function (w) { + var newWidth = w.width() / 2; + Sizes.setGenericWidth(main, newWidth, w.unit()); + Sizes.setGenericWidth(other, newWidth, w.unit()); + }); + }; + var CellMutations = { halve: halve }; + + var r = function (left, top) { + var translate = function (x, y) { + return r(left + x, top + y); + }; + return { + left: constant(left), + top: constant(top), + translate: translate + }; + }; + var Position = r; + + var boxPosition = function (dom) { + var box = dom.getBoundingClientRect(); + return Position(box.left, box.top); + }; + var firstDefinedOrZero = function (a, b) { + return a !== undefined ? a : b !== undefined ? b : 0; + }; + var absolute = function (element) { + var doc = element.dom().ownerDocument; + var body = doc.body; + var win = doc.defaultView; + var html = doc.documentElement; + if (body === element.dom()) { + return Position(body.offsetLeft, body.offsetTop); + } + var scrollTop = firstDefinedOrZero(win.pageYOffset, html.scrollTop); + var scrollLeft = firstDefinedOrZero(win.pageXOffset, html.scrollLeft); + var clientTop = firstDefinedOrZero(html.clientTop, body.clientTop); + var clientLeft = firstDefinedOrZero(html.clientLeft, body.clientLeft); + return viewport(element).translate(scrollLeft - clientLeft, scrollTop - clientTop); + }; + var viewport = function (element) { + var dom = element.dom(); + var doc = dom.ownerDocument; + var body = doc.body; + if (body === dom) { + return Position(body.offsetLeft, body.offsetTop); + } + if (!inBody(element)) { + return Position(0, 0); + } + return boxPosition(dom); + }; + + var rowInfo = Immutable('row', 'y'); + var colInfo = Immutable('col', 'x'); + var rtlEdge = function (cell) { + var pos = absolute(cell); + return pos.left() + getOuter$1(cell); + }; + var ltrEdge = function (cell) { + return absolute(cell).left(); + }; + var getLeftEdge = function (index, cell) { + return colInfo(index, ltrEdge(cell)); + }; + var getRightEdge = function (index, cell) { + return colInfo(index, rtlEdge(cell)); + }; + var getTop = function (cell) { + return absolute(cell).top(); + }; + var getTopEdge = function (index, cell) { + return rowInfo(index, getTop(cell)); + }; + var getBottomEdge = function (index, cell) { + return rowInfo(index, getTop(cell) + getOuter(cell)); + }; + var findPositions = function (getInnerEdge, getOuterEdge, array) { + if (array.length === 0) { + return []; + } + var lines = map(array.slice(1), function (cellOption, index) { + return cellOption.map(function (cell) { + return getInnerEdge(index, cell); + }); + }); + var lastLine = array[array.length - 1].map(function (cell) { + return getOuterEdge(array.length - 1, cell); + }); + return lines.concat([lastLine]); + }; + var negate = function (step) { + return -step; + }; + var height = { + delta: identity, + positions: function (optElements) { + return findPositions(getTopEdge, getBottomEdge, optElements); + }, + edge: getTop + }; + var ltr = { + delta: identity, + edge: ltrEdge, + positions: function (optElements) { + return findPositions(getLeftEdge, getRightEdge, optElements); + } + }; + var rtl = { + delta: negate, + edge: rtlEdge, + positions: function (optElements) { + return findPositions(getRightEdge, getLeftEdge, optElements); + } + }; + var BarPositions = { + height: height, + rtl: rtl, + ltr: ltr + }; + + var ResizeDirection = { + ltr: BarPositions.ltr, + rtl: BarPositions.rtl + }; + + function TableDirection (directionAt) { + var auto = function (table) { + return directionAt(table).isRtl() ? ResizeDirection.rtl : ResizeDirection.ltr; + }; + var delta = function (amount, table) { + return auto(table).delta(amount, table); + }; + var positions = function (cols, table) { + return auto(table).positions(cols, table); + }; + var edge = function (cell) { + return auto(cell).edge(cell); + }; + return { + delta: delta, + edge: edge, + positions: positions + }; + } + + var getGridSize = function (table) { + var input = DetailsList.fromTable(table); + var warehouse = Warehouse.generate(input); + return warehouse.grid(); + }; + var TableGridSize = { getGridSize: getGridSize }; + + var cat = function (arr) { + var r = []; + var push = function (x) { + r.push(x); + }; + for (var i = 0; i < arr.length; i++) { + arr[i].each(push); + } + return r; + }; + var findMap = function (arr, f) { + for (var i = 0; i < arr.length; i++) { + var r = f(arr[i], i); + if (r.isSome()) { + return r; + } + } + return Option.none(); + }; + + var setIfNot = function (element, property, value, ignore) { + if (value === ignore) { + remove(element, property); + } else { + set(element, property, value); + } + }; + var render = function (table, grid) { + var newRows = []; + var newCells = []; + var renderSection = function (gridSection, sectionName) { + var section = child$2(table, sectionName).getOrThunk(function () { + var tb = Element.fromTag(sectionName, owner(table).dom()); + append(table, tb); + return tb; + }); + empty(section); + var rows = map(gridSection, function (row) { + if (row.isNew()) { + newRows.push(row.element()); + } + var tr = row.element(); + empty(tr); + each(row.cells(), function (cell) { + if (cell.isNew()) { + newCells.push(cell.element()); + } + setIfNot(cell.element(), 'colspan', cell.colspan(), 1); + setIfNot(cell.element(), 'rowspan', cell.rowspan(), 1); + append(tr, cell.element()); + }); + return tr; + }); + append$1(section, rows); + }; + var removeSection = function (sectionName) { + child$2(table, sectionName).each(remove$2); + }; + var renderOrRemoveSection = function (gridSection, sectionName) { + if (gridSection.length > 0) { + renderSection(gridSection, sectionName); + } else { + removeSection(sectionName); + } + }; + var headSection = []; + var bodySection = []; + var footSection = []; + each(grid, function (row) { + switch (row.section()) { + case 'thead': + headSection.push(row); + break; + case 'tbody': + bodySection.push(row); + break; + case 'tfoot': + footSection.push(row); + break; + } + }); + renderOrRemoveSection(headSection, 'thead'); + renderOrRemoveSection(bodySection, 'tbody'); + renderOrRemoveSection(footSection, 'tfoot'); + return { + newRows: constant(newRows), + newCells: constant(newCells) + }; + }; + var copy$2 = function (grid) { + var rows = map(grid, function (row) { + var tr = shallow(row.element()); + each(row.cells(), function (cell) { + var clonedCell = deep(cell.element()); + setIfNot(clonedCell, 'colspan', cell.colspan(), 1); + setIfNot(clonedCell, 'rowspan', cell.rowspan(), 1); + append(tr, clonedCell); + }); + return tr; + }); + return rows; + }; + var Redraw = { + render: render, + copy: copy$2 + }; + + var read = function (element, attr) { + var value = get$1(element, attr); + return value === undefined || value === '' ? [] : value.split(' '); + }; + var add = function (element, attr, id) { + var old = read(element, attr); + var nu = old.concat([id]); + set(element, attr, nu.join(' ')); + return true; + }; + var remove$3 = function (element, attr, id) { + var nu = filter(read(element, attr), function (v) { + return v !== id; + }); + if (nu.length > 0) { + set(element, attr, nu.join(' ')); + } else { + remove(element, attr); + } + return false; + }; + + var supports = function (element) { + return element.dom().classList !== undefined; + }; + var get$7 = function (element) { + return read(element, 'class'); + }; + var add$1 = function (element, clazz) { + return add(element, 'class', clazz); + }; + var remove$4 = function (element, clazz) { + return remove$3(element, 'class', clazz); + }; + + var add$2 = function (element, clazz) { + if (supports(element)) { + element.dom().classList.add(clazz); + } else { + add$1(element, clazz); + } + }; + var cleanClass = function (element) { + var classList = supports(element) ? element.dom().classList : get$7(element); + if (classList.length === 0) { + remove(element, 'class'); + } + }; + var remove$5 = function (element, clazz) { + if (supports(element)) { + var classList = element.dom().classList; + classList.remove(clazz); + } else { + remove$4(element, clazz); + } + cleanClass(element); + }; + var has$2 = function (element, clazz) { + return supports(element) && element.dom().classList.contains(clazz); + }; + + var repeat = function (repititions, f) { + var r = []; + for (var i = 0; i < repititions; i++) { + r.push(f(i)); + } + return r; + }; + var range = function (start, end) { + var r = []; + for (var i = start; i < end; i++) { + r.push(i); + } + return r; + }; + var deduce = function (xs, index) { + if (index < 0 || index >= xs.length - 1) { + return Option.none(); + } + var current = xs[index].fold(function () { + var rest = reverse(xs.slice(0, index)); + return findMap(rest, function (a, i) { + return a.map(function (aa) { + return { + value: aa, + delta: i + 1 + }; + }); + }); + }, function (c) { + return Option.some({ + value: c, + delta: 0 + }); + }); + var next = xs[index + 1].fold(function () { + var rest = xs.slice(index + 1); + return findMap(rest, function (a, i) { + return a.map(function (aa) { + return { + value: aa, + delta: i + 1 + }; + }); + }); + }, function (n) { + return Option.some({ + value: n, + delta: 1 + }); + }); + return current.bind(function (c) { + return next.map(function (n) { + var extras = n.delta + c.delta; + return Math.abs(n.value - c.value) / extras; + }); + }); + }; + + var columns = function (warehouse) { + var grid = warehouse.grid(); + var cols = range(0, grid.columns()); + var rowsArr = range(0, grid.rows()); + return map(cols, function (col) { + var getBlock = function () { + return bind(rowsArr, function (r) { + return Warehouse.getAt(warehouse, r, col).filter(function (detail) { + return detail.column() === col; + }).fold(constant([]), function (detail) { + return [detail]; + }); + }); + }; + var isSingle = function (detail) { + return detail.colspan() === 1; + }; + var getFallback = function () { + return Warehouse.getAt(warehouse, 0, col); + }; + return decide(getBlock, isSingle, getFallback); + }); + }; + var decide = function (getBlock, isSingle, getFallback) { + var inBlock = getBlock(); + var singleInBlock = find(inBlock, isSingle); + var detailOption = singleInBlock.orThunk(function () { + return Option.from(inBlock[0]).orThunk(getFallback); + }); + return detailOption.map(function (detail) { + return detail.element(); + }); + }; + var rows$1 = function (warehouse) { + var grid = warehouse.grid(); + var rowsArr = range(0, grid.rows()); + var cols = range(0, grid.columns()); + return map(rowsArr, function (row) { + var getBlock = function () { + return bind(cols, function (c) { + return Warehouse.getAt(warehouse, row, c).filter(function (detail) { + return detail.row() === row; + }).fold(constant([]), function (detail) { + return [detail]; + }); + }); + }; + var isSingle = function (detail) { + return detail.rowspan() === 1; + }; + var getFallback = function () { + return Warehouse.getAt(warehouse, row, 0); + }; + return decide(getBlock, isSingle, getFallback); + }); + }; + var Blocks = { + columns: columns, + rows: rows$1 + }; + + var css = function (namespace) { + var dashNamespace = namespace.replace(/\./g, '-'); + var resolve = function (str) { + return dashNamespace + '-' + str; + }; + return { resolve: resolve }; + }; + + var styles = css('ephox-snooker'); + var Styles = { resolve: styles.resolve }; + + var col = function (column, x, y, w, h) { + var blocker = Element.fromTag('div'); + setAll$1(blocker, { + position: 'absolute', + left: x - w / 2 + 'px', + top: y + 'px', + height: h + 'px', + width: w + 'px' + }); + setAll(blocker, { + 'data-column': column, + 'role': 'presentation' + }); + return blocker; + }; + var row$1 = function (r, x, y, w, h) { + var blocker = Element.fromTag('div'); + setAll$1(blocker, { + position: 'absolute', + left: x + 'px', + top: y - h / 2 + 'px', + height: h + 'px', + width: w + 'px' + }); + setAll(blocker, { + 'data-row': r, + 'role': 'presentation' + }); + return blocker; + }; + var Bar = { + col: col, + row: row$1 + }; + + var resizeBar = Styles.resolve('resizer-bar'); + var resizeRowBar = Styles.resolve('resizer-rows'); + var resizeColBar = Styles.resolve('resizer-cols'); + var BAR_THICKNESS = 7; + var destroy = function (wire) { + var previous = descendants$1(wire.parent(), '.' + resizeBar); + each(previous, remove$2); + }; + var drawBar = function (wire, positions, create) { + var origin = wire.origin(); + each(positions, function (cpOption, i) { + cpOption.each(function (cp) { + var bar = create(origin, cp); + add$2(bar, resizeBar); + append(wire.parent(), bar); + }); + }); + }; + var refreshCol = function (wire, colPositions, position, tableHeight) { + drawBar(wire, colPositions, function (origin, cp) { + var colBar = Bar.col(cp.col(), cp.x() - origin.left(), position.top() - origin.top(), BAR_THICKNESS, tableHeight); + add$2(colBar, resizeColBar); + return colBar; + }); + }; + var refreshRow = function (wire, rowPositions, position, tableWidth) { + drawBar(wire, rowPositions, function (origin, cp) { + var rowBar = Bar.row(cp.row(), position.left() - origin.left(), cp.y() - origin.top(), tableWidth, BAR_THICKNESS); + add$2(rowBar, resizeRowBar); + return rowBar; + }); + }; + var refreshGrid = function (wire, table, rows, cols, hdirection, vdirection) { + var position = absolute(table); + var rowPositions = rows.length > 0 ? hdirection.positions(rows, table) : []; + refreshRow(wire, rowPositions, position, getOuter$1(table)); + var colPositions = cols.length > 0 ? vdirection.positions(cols, table) : []; + refreshCol(wire, colPositions, position, getOuter(table)); + }; + var refresh = function (wire, table, hdirection, vdirection) { + destroy(wire); + var list = DetailsList.fromTable(table); + var warehouse = Warehouse.generate(list); + var rows = Blocks.rows(warehouse); + var cols = Blocks.columns(warehouse); + refreshGrid(wire, table, rows, cols, hdirection, vdirection); + }; + var each$2 = function (wire, f) { + var bars = descendants$1(wire.parent(), '.' + resizeBar); + each(bars, f); + }; + var hide = function (wire) { + each$2(wire, function (bar) { + set$1(bar, 'display', 'none'); + }); + }; + var show = function (wire) { + each$2(wire, function (bar) { + set$1(bar, 'display', 'block'); + }); + }; + var isRowBar = function (element) { + return has$2(element, resizeRowBar); + }; + var isColBar = function (element) { + return has$2(element, resizeColBar); + }; + var Bars = { + refresh: refresh, + hide: hide, + show: show, + destroy: destroy, + isRowBar: isRowBar, + isColBar: isColBar + }; + + var addCell = function (gridRow, index, cell) { + var cells = gridRow.cells(); + var before = cells.slice(0, index); + var after = cells.slice(index); + var newCells = before.concat([cell]).concat(after); + return setCells(gridRow, newCells); + }; + var mutateCell = function (gridRow, index, cell) { + var cells = gridRow.cells(); + cells[index] = cell; + }; + var setCells = function (gridRow, cells) { + return rowcells(cells, gridRow.section()); + }; + var mapCells = function (gridRow, f) { + var cells = gridRow.cells(); + var r = map(cells, f); + return rowcells(r, gridRow.section()); + }; + var getCell = function (gridRow, index) { + return gridRow.cells()[index]; + }; + var getCellElement = function (gridRow, index) { + return getCell(gridRow, index).element(); + }; + var cellLength = function (gridRow) { + return gridRow.cells().length; + }; + var GridRow = { + addCell: addCell, + setCells: setCells, + mutateCell: mutateCell, + getCell: getCell, + getCellElement: getCellElement, + mapCells: mapCells, + cellLength: cellLength + }; + + var getColumn = function (grid, index) { + return map(grid, function (row) { + return GridRow.getCell(row, index); + }); + }; + var getRow = function (grid, index) { + return grid[index]; + }; + var findDiff = function (xs, comp) { + if (xs.length === 0) { + return 0; + } + var first = xs[0]; + var index = findIndex(xs, function (x) { + return !comp(first.element(), x.element()); + }); + return index.fold(function () { + return xs.length; + }, function (ind) { + return ind; + }); + }; + var subgrid = function (grid, row, column, comparator) { + var restOfRow = getRow(grid, row).cells().slice(column); + var endColIndex = findDiff(restOfRow, comparator); + var restOfColumn = getColumn(grid, column).slice(row); + var endRowIndex = findDiff(restOfColumn, comparator); + return { + colspan: constant(endColIndex), + rowspan: constant(endRowIndex) + }; + }; + var TableGrid = { subgrid: subgrid }; + + var toDetails = function (grid, comparator) { + var seen = map(grid, function (row, ri) { + return map(row.cells(), function (col, ci) { + return false; + }); + }); + var updateSeen = function (ri, ci, rowspan, colspan) { + for (var r = ri; r < ri + rowspan; r++) { + for (var c = ci; c < ci + colspan; c++) { + seen[r][c] = true; + } + } + }; + return map(grid, function (row, ri) { + var details = bind(row.cells(), function (cell, ci) { + if (seen[ri][ci] === false) { + var result = TableGrid.subgrid(grid, ri, ci, comparator); + updateSeen(ri, ci, result.rowspan(), result.colspan()); + return [detailnew(cell.element(), result.rowspan(), result.colspan(), cell.isNew())]; + } else { + return []; + } + }); + return rowdetails(details, row.section()); + }); + }; + var toGrid = function (warehouse, generators, isNew) { + var grid = []; + for (var i = 0; i < warehouse.grid().rows(); i++) { + var rowCells = []; + for (var j = 0; j < warehouse.grid().columns(); j++) { + var element = Warehouse.getAt(warehouse, i, j).map(function (item) { + return elementnew(item.element(), isNew); + }).getOrThunk(function () { + return elementnew(generators.gap(), true); + }); + rowCells.push(element); + } + var row = rowcells(rowCells, warehouse.all()[i].section()); + grid.push(row); + } + return grid; + }; + var Transitions = { + toDetails: toDetails, + toGrid: toGrid + }; + + var fromWarehouse = function (warehouse, generators) { + return Transitions.toGrid(warehouse, generators, false); + }; + var deriveRows = function (rendered, generators) { + var findRow = function (details) { + var rowOfCells = findMap(details, function (detail) { + return parent(detail.element()).map(function (row) { + var isNew = parent(row).isNone(); + return elementnew(row, isNew); + }); + }); + return rowOfCells.getOrThunk(function () { + return elementnew(generators.row(), true); + }); + }; + return map(rendered, function (details) { + var row = findRow(details.details()); + return rowdatanew(row.element(), details.details(), details.section(), row.isNew()); + }); + }; + var toDetailList = function (grid, generators) { + var rendered = Transitions.toDetails(grid, eq); + return deriveRows(rendered, generators); + }; + var findInWarehouse = function (warehouse, element) { + var all = flatten(map(warehouse.all(), function (r) { + return r.cells(); + })); + return find(all, function (e) { + return eq(element, e.element()); + }); + }; + var run = function (operation, extract, adjustment, postAction, genWrappers) { + return function (wire, table, target, generators, direction) { + var input = DetailsList.fromTable(table); + var warehouse = Warehouse.generate(input); + var output = extract(warehouse, target).map(function (info) { + var model = fromWarehouse(warehouse, generators); + var result = operation(model, info, eq, genWrappers(generators)); + var grid = toDetailList(result.grid(), generators); + return { + grid: constant(grid), + cursor: result.cursor + }; + }); + return output.fold(function () { + return Option.none(); + }, function (out) { + var newElements = Redraw.render(table, out.grid()); + adjustment(table, out.grid(), direction); + postAction(table); + Bars.refresh(wire, table, BarPositions.height, direction); + return Option.some({ + cursor: out.cursor, + newRows: newElements.newRows, + newCells: newElements.newCells + }); + }); + }; + }; + var onCell = function (warehouse, target) { + return TableLookup.cell(target.element()).bind(function (cell) { + return findInWarehouse(warehouse, cell); + }); + }; + var onPaste = function (warehouse, target) { + return TableLookup.cell(target.element()).bind(function (cell) { + return findInWarehouse(warehouse, cell).map(function (details) { + var value = __assign(__assign({}, details), { + generators: target.generators, + clipboard: target.clipboard + }); + return value; + }); + }); + }; + var onPasteRows = function (warehouse, target) { + var details = map(target.selection(), function (cell) { + return TableLookup.cell(cell).bind(function (lc) { + return findInWarehouse(warehouse, lc); + }); + }); + var cells = cat(details); + return cells.length > 0 ? Option.some({ + cells: cells, + generators: target.generators, + clipboard: target.clipboard + }) : Option.none(); + }; + var onMergable = function (_warehouse, target) { + return target.mergable(); + }; + var onUnmergable = function (_warehouse, target) { + return target.unmergable(); + }; + var onCells = function (warehouse, target) { + var details = map(target.selection(), function (cell) { + return TableLookup.cell(cell).bind(function (lc) { + return findInWarehouse(warehouse, lc); + }); + }); + var cells = cat(details); + return cells.length > 0 ? Option.some(cells) : Option.none(); + }; + + var value = function (o) { + var is = function (v) { + return o === v; + }; + var or = function (opt) { + return value(o); + }; + var orThunk = function (f) { + return value(o); + }; + var map = function (f) { + return value(f(o)); + }; + var mapError = function (f) { + return value(o); + }; + var each = function (f) { + f(o); + }; + var bind = function (f) { + return f(o); + }; + var fold = function (_, onValue) { + return onValue(o); + }; + var exists = function (f) { + return f(o); + }; + var forall = function (f) { + return f(o); + }; + var toOption = function () { + return Option.some(o); + }; + return { + is: is, + isValue: always, + isError: never, + getOr: constant(o), + getOrThunk: constant(o), + getOrDie: constant(o), + or: or, + orThunk: orThunk, + fold: fold, + map: map, + mapError: mapError, + each: each, + bind: bind, + exists: exists, + forall: forall, + toOption: toOption + }; + }; + var error = function (message) { + var getOrThunk = function (f) { + return f(); + }; + var getOrDie = function () { + return die(String(message))(); + }; + var or = function (opt) { + return opt; + }; + var orThunk = function (f) { + return f(); + }; + var map = function (f) { + return error(message); + }; + var mapError = function (f) { + return error(f(message)); + }; + var bind = function (f) { + return error(message); + }; + var fold = function (onError, _) { + return onError(message); + }; + return { + is: never, + isValue: never, + isError: always, + getOr: identity, + getOrThunk: getOrThunk, + getOrDie: getOrDie, + or: or, + orThunk: orThunk, + fold: fold, + map: map, + mapError: mapError, + each: noop, + bind: bind, + exists: never, + forall: always, + toOption: Option.none + }; + }; + var fromOption = function (opt, err) { + return opt.fold(function () { + return error(err); + }, value); + }; + var Result = { + value: value, + error: error, + fromOption: fromOption + }; + + var measure = function (startAddress, gridA, gridB) { + if (startAddress.row() >= gridA.length || startAddress.column() > GridRow.cellLength(gridA[0])) { + return Result.error('invalid start address out of table bounds, row: ' + startAddress.row() + ', column: ' + startAddress.column()); + } + var rowRemainder = gridA.slice(startAddress.row()); + var colRemainder = rowRemainder[0].cells().slice(startAddress.column()); + var colRequired = GridRow.cellLength(gridB[0]); + var rowRequired = gridB.length; + return Result.value({ + rowDelta: constant(rowRemainder.length - rowRequired), + colDelta: constant(colRemainder.length - colRequired) + }); + }; + var measureWidth = function (gridA, gridB) { + var colLengthA = GridRow.cellLength(gridA[0]); + var colLengthB = GridRow.cellLength(gridB[0]); + return { + rowDelta: constant(0), + colDelta: constant(colLengthA - colLengthB) + }; + }; + var fill = function (cells, generator) { + return map(cells, function () { + return elementnew(generator.cell(), true); + }); + }; + var rowFill = function (grid, amount, generator) { + return grid.concat(repeat(amount, function (_row) { + return GridRow.setCells(grid[grid.length - 1], fill(grid[grid.length - 1].cells(), generator)); + })); + }; + var colFill = function (grid, amount, generator) { + return map(grid, function (row) { + return GridRow.setCells(row, row.cells().concat(fill(range(0, amount), generator))); + }); + }; + var tailor = function (gridA, delta, generator) { + var fillCols = delta.colDelta() < 0 ? colFill : identity; + var fillRows = delta.rowDelta() < 0 ? rowFill : identity; + var modifiedCols = fillCols(gridA, Math.abs(delta.colDelta()), generator); + var tailoredGrid = fillRows(modifiedCols, Math.abs(delta.rowDelta()), generator); + return tailoredGrid; + }; + var Fitment = { + measure: measure, + measureWidth: measureWidth, + tailor: tailor + }; + + var merge = function (grid, bounds, comparator, substitution) { + if (grid.length === 0) { + return grid; + } + for (var i = bounds.startRow(); i <= bounds.finishRow(); i++) { + for (var j = bounds.startCol(); j <= bounds.finishCol(); j++) { + GridRow.mutateCell(grid[i], j, elementnew(substitution(), false)); + } + } + return grid; + }; + var unmerge = function (grid, target, comparator, substitution) { + var first = true; + for (var i = 0; i < grid.length; i++) { + for (var j = 0; j < GridRow.cellLength(grid[0]); j++) { + var current = GridRow.getCellElement(grid[i], j); + var isToReplace = comparator(current, target); + if (isToReplace === true && first === false) { + GridRow.mutateCell(grid[i], j, elementnew(substitution(), true)); + } else if (isToReplace === true) { + first = false; + } + } + } + return grid; + }; + var uniqueCells = function (row, comparator) { + return foldl(row, function (rest, cell) { + return exists(rest, function (currentCell) { + return comparator(currentCell.element(), cell.element()); + }) ? rest : rest.concat([cell]); + }, []); + }; + var splitRows = function (grid, index, comparator, substitution) { + if (index > 0 && index < grid.length) { + var rowPrevCells = grid[index - 1].cells(); + var cells = uniqueCells(rowPrevCells, comparator); + each(cells, function (cell) { + var replacement = Option.none(); + var _loop_1 = function (i) { + var _loop_2 = function (j) { + var current = grid[i].cells()[j]; + var isToReplace = comparator(current.element(), cell.element()); + if (isToReplace) { + if (replacement.isNone()) { + replacement = Option.some(substitution()); + } + replacement.each(function (sub) { + GridRow.mutateCell(grid[i], j, elementnew(sub, true)); + }); + } + }; + for (var j = 0; j < GridRow.cellLength(grid[0]); j++) { + _loop_2(j); + } + }; + for (var i = index; i < grid.length; i++) { + _loop_1(i); + } + }); + } + return grid; + }; + var MergingOperations = { + merge: merge, + unmerge: unmerge, + splitRows: splitRows + }; + + var isSpanning = function (grid, row, col, comparator) { + var candidate = GridRow.getCell(grid[row], col); + var matching = curry(comparator, candidate.element()); + var currentRow = grid[row]; + return grid.length > 1 && GridRow.cellLength(currentRow) > 1 && (col > 0 && matching(GridRow.getCellElement(currentRow, col - 1)) || col < currentRow.cells().length - 1 && matching(GridRow.getCellElement(currentRow, col + 1)) || row > 0 && matching(GridRow.getCellElement(grid[row - 1], col)) || row < grid.length - 1 && matching(GridRow.getCellElement(grid[row + 1], col))); + }; + var mergeTables = function (startAddress, gridA, gridB, generator, comparator) { + var startRow = startAddress.row(); + var startCol = startAddress.column(); + var mergeHeight = gridB.length; + var mergeWidth = GridRow.cellLength(gridB[0]); + var endRow = startRow + mergeHeight; + var endCol = startCol + mergeWidth; + for (var r = startRow; r < endRow; r++) { + for (var c = startCol; c < endCol; c++) { + if (isSpanning(gridA, r, c, comparator)) { + MergingOperations.unmerge(gridA, GridRow.getCellElement(gridA[r], c), comparator, generator.cell); + } + var newCell = GridRow.getCellElement(gridB[r - startRow], c - startCol); + var replacement = generator.replace(newCell); + GridRow.mutateCell(gridA[r], c, elementnew(replacement, true)); + } + } + return gridA; + }; + var merge$1 = function (startAddress, gridA, gridB, generator, comparator) { + var result = Fitment.measure(startAddress, gridA, gridB); + return result.map(function (delta) { + var fittedGrid = Fitment.tailor(gridA, delta, generator); + return mergeTables(startAddress, fittedGrid, gridB, generator, comparator); + }); + }; + var insert = function (index, gridA, gridB, generator, comparator) { + MergingOperations.splitRows(gridA, index, comparator, generator.cell); + var delta = Fitment.measureWidth(gridB, gridA); + var fittedNewGrid = Fitment.tailor(gridB, delta, generator); + var secondDelta = Fitment.measureWidth(gridA, fittedNewGrid); + var fittedOldGrid = Fitment.tailor(gridA, secondDelta, generator); + return fittedOldGrid.slice(0, index).concat(fittedNewGrid).concat(fittedOldGrid.slice(index, fittedOldGrid.length)); + }; + var TableMerge = { + merge: merge$1, + insert: insert + }; + + var insertRowAt = function (grid, index, example, comparator, substitution) { + var before = grid.slice(0, index); + var after = grid.slice(index); + var between = GridRow.mapCells(grid[example], function (ex, c) { + var withinSpan = index > 0 && index < grid.length && comparator(GridRow.getCellElement(grid[index - 1], c), GridRow.getCellElement(grid[index], c)); + var ret = withinSpan ? GridRow.getCell(grid[index], c) : elementnew(substitution(ex.element(), comparator), true); + return ret; + }); + return before.concat([between]).concat(after); + }; + var insertColumnAt = function (grid, index, example, comparator, substitution) { + return map(grid, function (row) { + var withinSpan = index > 0 && index < GridRow.cellLength(row) && comparator(GridRow.getCellElement(row, index - 1), GridRow.getCellElement(row, index)); + var sub = withinSpan ? GridRow.getCell(row, index) : elementnew(substitution(GridRow.getCellElement(row, example), comparator), true); + return GridRow.addCell(row, index, sub); + }); + }; + var splitCellIntoColumns = function (grid, exampleRow, exampleCol, comparator, substitution) { + var index = exampleCol + 1; + return map(grid, function (row, i) { + var isTargetCell = i === exampleRow; + var sub = isTargetCell ? elementnew(substitution(GridRow.getCellElement(row, exampleCol), comparator), true) : GridRow.getCell(row, exampleCol); + return GridRow.addCell(row, index, sub); + }); + }; + var splitCellIntoRows = function (grid, exampleRow, exampleCol, comparator, substitution) { + var index = exampleRow + 1; + var before = grid.slice(0, index); + var after = grid.slice(index); + var between = GridRow.mapCells(grid[exampleRow], function (ex, i) { + var isTargetCell = i === exampleCol; + return isTargetCell ? elementnew(substitution(ex.element(), comparator), true) : ex; + }); + return before.concat([between]).concat(after); + }; + var deleteColumnsAt = function (grid, start, finish) { + var rows = map(grid, function (row) { + var cells = row.cells().slice(0, start).concat(row.cells().slice(finish + 1)); + return rowcells(cells, row.section()); + }); + return filter(rows, function (row) { + return row.cells().length > 0; + }); + }; + var deleteRowsAt = function (grid, start, finish) { + return grid.slice(0, start).concat(grid.slice(finish + 1)); + }; + var ModificationOperations = { + insertRowAt: insertRowAt, + insertColumnAt: insertColumnAt, + splitCellIntoColumns: splitCellIntoColumns, + splitCellIntoRows: splitCellIntoRows, + deleteRowsAt: deleteRowsAt, + deleteColumnsAt: deleteColumnsAt + }; + + var replaceIn = function (grid, targets, comparator, substitution) { + var isTarget = function (cell) { + return exists(targets, function (target) { + return comparator(cell.element(), target.element()); + }); + }; + return map(grid, function (row) { + return GridRow.mapCells(row, function (cell) { + return isTarget(cell) ? elementnew(substitution(cell.element(), comparator), true) : cell; + }); + }); + }; + var notStartRow = function (grid, rowIndex, colIndex, comparator) { + return GridRow.getCellElement(grid[rowIndex], colIndex) !== undefined && (rowIndex > 0 && comparator(GridRow.getCellElement(grid[rowIndex - 1], colIndex), GridRow.getCellElement(grid[rowIndex], colIndex))); + }; + var notStartColumn = function (row, index, comparator) { + return index > 0 && comparator(GridRow.getCellElement(row, index - 1), GridRow.getCellElement(row, index)); + }; + var replaceColumn = function (grid, index, comparator, substitution) { + var targets = bind(grid, function (row, i) { + var alreadyAdded = notStartRow(grid, i, index, comparator) || notStartColumn(row, index, comparator); + return alreadyAdded ? [] : [GridRow.getCell(row, index)]; + }); + return replaceIn(grid, targets, comparator, substitution); + }; + var replaceRow = function (grid, index, comparator, substitution) { + var targetRow = grid[index]; + var targets = bind(targetRow.cells(), function (item, i) { + var alreadyAdded = notStartRow(grid, index, i, comparator) || notStartColumn(targetRow, i, comparator); + return alreadyAdded ? [] : [item]; + }); + return replaceIn(grid, targets, comparator, substitution); + }; + var TransformOperations = { + replaceColumn: replaceColumn, + replaceRow: replaceRow + }; + + var adt = Adt.generate([ + { none: [] }, + { only: ['index'] }, + { + left: [ + 'index', + 'next' + ] + }, + { + middle: [ + 'prev', + 'index', + 'next' + ] + }, + { + right: [ + 'prev', + 'index' + ] + } + ]); + var ColumnContext = __assign({}, adt); + + var neighbours$1 = function (input, index) { + if (input.length === 0) { + return ColumnContext.none(); + } + if (input.length === 1) { + return ColumnContext.only(0); + } + if (index === 0) { + return ColumnContext.left(0, 1); + } + if (index === input.length - 1) { + return ColumnContext.right(index - 1, index); + } + if (index > 0 && index < input.length - 1) { + return ColumnContext.middle(index - 1, index, index + 1); + } + return ColumnContext.none(); + }; + var determine = function (input, column, step, tableSize) { + var result = input.slice(0); + var context = neighbours$1(input, column); + var zero = function (array) { + return map(array, constant(0)); + }; + var onNone = constant(zero(result)); + var onOnly = function (index) { + return tableSize.singleColumnWidth(result[index], step); + }; + var onChange = function (index, next) { + if (step >= 0) { + var newNext = Math.max(tableSize.minCellWidth(), result[next] - step); + return zero(result.slice(0, index)).concat([ + step, + newNext - result[next] + ]).concat(zero(result.slice(next + 1))); + } else { + var newThis = Math.max(tableSize.minCellWidth(), result[index] + step); + var diffx = result[index] - newThis; + return zero(result.slice(0, index)).concat([ + newThis - result[index], + diffx + ]).concat(zero(result.slice(next + 1))); + } + }; + var onLeft = onChange; + var onMiddle = function (_prev, index, next) { + return onChange(index, next); + }; + var onRight = function (_prev, index) { + if (step >= 0) { + return zero(result.slice(0, index)).concat([step]); + } else { + var size = Math.max(tableSize.minCellWidth(), result[index] + step); + return zero(result.slice(0, index)).concat([size - result[index]]); + } + }; + return context.fold(onNone, onOnly, onLeft, onMiddle, onRight); + }; + var Deltas = { determine: determine }; + + var getSpan$1 = function (cell, type) { + return has$1(cell, type) && parseInt(get$1(cell, type), 10) > 1; + }; + var hasColspan = function (cell) { + return getSpan$1(cell, 'colspan'); + }; + var hasRowspan = function (cell) { + return getSpan$1(cell, 'rowspan'); + }; + var getInt = function (element, property) { + return parseInt(get$2(element, property), 10); + }; + var CellUtils = { + hasColspan: hasColspan, + hasRowspan: hasRowspan, + minWidth: constant(10), + minHeight: constant(10), + getInt: getInt + }; + + var getRaw$1 = function (cell, property, getter) { + return getRaw(cell, property).fold(function () { + return getter(cell) + 'px'; + }, function (raw) { + return raw; + }); + }; + var getRawW = function (cell, tableSize) { + return getRaw$1(cell, 'width', function (e) { + return Sizes.getPixelWidth(e, tableSize); + }); + }; + var getRawH = function (cell) { + return getRaw$1(cell, 'height', Sizes.getHeight); + }; + var getWidthFrom = function (warehouse, direction, getWidth, fallback, tableSize) { + var columns = Blocks.columns(warehouse); + var backups = map(columns, function (cellOption) { + return cellOption.map(direction.edge); + }); + return map(columns, function (cellOption, c) { + var columnCell = cellOption.filter(not(CellUtils.hasColspan)); + return columnCell.fold(function () { + var deduced = deduce(backups, c); + return fallback(deduced); + }, function (cell) { + return getWidth(cell, tableSize); + }); + }); + }; + var getDeduced = function (deduced) { + return deduced.map(function (d) { + return d + 'px'; + }).getOr(''); + }; + var getRawWidths = function (warehouse, direction, tableSize) { + return getWidthFrom(warehouse, direction, getRawW, getDeduced, tableSize); + }; + var getPercentageWidths = function (warehouse, direction, tableSize) { + return getWidthFrom(warehouse, direction, Sizes.getPercentageWidth, function (deduced) { + return deduced.fold(function () { + return tableSize.minCellWidth(); + }, function (cellWidth) { + return cellWidth / tableSize.pixelWidth() * 100; + }); + }, tableSize); + }; + var getPixelWidths = function (warehouse, direction, tableSize) { + return getWidthFrom(warehouse, direction, Sizes.getPixelWidth, function (deduced) { + return deduced.getOrThunk(tableSize.minCellWidth); + }, tableSize); + }; + var getHeightFrom = function (warehouse, direction, getHeight, fallback) { + var rows = Blocks.rows(warehouse); + var backups = map(rows, function (cellOption) { + return cellOption.map(direction.edge); + }); + return map(rows, function (cellOption, c) { + var rowCell = cellOption.filter(not(CellUtils.hasRowspan)); + return rowCell.fold(function () { + var deduced = deduce(backups, c); + return fallback(deduced); + }, function (cell) { + return getHeight(cell); + }); + }); + }; + var getPixelHeights = function (warehouse, direction) { + return getHeightFrom(warehouse, direction, Sizes.getHeight, function (deduced) { + return deduced.getOrThunk(CellUtils.minHeight); + }); + }; + var getRawHeights = function (warehouse, direction) { + return getHeightFrom(warehouse, direction, getRawH, getDeduced); + }; + var ColumnSizes = { + getRawWidths: getRawWidths, + getPixelWidths: getPixelWidths, + getPercentageWidths: getPercentageWidths, + getPixelHeights: getPixelHeights, + getRawHeights: getRawHeights + }; + + var total = function (start, end, measures) { + var r = 0; + for (var i = start; i < end; i++) { + r += measures[i] !== undefined ? measures[i] : 0; + } + return r; + }; + var recalculateWidth = function (warehouse, widths) { + var all = Warehouse.justCells(warehouse); + return map(all, function (cell) { + var width = total(cell.column(), cell.column() + cell.colspan(), widths); + return { + element: cell.element, + width: constant(width), + colspan: cell.colspan + }; + }); + }; + var recalculateHeight = function (warehouse, heights) { + var all = Warehouse.justCells(warehouse); + return map(all, function (cell) { + var height = total(cell.row(), cell.row() + cell.rowspan(), heights); + return { + element: cell.element, + height: constant(height), + rowspan: cell.rowspan + }; + }); + }; + var matchRowHeight = function (warehouse, heights) { + return map(warehouse.all(), function (row, i) { + return { + element: row.element, + height: constant(heights[i]) + }; + }); + }; + var Recalculations = { + recalculateWidth: recalculateWidth, + recalculateHeight: recalculateHeight, + matchRowHeight: matchRowHeight + }; + + var percentageSize = function (width, element) { + var floatWidth = parseFloat(width); + var pixelWidth = get$5(element); + var getCellDelta = function (delta) { + return delta / pixelWidth * 100; + }; + var singleColumnWidth = function (w, _delta) { + return [100 - w]; + }; + var minCellWidth = function () { + return CellUtils.minWidth() / pixelWidth * 100; + }; + var setTableWidth = function (table, _newWidths, delta) { + var ratio = delta / 100; + var change = ratio * floatWidth; + Sizes.setPercentageWidth(table, floatWidth + change); + }; + return { + width: constant(floatWidth), + pixelWidth: constant(pixelWidth), + getWidths: ColumnSizes.getPercentageWidths, + getCellDelta: getCellDelta, + singleColumnWidth: singleColumnWidth, + minCellWidth: minCellWidth, + setElementWidth: Sizes.setPercentageWidth, + setTableWidth: setTableWidth + }; + }; + var pixelSize = function (width) { + var getCellDelta = identity; + var singleColumnWidth = function (w, delta) { + var newNext = Math.max(CellUtils.minWidth(), w + delta); + return [newNext - w]; + }; + var setTableWidth = function (table, newWidths, _delta) { + var total = foldr(newWidths, function (b, a) { + return b + a; + }, 0); + Sizes.setPixelWidth(table, total); + }; + return { + width: constant(width), + pixelWidth: constant(width), + getWidths: ColumnSizes.getPixelWidths, + getCellDelta: getCellDelta, + singleColumnWidth: singleColumnWidth, + minCellWidth: CellUtils.minWidth, + setElementWidth: Sizes.setPixelWidth, + setTableWidth: setTableWidth + }; + }; + var chooseSize = function (element, width) { + var percentMatch = Sizes.percentageBasedSizeRegex().exec(width); + if (percentMatch !== null) { + return percentageSize(percentMatch[1], element); + } + var pixelMatch = Sizes.pixelBasedSizeRegex().exec(width); + if (pixelMatch !== null) { + var intWidth = parseInt(pixelMatch[1], 10); + return pixelSize(intWidth); + } + var fallbackWidth = get$5(element); + return pixelSize(fallbackWidth); + }; + var getTableSize = function (element) { + var width = Sizes.getRawWidth(element); + return width.fold(function () { + var fallbackWidth = get$5(element); + return pixelSize(fallbackWidth); + }, function (w) { + return chooseSize(element, w); + }); + }; + var TableSize = { getTableSize: getTableSize }; + + var getWarehouse$1 = function (list) { + return Warehouse.generate(list); + }; + var sumUp = function (newSize) { + return foldr(newSize, function (b, a) { + return b + a; + }, 0); + }; + var getTableWarehouse = function (table) { + var list = DetailsList.fromTable(table); + return getWarehouse$1(list); + }; + var adjustWidth = function (table, delta, index, direction) { + var tableSize = TableSize.getTableSize(table); + var step = tableSize.getCellDelta(delta); + var warehouse = getTableWarehouse(table); + var widths = tableSize.getWidths(warehouse, direction, tableSize); + var deltas = Deltas.determine(widths, index, step, tableSize); + var newWidths = map(deltas, function (dx, i) { + return dx + widths[i]; + }); + var newSizes = Recalculations.recalculateWidth(warehouse, newWidths); + each(newSizes, function (cell) { + tableSize.setElementWidth(cell.element(), cell.width()); + }); + if (index === warehouse.grid().columns() - 1) { + tableSize.setTableWidth(table, newWidths, step); + } + }; + var adjustHeight = function (table, delta, index, direction) { + var warehouse = getTableWarehouse(table); + var heights = ColumnSizes.getPixelHeights(warehouse, direction); + var newHeights = map(heights, function (dy, i) { + return index === i ? Math.max(delta + dy, CellUtils.minHeight()) : dy; + }); + var newCellSizes = Recalculations.recalculateHeight(warehouse, newHeights); + var newRowSizes = Recalculations.matchRowHeight(warehouse, newHeights); + each(newRowSizes, function (row) { + Sizes.setHeight(row.element(), row.height()); + }); + each(newCellSizes, function (cell) { + Sizes.setHeight(cell.element(), cell.height()); + }); + var total = sumUp(newHeights); + Sizes.setHeight(table, total); + }; + var adjustWidthTo = function (table, list, direction) { + var tableSize = TableSize.getTableSize(table); + var warehouse = getWarehouse$1(list); + var widths = tableSize.getWidths(warehouse, direction, tableSize); + var newSizes = Recalculations.recalculateWidth(warehouse, widths); + each(newSizes, function (cell) { + tableSize.setElementWidth(cell.element(), cell.width()); + }); + if (newSizes.length > 0) { + tableSize.setTableWidth(table, widths, tableSize.getCellDelta(0)); + } + }; + var Adjustments = { + adjustWidth: adjustWidth, + adjustHeight: adjustHeight, + adjustWidthTo: adjustWidthTo + }; + + var base = function (handleUnsupported, required) { + return baseWith(handleUnsupported, required, { + validate: isFunction, + label: 'function' + }); + }; + var baseWith = function (handleUnsupported, required, pred) { + if (required.length === 0) { + throw new Error('You must specify at least one required field.'); + } + validateStrArr('required', required); + checkDupes(required); + return function (obj) { + var keys$1 = keys(obj); + var allReqd = forall(required, function (req) { + return contains(keys$1, req); + }); + if (!allReqd) { + reqMessage(required, keys$1); + } + handleUnsupported(required, keys$1); + var invalidKeys = filter(required, function (key) { + return !pred.validate(obj[key], key); + }); + if (invalidKeys.length > 0) { + invalidTypeMessage(invalidKeys, pred.label); + } + return obj; + }; + }; + var handleExact = function (required, keys) { + var unsupported = filter(keys, function (key) { + return !contains(required, key); + }); + if (unsupported.length > 0) { + unsuppMessage(unsupported); + } + }; + var exactly = function (required) { + return base(handleExact, required); + }; + + var verifyGenerators = exactly([ + 'cell', + 'row', + 'replace', + 'gap' + ]); + var elementToData = function (element) { + var colspan = has$1(element, 'colspan') ? parseInt(get$1(element, 'colspan'), 10) : 1; + var rowspan = has$1(element, 'rowspan') ? parseInt(get$1(element, 'rowspan'), 10) : 1; + return { + element: constant(element), + colspan: constant(colspan), + rowspan: constant(rowspan) + }; + }; + var modification = function (generators, toData) { + if (toData === void 0) { + toData = elementToData; + } + verifyGenerators(generators); + var position = Cell(Option.none()); + var nu = function (data) { + return generators.cell(data); + }; + var nuFrom = function (element) { + var data = toData(element); + return nu(data); + }; + var add = function (element) { + var replacement = nuFrom(element); + if (position.get().isNone()) { + position.set(Option.some(replacement)); + } + recent = Option.some({ + item: element, + replacement: replacement + }); + return replacement; + }; + var recent = Option.none(); + var getOrInit = function (element, comparator) { + return recent.fold(function () { + return add(element); + }, function (p) { + return comparator(element, p.item) ? p.replacement : add(element); + }); + }; + return { + getOrInit: getOrInit, + cursor: position.get + }; + }; + var transform = function (scope, tag) { + return function (generators) { + var position = Cell(Option.none()); + verifyGenerators(generators); + var list = []; + var find$1 = function (element, comparator) { + return find(list, function (x) { + return comparator(x.item, element); + }); + }; + var makeNew = function (element) { + var attrs = { scope: scope }; + var cell = generators.replace(element, tag, attrs); + list.push({ + item: element, + sub: cell + }); + if (position.get().isNone()) { + position.set(Option.some(cell)); + } + return cell; + }; + var replaceOrInit = function (element, comparator) { + return find$1(element, comparator).fold(function () { + return makeNew(element); + }, function (p) { + return comparator(element, p.item) ? p.sub : makeNew(element); + }); + }; + return { + replaceOrInit: replaceOrInit, + cursor: position.get + }; + }; + }; + var merging = function (generators) { + verifyGenerators(generators); + var position = Cell(Option.none()); + var combine = function (cell) { + if (position.get().isNone()) { + position.set(Option.some(cell)); + } + return function () { + var raw = generators.cell({ + element: constant(cell), + colspan: constant(1), + rowspan: constant(1) + }); + remove$1(raw, 'width'); + remove$1(cell, 'width'); + return raw; + }; + }; + return { + combine: combine, + cursor: position.get + }; + }; + var Generators = { + modification: modification, + transform: transform, + merging: merging + }; + + var blockList = [ + 'body', + 'p', + 'div', + 'article', + 'aside', + 'figcaption', + 'figure', + 'footer', + 'header', + 'nav', + 'section', + 'ol', + 'ul', + 'table', + 'thead', + 'tfoot', + 'tbody', + 'caption', + 'tr', + 'td', + 'th', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'blockquote', + 'pre', + 'address' + ]; + var isList = function (universe, item) { + var tagName = universe.property().name(item); + return contains([ + 'ol', + 'ul' + ], tagName); + }; + var isBlock = function (universe, item) { + var tagName = universe.property().name(item); + return contains(blockList, tagName); + }; + var isFormatting = function (universe, item) { + var tagName = universe.property().name(item); + return contains([ + 'address', + 'pre', + 'p', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6' + ], tagName); + }; + var isHeading = function (universe, item) { + var tagName = universe.property().name(item); + return contains([ + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6' + ], tagName); + }; + var isContainer = function (universe, item) { + return contains([ + 'div', + 'li', + 'td', + 'th', + 'blockquote', + 'body', + 'caption' + ], universe.property().name(item)); + }; + var isEmptyTag = function (universe, item) { + return contains([ + 'br', + 'img', + 'hr', + 'input' + ], universe.property().name(item)); + }; + var isFrame = function (universe, item) { + return universe.property().name(item) === 'iframe'; + }; + var isInline = function (universe, item) { + return !(isBlock(universe, item) || isEmptyTag(universe, item)) && universe.property().name(item) !== 'li'; + }; + var Structure = { + isBlock: isBlock, + isList: isList, + isFormatting: isFormatting, + isHeading: isHeading, + isContainer: isContainer, + isEmptyTag: isEmptyTag, + isFrame: isFrame, + isInline: isInline + }; + + var universe$1 = DomUniverse(); + var isBlock$1 = function (element) { + return Structure.isBlock(universe$1, element); + }; + var isList$1 = function (element) { + return Structure.isList(universe$1, element); + }; + var isFormatting$1 = function (element) { + return Structure.isFormatting(universe$1, element); + }; + var isHeading$1 = function (element) { + return Structure.isHeading(universe$1, element); + }; + var isContainer$1 = function (element) { + return Structure.isContainer(universe$1, element); + }; + var isEmptyTag$1 = function (element) { + return Structure.isEmptyTag(universe$1, element); + }; + var isFrame$1 = function (element) { + return Structure.isFrame(universe$1, element); + }; + var isInline$1 = function (element) { + return Structure.isInline(universe$1, element); + }; + var DomStructure = { + isBlock: isBlock$1, + isList: isList$1, + isFormatting: isFormatting$1, + isHeading: isHeading$1, + isContainer: isContainer$1, + isEmptyTag: isEmptyTag$1, + isFrame: isFrame$1, + isInline: isInline$1 + }; + + var merge$2 = function (cells) { + var isBr = function (el) { + return name(el) === 'br'; + }; + var advancedBr = function (children) { + return forall(children, function (c) { + return isBr(c) || isText(c) && get$3(c).trim().length === 0; + }); + }; + var isListItem = function (el) { + return name(el) === 'li' || ancestor(el, DomStructure.isList).isSome(); + }; + var siblingIsBlock = function (el) { + return nextSibling(el).map(function (rightSibling) { + if (DomStructure.isBlock(rightSibling)) { + return true; + } + if (DomStructure.isEmptyTag(rightSibling)) { + return name(rightSibling) === 'img' ? false : true; + } + return false; + }).getOr(false); + }; + var markCell = function (cell) { + return last$1(cell).bind(function (rightEdge) { + var rightSiblingIsBlock = siblingIsBlock(rightEdge); + return parent(rightEdge).map(function (parent) { + return rightSiblingIsBlock === true || isListItem(parent) || isBr(rightEdge) || DomStructure.isBlock(parent) && !eq(cell, parent) ? [] : [Element.fromTag('br')]; + }); + }).getOr([]); + }; + var markContent = function () { + var content = bind(cells, function (cell) { + var children$1 = children(cell); + return advancedBr(children$1) ? [] : children$1.concat(markCell(cell)); + }); + return content.length === 0 ? [Element.fromTag('br')] : content; + }; + var contents = markContent(); + empty(cells[0]); + append$1(cells[0], contents); + }; + var TableContent = { merge: merge$2 }; + + var prune = function (table) { + var cells = TableLookup.cells(table); + if (cells.length === 0) { + remove$2(table); + } + }; + var outcome = Immutable('grid', 'cursor'); + var elementFromGrid = function (grid, row, column) { + return findIn(grid, row, column).orThunk(function () { + return findIn(grid, 0, 0); + }); + }; + var findIn = function (grid, row, column) { + return Option.from(grid[row]).bind(function (r) { + return Option.from(r.cells()[column]).bind(function (c) { + return Option.from(c.element()); + }); + }); + }; + var bundle = function (grid, row, column) { + return outcome(grid, findIn(grid, row, column)); + }; + var uniqueRows = function (details) { + return foldl(details, function (rest, detail) { + return exists(rest, function (currentDetail) { + return currentDetail.row() === detail.row(); + }) ? rest : rest.concat([detail]); + }, []).sort(function (detailA, detailB) { + return detailA.row() - detailB.row(); + }); + }; + var uniqueColumns = function (details) { + return foldl(details, function (rest, detail) { + return exists(rest, function (currentDetail) { + return currentDetail.column() === detail.column(); + }) ? rest : rest.concat([detail]); + }, []).sort(function (detailA, detailB) { + return detailA.column() - detailB.column(); + }); + }; + var insertRowBefore = function (grid, detail, comparator, genWrappers) { + var example = detail.row(); + var targetIndex = detail.row(); + var newGrid = ModificationOperations.insertRowAt(grid, targetIndex, example, comparator, genWrappers.getOrInit); + return bundle(newGrid, targetIndex, detail.column()); + }; + var insertRowsBefore = function (grid, details, comparator, genWrappers) { + var example = details[0].row(); + var targetIndex = details[0].row(); + var rows = uniqueRows(details); + var newGrid = foldl(rows, function (newG, _row) { + return ModificationOperations.insertRowAt(newG, targetIndex, example, comparator, genWrappers.getOrInit); + }, grid); + return bundle(newGrid, targetIndex, details[0].column()); + }; + var insertRowAfter = function (grid, detail, comparator, genWrappers) { + var example = detail.row(); + var targetIndex = detail.row() + detail.rowspan(); + var newGrid = ModificationOperations.insertRowAt(grid, targetIndex, example, comparator, genWrappers.getOrInit); + return bundle(newGrid, targetIndex, detail.column()); + }; + var insertRowsAfter = function (grid, details, comparator, genWrappers) { + var rows = uniqueRows(details); + var example = rows[rows.length - 1].row(); + var targetIndex = rows[rows.length - 1].row() + rows[rows.length - 1].rowspan(); + var newGrid = foldl(rows, function (newG, _row) { + return ModificationOperations.insertRowAt(newG, targetIndex, example, comparator, genWrappers.getOrInit); + }, grid); + return bundle(newGrid, targetIndex, details[0].column()); + }; + var insertColumnBefore = function (grid, detail, comparator, genWrappers) { + var example = detail.column(); + var targetIndex = detail.column(); + var newGrid = ModificationOperations.insertColumnAt(grid, targetIndex, example, comparator, genWrappers.getOrInit); + return bundle(newGrid, detail.row(), targetIndex); + }; + var insertColumnsBefore = function (grid, details, comparator, genWrappers) { + var columns = uniqueColumns(details); + var example = columns[0].column(); + var targetIndex = columns[0].column(); + var newGrid = foldl(columns, function (newG, _row) { + return ModificationOperations.insertColumnAt(newG, targetIndex, example, comparator, genWrappers.getOrInit); + }, grid); + return bundle(newGrid, details[0].row(), targetIndex); + }; + var insertColumnAfter = function (grid, detail, comparator, genWrappers) { + var example = detail.column(); + var targetIndex = detail.column() + detail.colspan(); + var newGrid = ModificationOperations.insertColumnAt(grid, targetIndex, example, comparator, genWrappers.getOrInit); + return bundle(newGrid, detail.row(), targetIndex); + }; + var insertColumnsAfter = function (grid, details, comparator, genWrappers) { + var example = details[details.length - 1].column(); + var targetIndex = details[details.length - 1].column() + details[details.length - 1].colspan(); + var columns = uniqueColumns(details); + var newGrid = foldl(columns, function (newG, _row) { + return ModificationOperations.insertColumnAt(newG, targetIndex, example, comparator, genWrappers.getOrInit); + }, grid); + return bundle(newGrid, details[0].row(), targetIndex); + }; + var makeRowHeader = function (grid, detail, comparator, genWrappers) { + var newGrid = TransformOperations.replaceRow(grid, detail.row(), comparator, genWrappers.replaceOrInit); + return bundle(newGrid, detail.row(), detail.column()); + }; + var makeColumnHeader = function (grid, detail, comparator, genWrappers) { + var newGrid = TransformOperations.replaceColumn(grid, detail.column(), comparator, genWrappers.replaceOrInit); + return bundle(newGrid, detail.row(), detail.column()); + }; + var unmakeRowHeader = function (grid, detail, comparator, genWrappers) { + var newGrid = TransformOperations.replaceRow(grid, detail.row(), comparator, genWrappers.replaceOrInit); + return bundle(newGrid, detail.row(), detail.column()); + }; + var unmakeColumnHeader = function (grid, detail, comparator, genWrappers) { + var newGrid = TransformOperations.replaceColumn(grid, detail.column(), comparator, genWrappers.replaceOrInit); + return bundle(newGrid, detail.row(), detail.column()); + }; + var splitCellIntoColumns$1 = function (grid, detail, comparator, genWrappers) { + var newGrid = ModificationOperations.splitCellIntoColumns(grid, detail.row(), detail.column(), comparator, genWrappers.getOrInit); + return bundle(newGrid, detail.row(), detail.column()); + }; + var splitCellIntoRows$1 = function (grid, detail, comparator, genWrappers) { + var newGrid = ModificationOperations.splitCellIntoRows(grid, detail.row(), detail.column(), comparator, genWrappers.getOrInit); + return bundle(newGrid, detail.row(), detail.column()); + }; + var eraseColumns = function (grid, details, _comparator, _genWrappers) { + var columns = uniqueColumns(details); + var newGrid = ModificationOperations.deleteColumnsAt(grid, columns[0].column(), columns[columns.length - 1].column()); + var cursor = elementFromGrid(newGrid, details[0].row(), details[0].column()); + return outcome(newGrid, cursor); + }; + var eraseRows = function (grid, details, _comparator, _genWrappers) { + var rows = uniqueRows(details); + var newGrid = ModificationOperations.deleteRowsAt(grid, rows[0].row(), rows[rows.length - 1].row()); + var cursor = elementFromGrid(newGrid, details[0].row(), details[0].column()); + return outcome(newGrid, cursor); + }; + var mergeCells = function (grid, mergable, comparator, _genWrappers) { + var cells = mergable.cells(); + TableContent.merge(cells); + var newGrid = MergingOperations.merge(grid, mergable.bounds(), comparator, constant(cells[0])); + return outcome(newGrid, Option.from(cells[0])); + }; + var unmergeCells = function (grid, unmergable, comparator, genWrappers) { + var newGrid = foldr(unmergable, function (b, cell) { + return MergingOperations.unmerge(b, cell, comparator, genWrappers.combine(cell)); + }, grid); + return outcome(newGrid, Option.from(unmergable[0])); + }; + var pasteCells = function (grid, pasteDetails, comparator, _genWrappers) { + var gridify = function (table, generators) { + var list = DetailsList.fromTable(table); + var wh = Warehouse.generate(list); + return Transitions.toGrid(wh, generators, true); + }; + var gridB = gridify(pasteDetails.clipboard(), pasteDetails.generators()); + var startAddress = address(pasteDetails.row(), pasteDetails.column()); + var mergedGrid = TableMerge.merge(startAddress, grid, gridB, pasteDetails.generators(), comparator); + return mergedGrid.fold(function () { + return outcome(grid, Option.some(pasteDetails.element())); + }, function (nuGrid) { + var cursor = elementFromGrid(nuGrid, pasteDetails.row(), pasteDetails.column()); + return outcome(nuGrid, cursor); + }); + }; + var gridifyRows = function (rows, generators, example) { + var pasteDetails = DetailsList.fromPastedRows(rows, example); + var wh = Warehouse.generate(pasteDetails); + return Transitions.toGrid(wh, generators, true); + }; + var pasteRowsBefore = function (grid, pasteDetails, comparator, _genWrappers) { + var example = grid[pasteDetails.cells[0].row()]; + var index = pasteDetails.cells[0].row(); + var gridB = gridifyRows(pasteDetails.clipboard(), pasteDetails.generators(), example); + var mergedGrid = TableMerge.insert(index, grid, gridB, pasteDetails.generators(), comparator); + var cursor = elementFromGrid(mergedGrid, pasteDetails.cells[0].row(), pasteDetails.cells[0].column()); + return outcome(mergedGrid, cursor); + }; + var pasteRowsAfter = function (grid, pasteDetails, comparator, _genWrappers) { + var example = grid[pasteDetails.cells[0].row()]; + var index = pasteDetails.cells[pasteDetails.cells.length - 1].row() + pasteDetails.cells[pasteDetails.cells.length - 1].rowspan(); + var gridB = gridifyRows(pasteDetails.clipboard(), pasteDetails.generators(), example); + var mergedGrid = TableMerge.insert(index, grid, gridB, pasteDetails.generators(), comparator); + var cursor = elementFromGrid(mergedGrid, pasteDetails.cells[0].row(), pasteDetails.cells[0].column()); + return outcome(mergedGrid, cursor); + }; + var resize = Adjustments.adjustWidthTo; + var TableOperations = { + insertRowBefore: run(insertRowBefore, onCell, noop, noop, Generators.modification), + insertRowsBefore: run(insertRowsBefore, onCells, noop, noop, Generators.modification), + insertRowAfter: run(insertRowAfter, onCell, noop, noop, Generators.modification), + insertRowsAfter: run(insertRowsAfter, onCells, noop, noop, Generators.modification), + insertColumnBefore: run(insertColumnBefore, onCell, resize, noop, Generators.modification), + insertColumnsBefore: run(insertColumnsBefore, onCells, resize, noop, Generators.modification), + insertColumnAfter: run(insertColumnAfter, onCell, resize, noop, Generators.modification), + insertColumnsAfter: run(insertColumnsAfter, onCells, resize, noop, Generators.modification), + splitCellIntoColumns: run(splitCellIntoColumns$1, onCell, resize, noop, Generators.modification), + splitCellIntoRows: run(splitCellIntoRows$1, onCell, noop, noop, Generators.modification), + eraseColumns: run(eraseColumns, onCells, resize, prune, Generators.modification), + eraseRows: run(eraseRows, onCells, noop, prune, Generators.modification), + makeColumnHeader: run(makeColumnHeader, onCell, noop, noop, Generators.transform('row', 'th')), + unmakeColumnHeader: run(unmakeColumnHeader, onCell, noop, noop, Generators.transform(null, 'td')), + makeRowHeader: run(makeRowHeader, onCell, noop, noop, Generators.transform('col', 'th')), + unmakeRowHeader: run(unmakeRowHeader, onCell, noop, noop, Generators.transform(null, 'td')), + mergeCells: run(mergeCells, onMergable, noop, noop, Generators.merging), + unmergeCells: run(unmergeCells, onUnmergable, resize, noop, Generators.merging), + pasteCells: run(pasteCells, onPaste, resize, noop, Generators.modification), + pasteRowsBefore: run(pasteRowsBefore, onPasteRows, noop, noop, Generators.modification), + pasteRowsAfter: run(pasteRowsAfter, onPasteRows, noop, noop, Generators.modification) + }; + + var getBody$1 = function (editor) { + return Element.fromDom(editor.getBody()); + }; + var getPixelWidth$1 = function (elm) { + return elm.getBoundingClientRect().width; + }; + var getPixelHeight = function (elm) { + return elm.getBoundingClientRect().height; + }; + var getIsRoot = function (editor) { + return function (element) { + return eq(element, getBody$1(editor)); + }; + }; + var removePxSuffix = function (size) { + return size ? size.replace(/px$/, '') : ''; + }; + var addSizeSuffix = function (size) { + if (/^[0-9]+$/.test(size)) { + size += 'px'; + } + return size; + }; + var removeDataStyle = function (table) { + var dataStyleCells = descendants$1(table, 'td[data-mce-style],th[data-mce-style]'); + remove(table, 'data-mce-style'); + each(dataStyleCells, function (cell) { + remove(cell, 'data-mce-style'); + }); + }; + + var getDirection = function (element) { + return get$2(element, 'direction') === 'rtl' ? 'rtl' : 'ltr'; + }; + + var ltr$1 = { isRtl: constant(false) }; + var rtl$1 = { isRtl: constant(true) }; + var directionAt = function (element) { + var dir = getDirection(element); + return dir === 'rtl' ? rtl$1 : ltr$1; + }; + var Direction = { directionAt: directionAt }; + + var defaultTableToolbar = 'tableprops tabledelete | tableinsertrowbefore tableinsertrowafter tabledeleterow | tableinsertcolbefore tableinsertcolafter tabledeletecol'; + var defaultStyles = { + 'border-collapse': 'collapse', + 'width': '100%' + }; + var defaultAttributes = { border: '1' }; + var getDefaultAttributes = function (editor) { + return editor.getParam('table_default_attributes', defaultAttributes, 'object'); + }; + var getDefaultStyles = function (editor) { + return editor.getParam('table_default_styles', defaultStyles, 'object'); + }; + var hasTableResizeBars = function (editor) { + return editor.getParam('table_resize_bars', true, 'boolean'); + }; + var hasTabNavigation = function (editor) { + return editor.getParam('table_tab_navigation', true, 'boolean'); + }; + var hasAdvancedCellTab = function (editor) { + return editor.getParam('table_cell_advtab', true, 'boolean'); + }; + var hasAdvancedRowTab = function (editor) { + return editor.getParam('table_row_advtab', true, 'boolean'); + }; + var hasAdvancedTableTab = function (editor) { + return editor.getParam('table_advtab', true, 'boolean'); + }; + var hasAppearanceOptions = function (editor) { + return editor.getParam('table_appearance_options', true, 'boolean'); + }; + var hasTableGrid = function (editor) { + return editor.getParam('table_grid', true, 'boolean'); + }; + var shouldStyleWithCss = function (editor) { + return editor.getParam('table_style_by_css', false, 'boolean'); + }; + var getCellClassList = function (editor) { + return editor.getParam('table_cell_class_list', [], 'array'); + }; + var getRowClassList = function (editor) { + return editor.getParam('table_row_class_list', [], 'array'); + }; + var getTableClassList = function (editor) { + return editor.getParam('table_class_list', [], 'array'); + }; + var isPercentagesForced = function (editor) { + return editor.getParam('table_responsive_width') === true; + }; + var isPixelsForced = function (editor) { + return editor.getParam('table_responsive_width') === false; + }; + var getToolbar = function (editor) { + return editor.getParam('table_toolbar', defaultTableToolbar); + }; + var getCloneElements = function (editor) { + var cloneElements = editor.getParam('table_clone_elements'); + if (isString(cloneElements)) { + return Option.some(cloneElements.split(/[ ,]/)); + } else if (Array.isArray(cloneElements)) { + return Option.some(cloneElements); + } else { + return Option.none(); + } + }; + var hasObjectResizing = function (editor) { + var objectResizing = editor.getParam('object_resizing', true); + return isString(objectResizing) ? objectResizing === 'table' : objectResizing; + }; + + var fireNewRow = function (editor, row) { + return editor.fire('newrow', { node: row }); + }; + var fireNewCell = function (editor, cell) { + return editor.fire('newcell', { node: cell }); + }; + var fireObjectResizeStart = function (editor, target, width, height) { + editor.fire('ObjectResizeStart', { + target: target, + width: width, + height: height + }); + }; + var fireObjectResized = function (editor, target, width, height) { + editor.fire('ObjectResized', { + target: target, + width: width, + height: height + }); + }; + var fireTableSelectionChange = function (editor, cells, start, finish, otherCells) { + editor.fire('TableSelectionChange', { + cells: cells, + start: start, + finish: finish, + otherCells: otherCells + }); + }; + var fireTableSelectionClear = function (editor) { + editor.fire('TableSelectionClear'); + }; + + var TableActions = function (editor, lazyWire) { + var isTableBody = function (editor) { + return name(getBody$1(editor)) === 'table'; + }; + var lastRowGuard = function (table) { + var size = TableGridSize.getGridSize(table); + return isTableBody(editor) === false || size.rows() > 1; + }; + var lastColumnGuard = function (table) { + var size = TableGridSize.getGridSize(table); + return isTableBody(editor) === false || size.columns() > 1; + }; + var cloneFormats = getCloneElements(editor); + var execute = function (operation, guard, mutate, lazyWire) { + return function (table, target) { + removeDataStyle(table); + var wire = lazyWire(); + var doc = Element.fromDom(editor.getDoc()); + var direction = TableDirection(Direction.directionAt); + var generators = TableFill.cellOperations(mutate, doc, cloneFormats); + return guard(table) ? operation(wire, table, target, generators, direction).bind(function (result) { + each(result.newRows(), function (row) { + fireNewRow(editor, row.dom()); + }); + each(result.newCells(), function (cell) { + fireNewCell(editor, cell.dom()); + }); + return result.cursor().map(function (cell) { + var rng = editor.dom.createRng(); + rng.setStart(cell.dom(), 0); + rng.setEnd(cell.dom(), 0); + return rng; + }); + }) : Option.none(); + }; + }; + var deleteRow = execute(TableOperations.eraseRows, lastRowGuard, noop, lazyWire); + var deleteColumn = execute(TableOperations.eraseColumns, lastColumnGuard, noop, lazyWire); + var insertRowsBefore = execute(TableOperations.insertRowsBefore, always, noop, lazyWire); + var insertRowsAfter = execute(TableOperations.insertRowsAfter, always, noop, lazyWire); + var insertColumnsBefore = execute(TableOperations.insertColumnsBefore, always, CellMutations.halve, lazyWire); + var insertColumnsAfter = execute(TableOperations.insertColumnsAfter, always, CellMutations.halve, lazyWire); + var mergeCells = execute(TableOperations.mergeCells, always, noop, lazyWire); + var unmergeCells = execute(TableOperations.unmergeCells, always, noop, lazyWire); + var pasteRowsBefore = execute(TableOperations.pasteRowsBefore, always, noop, lazyWire); + var pasteRowsAfter = execute(TableOperations.pasteRowsAfter, always, noop, lazyWire); + var pasteCells = execute(TableOperations.pasteCells, always, noop, lazyWire); + return { + deleteRow: deleteRow, + deleteColumn: deleteColumn, + insertRowsBefore: insertRowsBefore, + insertRowsAfter: insertRowsAfter, + insertColumnsBefore: insertColumnsBefore, + insertColumnsAfter: insertColumnsAfter, + mergeCells: mergeCells, + unmergeCells: unmergeCells, + pasteRowsBefore: pasteRowsBefore, + pasteRowsAfter: pasteRowsAfter, + pasteCells: pasteCells + }; + }; + + var copyRows = function (table, target, generators) { + var list = DetailsList.fromTable(table); + var house = Warehouse.generate(list); + var details = onCells(house, target); + return details.map(function (selectedCells) { + var grid = Transitions.toGrid(house, generators, false); + var slicedGrid = grid.slice(selectedCells[0].row(), selectedCells[selectedCells.length - 1].row() + selectedCells[selectedCells.length - 1].rowspan()); + var slicedDetails = toDetailList(slicedGrid, generators); + return Redraw.copy(slicedDetails); + }); + }; + var CopyRows = { copyRows: copyRows }; + + var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + + var getTDTHOverallStyle = function (dom, elm, name) { + var cells = dom.select('td,th', elm); + var firstChildStyle; + var checkChildren = function (firstChildStyle, elms) { + for (var i = 0; i < elms.length; i++) { + var currentStyle = dom.getStyle(elms[i], name); + if (typeof firstChildStyle === 'undefined') { + firstChildStyle = currentStyle; + } + if (firstChildStyle !== currentStyle) { + return ''; + } + } + return firstChildStyle; + }; + firstChildStyle = checkChildren(firstChildStyle, cells); + return firstChildStyle; + }; + var applyAlign = function (editor, elm, name) { + if (name) { + editor.formatter.apply('align' + name, {}, elm); + } + }; + var applyVAlign = function (editor, elm, name) { + if (name) { + editor.formatter.apply('valign' + name, {}, elm); + } + }; + var unApplyAlign = function (editor, elm) { + global$1.each('left center right'.split(' '), function (name) { + editor.formatter.remove('align' + name, {}, elm); + }); + }; + var unApplyVAlign = function (editor, elm) { + global$1.each('top middle bottom'.split(' '), function (name) { + editor.formatter.remove('valign' + name, {}, elm); + }); + }; + var Styles$1 = { + applyAlign: applyAlign, + applyVAlign: applyVAlign, + unApplyAlign: unApplyAlign, + unApplyVAlign: unApplyVAlign, + getTDTHOverallStyle: getTDTHOverallStyle + }; + + var buildListItems = function (inputList, itemCallback, startItems) { + var appendItems = function (values, output) { + output = output || []; + global$1.each(values, function (item) { + var menuItem = { text: item.text || item.title }; + if (item.menu) { + menuItem.menu = appendItems(item.menu); + } else { + menuItem.value = item.value; + if (itemCallback) { + itemCallback(menuItem); + } + } + output.push(menuItem); + }); + return output; + }; + return appendItems(inputList, startItems || []); + }; + var extractAdvancedStyles = function (dom, elm) { + var rgbToHex = function (value) { + return startsWith(value, 'rgb') ? dom.toHex(value) : value; + }; + var borderWidth = getRaw(Element.fromDom(elm), 'border-width').getOr(''); + var borderStyle = getRaw(Element.fromDom(elm), 'border-style').getOr(''); + var borderColor = getRaw(Element.fromDom(elm), 'border-color').map(rgbToHex).getOr(''); + var bgColor = getRaw(Element.fromDom(elm), 'background-color').map(rgbToHex).getOr(''); + return { + borderwidth: borderWidth, + borderstyle: borderStyle, + bordercolor: borderColor, + backgroundcolor: bgColor + }; + }; + var getSharedValues = function (data) { + var baseData = data[0]; + var comparisonData = data.slice(1); + var keys$1 = keys(baseData); + each(comparisonData, function (items) { + each(keys$1, function (key) { + each$1(items, function (itemValue, itemKey) { + var comparisonValue = baseData[key]; + if (comparisonValue !== '' && key === itemKey) { + if (comparisonValue !== itemValue) { + baseData[key] = ''; + } + } + }); + }); + }); + return baseData; + }; + var getAdvancedTab = function (dialogName) { + var advTabItems = [ + { + name: 'borderstyle', + type: 'selectbox', + label: 'Border style', + items: [ + { + text: 'Select...', + value: '' + }, + { + text: 'Solid', + value: 'solid' + }, + { + text: 'Dotted', + value: 'dotted' + }, + { + text: 'Dashed', + value: 'dashed' + }, + { + text: 'Double', + value: 'double' + }, + { + text: 'Groove', + value: 'groove' + }, + { + text: 'Ridge', + value: 'ridge' + }, + { + text: 'Inset', + value: 'inset' + }, + { + text: 'Outset', + value: 'outset' + }, + { + text: 'None', + value: 'none' + }, + { + text: 'Hidden', + value: 'hidden' + } + ] + }, + { + name: 'bordercolor', + type: 'colorinput', + label: 'Border color' + }, + { + name: 'backgroundcolor', + type: 'colorinput', + label: 'Background color' + } + ]; + var borderWidth = { + name: 'borderwidth', + type: 'input', + label: 'Border width' + }; + var items = dialogName === 'cell' ? [borderWidth].concat(advTabItems) : advTabItems; + return { + title: 'Advanced', + name: 'advanced', + items: items + }; + }; + var getAlignment = function (alignments, formatName, dataName, editor, elm) { + var alignmentData = {}; + global$1.each(alignments.split(' '), function (name) { + if (editor.formatter.matchNode(elm, formatName + name)) { + alignmentData[dataName] = name; + } + }); + if (!alignmentData[dataName]) { + alignmentData[dataName] = ''; + } + return alignmentData; + }; + var getHAlignment = curry(getAlignment, 'left center right'); + var getVAlignment = curry(getAlignment, 'top middle bottom'); + var extractDataFromSettings = function (editor, hasAdvTableTab) { + var style = getDefaultStyles(editor); + var attrs = getDefaultAttributes(editor); + var extractAdvancedStyleData = function (dom) { + var rgbToHex = function (value) { + return startsWith(value, 'rgb') ? dom.toHex(value) : value; + }; + var borderStyle = get(style, 'border-style').getOr(''); + var borderColor = get(style, 'border-color').getOr(''); + var bgColor = get(style, 'background-color').getOr(''); + return { + borderstyle: borderStyle, + bordercolor: rgbToHex(borderColor), + backgroundcolor: rgbToHex(bgColor) + }; + }; + var defaultData = { + height: '', + width: '100%', + cellspacing: '', + cellpadding: '', + caption: false, + class: '', + align: '', + border: '' + }; + var getBorder = function () { + var borderWidth = style['border-width']; + if (shouldStyleWithCss(editor) && borderWidth) { + return { border: borderWidth }; + } + return get(attrs, 'border').fold(function () { + return {}; + }, function (border) { + return { border: border }; + }); + }; + var dom = editor.dom; + var advStyle = hasAdvTableTab ? extractAdvancedStyleData(dom) : {}; + var getCellPaddingCellSpacing = function () { + var spacing = get(style, 'border-spacing').or(get(attrs, 'cellspacing')).fold(function () { + return {}; + }, function (cellspacing) { + return { cellspacing: cellspacing }; + }); + var padding = get(style, 'border-padding').or(get(attrs, 'cellpadding')).fold(function () { + return {}; + }, function (cellpadding) { + return { cellpadding: cellpadding }; + }); + return __assign(__assign({}, spacing), padding); + }; + var data = __assign(__assign(__assign(__assign(__assign(__assign({}, defaultData), style), attrs), advStyle), getBorder()), getCellPaddingCellSpacing()); + return data; + }; + var extractDataFromTableElement = function (editor, elm, hasAdvTableTab) { + var getBorder = function (dom, elm) { + var optBorderWidth = getRaw(Element.fromDom(elm), 'border-width'); + if (shouldStyleWithCss(editor) && optBorderWidth.isSome()) { + return optBorderWidth.getOr(''); + } + return dom.getAttrib(elm, 'border') || Styles$1.getTDTHOverallStyle(editor.dom, elm, 'border-width') || Styles$1.getTDTHOverallStyle(editor.dom, elm, 'border'); + }; + var dom = editor.dom; + var data = __assign(__assign({ + width: dom.getStyle(elm, 'width') || dom.getAttrib(elm, 'width'), + height: dom.getStyle(elm, 'height') || dom.getAttrib(elm, 'height'), + cellspacing: dom.getStyle(elm, 'border-spacing') || dom.getAttrib(elm, 'cellspacing'), + cellpadding: dom.getAttrib(elm, 'cellpadding') || Styles$1.getTDTHOverallStyle(editor.dom, elm, 'padding'), + border: getBorder(dom, elm), + caption: !!dom.select('caption', elm)[0], + class: dom.getAttrib(elm, 'class', '') + }, getHAlignment('align', 'align', editor, elm)), hasAdvTableTab ? extractAdvancedStyles(dom, elm) : {}); + return data; + }; + var extractDataFromRowElement = function (editor, elm, hasAdvancedRowTab) { + var dom = editor.dom; + var data = __assign(__assign({ + height: dom.getStyle(elm, 'height') || dom.getAttrib(elm, 'height'), + scope: dom.getAttrib(elm, 'scope'), + class: dom.getAttrib(elm, 'class', ''), + align: '', + type: elm.parentNode.nodeName.toLowerCase() + }, getHAlignment('align', 'align', editor, elm)), hasAdvancedRowTab ? extractAdvancedStyles(dom, elm) : {}); + return data; + }; + var extractDataFromCellElement = function (editor, elm, hasAdvancedCellTab) { + var dom = editor.dom; + var data = __assign(__assign(__assign({ + width: dom.getStyle(elm, 'width') || dom.getAttrib(elm, 'width'), + height: dom.getStyle(elm, 'height') || dom.getAttrib(elm, 'height'), + scope: dom.getAttrib(elm, 'scope'), + celltype: elm.nodeName.toLowerCase(), + class: dom.getAttrib(elm, 'class', '') + }, getHAlignment('align', 'halign', editor, elm)), getVAlignment('valign', 'valign', editor, elm)), hasAdvancedCellTab ? extractAdvancedStyles(dom, elm) : {}); + return data; + }; + var Helpers = { + buildListItems: buildListItems, + extractAdvancedStyles: extractAdvancedStyles, + getSharedValues: getSharedValues, + getAdvancedTab: getAdvancedTab, + extractDataFromTableElement: extractDataFromTableElement, + extractDataFromRowElement: extractDataFromRowElement, + extractDataFromCellElement: extractDataFromCellElement, + extractDataFromSettings: extractDataFromSettings + }; + + var getClassList = function (editor) { + var rowClassList = getCellClassList(editor); + var classes = Helpers.buildListItems(rowClassList, function (item) { + if (item.value) { + item.textStyle = function () { + return editor.formatter.getCssText({ + block: 'tr', + classes: [item.value] + }); + }; + } + }); + if (rowClassList.length > 0) { + return Option.some({ + name: 'class', + type: 'selectbox', + label: 'Class', + items: classes + }); + } + return Option.none(); + }; + var children$3 = [ + { + name: 'width', + type: 'input', + label: 'Width' + }, + { + name: 'height', + type: 'input', + label: 'Height' + }, + { + name: 'celltype', + type: 'selectbox', + label: 'Cell type', + items: [ + { + text: 'Cell', + value: 'td' + }, + { + text: 'Header cell', + value: 'th' + } + ] + }, + { + name: 'scope', + type: 'selectbox', + label: 'Scope', + items: [ + { + text: 'None', + value: '' + }, + { + text: 'Row', + value: 'row' + }, + { + text: 'Column', + value: 'col' + }, + { + text: 'Row group', + value: 'rowgroup' + }, + { + text: 'Column group', + value: 'colgroup' + } + ] + }, + { + name: 'halign', + type: 'selectbox', + label: 'H Align', + items: [ + { + text: 'None', + value: '' + }, + { + text: 'Left', + value: 'left' + }, + { + text: 'Center', + value: 'center' + }, + { + text: 'Right', + value: 'right' + } + ] + }, + { + name: 'valign', + type: 'selectbox', + label: 'V Align', + items: [ + { + text: 'None', + value: '' + }, + { + text: 'Top', + value: 'top' + }, + { + text: 'Middle', + value: 'middle' + }, + { + text: 'Bottom', + value: 'bottom' + } + ] + } + ]; + var getItems = function (editor) { + return getClassList(editor).fold(function () { + return children$3; + }, function (classlist) { + return children$3.concat(classlist); + }); + }; + var CellDialogGeneralTab = { getItems: getItems }; + + var normal = function (dom, node) { + var setAttrib = function (attr, value) { + dom.setAttrib(node, attr, value); + }; + var setStyle = function (prop, value) { + dom.setStyle(node, prop, value); + }; + return { + setAttrib: setAttrib, + setStyle: setStyle + }; + }; + var ifTruthy = function (dom, node) { + var setAttrib = function (attr, value) { + if (value) { + dom.setAttrib(node, attr, value); + } + }; + var setStyle = function (prop, value) { + if (value) { + dom.setStyle(node, prop, value); + } + }; + return { + setAttrib: setAttrib, + setStyle: setStyle + }; + }; + var DomModifier = { + normal: normal, + ifTruthy: ifTruthy + }; + + var updateSimpleProps = function (modifiers, data) { + modifiers.setAttrib('scope', data.scope); + modifiers.setAttrib('class', data.class); + modifiers.setStyle('width', addSizeSuffix(data.width)); + modifiers.setStyle('height', addSizeSuffix(data.height)); + }; + var updateAdvancedProps = function (modifiers, data) { + modifiers.setStyle('background-color', data.backgroundcolor); + modifiers.setStyle('border-color', data.bordercolor); + modifiers.setStyle('border-style', data.borderstyle); + modifiers.setStyle('border-width', addSizeSuffix(data.borderwidth)); + }; + var applyToSingle = function (editor, cells, data) { + var dom = editor.dom; + var cellElm = data.celltype && cells[0].nodeName.toLowerCase() !== data.celltype ? dom.rename(cells[0], data.celltype) : cells[0]; + var modifiers = DomModifier.normal(dom, cellElm); + updateSimpleProps(modifiers, data); + if (hasAdvancedCellTab(editor)) { + updateAdvancedProps(modifiers, data); + } + Styles$1.unApplyAlign(editor, cellElm); + Styles$1.unApplyVAlign(editor, cellElm); + if (data.halign) { + Styles$1.applyAlign(editor, cellElm, data.halign); + } + if (data.valign) { + Styles$1.applyVAlign(editor, cellElm, data.valign); + } + }; + var applyToMultiple = function (editor, cells, data) { + var dom = editor.dom; + global$1.each(cells, function (cellElm) { + if (data.celltype && cellElm.nodeName.toLowerCase() !== data.celltype) { + cellElm = dom.rename(cellElm, data.celltype); + } + var modifiers = DomModifier.ifTruthy(dom, cellElm); + updateSimpleProps(modifiers, data); + if (hasAdvancedCellTab(editor)) { + updateAdvancedProps(modifiers, data); + } + if (data.halign) { + Styles$1.applyAlign(editor, cellElm, data.halign); + } + if (data.valign) { + Styles$1.applyVAlign(editor, cellElm, data.valign); + } + }); + }; + var onSubmitCellForm = function (editor, cells, api) { + var data = api.getData(); + api.close(); + editor.undoManager.transact(function () { + var applicator = cells.length === 1 ? applyToSingle : applyToMultiple; + applicator(editor, cells, data); + editor.focus(); + }); + }; + var open = function (editor) { + var cellElm, cells = []; + cells = editor.dom.select('td[data-mce-selected],th[data-mce-selected]'); + cellElm = editor.dom.getParent(editor.selection.getStart(), 'td,th'); + if (!cells.length && cellElm) { + cells.push(cellElm); + } + cellElm = cellElm || cells[0]; + if (!cellElm) { + return; + } + var cellsData = global$1.map(cells, function (cellElm) { + return Helpers.extractDataFromCellElement(editor, cellElm, hasAdvancedCellTab(editor)); + }); + var data = Helpers.getSharedValues(cellsData); + var dialogTabPanel = { + type: 'tabpanel', + tabs: [ + { + title: 'General', + name: 'general', + items: CellDialogGeneralTab.getItems(editor) + }, + Helpers.getAdvancedTab('cell') + ] + }; + var dialogPanel = { + type: 'panel', + items: [{ + type: 'grid', + columns: 2, + items: CellDialogGeneralTab.getItems(editor) + }] + }; + editor.windowManager.open({ + title: 'Cell Properties', + size: 'normal', + body: hasAdvancedCellTab(editor) ? dialogTabPanel : dialogPanel, + buttons: [ + { + type: 'cancel', + name: 'cancel', + text: 'Cancel' + }, + { + type: 'submit', + name: 'save', + text: 'Save', + primary: true + } + ], + initialData: data, + onSubmit: curry(onSubmitCellForm, editor, cells) + }); + }; + var CellDialog = { open: open }; + + var getClassList$1 = function (editor) { + var rowClassList = getRowClassList(editor); + var classes = Helpers.buildListItems(rowClassList, function (item) { + if (item.value) { + item.textStyle = function () { + return editor.formatter.getCssText({ + block: 'tr', + classes: [item.value] + }); + }; + } + }); + if (rowClassList.length > 0) { + return Option.some({ + name: 'class', + type: 'selectbox', + label: 'Class', + items: classes + }); + } + return Option.none(); + }; + var formChildren = [ + { + type: 'selectbox', + name: 'type', + label: 'Row type', + items: [ + { + text: 'Header', + value: 'thead' + }, + { + text: 'Body', + value: 'tbody' + }, + { + text: 'Footer', + value: 'tfoot' + } + ] + }, + { + type: 'selectbox', + name: 'align', + label: 'Alignment', + items: [ + { + text: 'None', + value: '' + }, + { + text: 'Left', + value: 'left' + }, + { + text: 'Center', + value: 'center' + }, + { + text: 'Right', + value: 'right' + } + ] + }, + { + label: 'Height', + name: 'height', + type: 'input' + } + ]; + var getItems$1 = function (editor) { + return getClassList$1(editor).fold(function () { + return formChildren; + }, function (classes) { + return formChildren.concat(classes); + }); + }; + var RowDialogGeneralTab = { getItems: getItems$1 }; + + var switchRowType = function (dom, rowElm, toType) { + var tableElm = dom.getParent(rowElm, 'table'); + var oldParentElm = rowElm.parentNode; + var parentElm = dom.select(toType, tableElm)[0]; + if (!parentElm) { + parentElm = dom.create(toType); + if (tableElm.firstChild) { + if (tableElm.firstChild.nodeName === 'CAPTION') { + dom.insertAfter(parentElm, tableElm.firstChild); + } else { + tableElm.insertBefore(parentElm, tableElm.firstChild); + } + } else { + tableElm.appendChild(parentElm); + } + } + if (toType === 'tbody' && oldParentElm.nodeName === 'THEAD' && parentElm.firstChild) { + parentElm.insertBefore(rowElm, parentElm.firstChild); + } else { + parentElm.appendChild(rowElm); + } + if (!oldParentElm.hasChildNodes()) { + dom.remove(oldParentElm); + } + }; + var updateAdvancedProps$1 = function (modifier, data) { + modifier.setStyle('background-color', data.backgroundcolor); + modifier.setStyle('border-color', data.bordercolor); + modifier.setStyle('border-style', data.borderstyle); + }; + var onSubmitRowForm = function (editor, rows, oldData, api) { + var dom = editor.dom; + var data = api.getData(); + api.close(); + var createModifier = rows.length === 1 ? DomModifier.normal : DomModifier.ifTruthy; + editor.undoManager.transact(function () { + global$1.each(rows, function (rowElm) { + if (data.type !== rowElm.parentNode.nodeName.toLowerCase()) { + switchRowType(editor.dom, rowElm, data.type); + } + var modifier = createModifier(dom, rowElm); + modifier.setAttrib('scope', data.scope); + modifier.setAttrib('class', data.class); + modifier.setStyle('height', addSizeSuffix(data.height)); + if (hasAdvancedRowTab(editor)) { + updateAdvancedProps$1(modifier, data); + } + if (data.align !== oldData.align) { + Styles$1.unApplyAlign(editor, rowElm); + Styles$1.applyAlign(editor, rowElm, data.align); + } + }); + editor.focus(); + }); + }; + var open$1 = function (editor) { + var dom = editor.dom; + var tableElm, cellElm, rowElm; + var rows = []; + tableElm = dom.getParent(editor.selection.getStart(), 'table'); + if (!tableElm) { + return; + } + cellElm = dom.getParent(editor.selection.getStart(), 'td,th'); + global$1.each(tableElm.rows, function (row) { + global$1.each(row.cells, function (cell) { + if ((dom.getAttrib(cell, 'data-mce-selected') || cell === cellElm) && rows.indexOf(row) < 0) { + rows.push(row); + return false; + } + }); + }); + rowElm = rows[0]; + if (!rowElm) { + return; + } + var rowsData = global$1.map(rows, function (rowElm) { + return Helpers.extractDataFromRowElement(editor, rowElm, hasAdvancedRowTab(editor)); + }); + var data = Helpers.getSharedValues(rowsData); + var dialogTabPanel = { + type: 'tabpanel', + tabs: [ + { + title: 'General', + name: 'general', + items: RowDialogGeneralTab.getItems(editor) + }, + Helpers.getAdvancedTab('row') + ] + }; + var dialogPanel = { + type: 'panel', + items: [{ + type: 'grid', + columns: 2, + items: RowDialogGeneralTab.getItems(editor) + }] + }; + editor.windowManager.open({ + title: 'Row Properties', + size: 'normal', + body: hasAdvancedRowTab(editor) ? dialogTabPanel : dialogPanel, + buttons: [ + { + type: 'cancel', + name: 'cancel', + text: 'Cancel' + }, + { + type: 'submit', + name: 'save', + text: 'Save', + primary: true + } + ], + initialData: data, + onSubmit: curry(onSubmitRowForm, editor, rows, data) + }); + }; + var RowDialog = { open: open$1 }; + + var hasOwnProperty$1 = Object.prototype.hasOwnProperty; + var shallow$1 = function (old, nu) { + return nu; + }; + var baseMerge = function (merger) { + return function () { + var objects = new Array(arguments.length); + for (var i = 0; i < objects.length; i++) { + objects[i] = arguments[i]; + } + if (objects.length === 0) { + throw new Error('Can\'t merge zero objects'); + } + var ret = {}; + for (var j = 0; j < objects.length; j++) { + var curObject = objects[j]; + for (var key in curObject) { + if (hasOwnProperty$1.call(curObject, key)) { + ret[key] = merger(ret[key], curObject[key]); + } + } + } + return ret; + }; + }; + var merge$3 = baseMerge(shallow$1); + + var global$2 = tinymce.util.Tools.resolve('tinymce.Env'); + + var DefaultRenderOptions = { + styles: { + 'border-collapse': 'collapse', + 'width': '100%' + }, + attributes: { border: '1' }, + percentages: true + }; + var makeTable = function () { + return Element.fromTag('table'); + }; + var tableBody = function () { + return Element.fromTag('tbody'); + }; + var tableRow = function () { + return Element.fromTag('tr'); + }; + var tableHeaderCell = function () { + return Element.fromTag('th'); + }; + var tableCell = function () { + return Element.fromTag('td'); + }; + var render$1 = function (rows, columns, rowHeaders, columnHeaders, renderOpts) { + if (renderOpts === void 0) { + renderOpts = DefaultRenderOptions; + } + var table = makeTable(); + setAll$1(table, renderOpts.styles); + setAll(table, renderOpts.attributes); + var tbody = tableBody(); + append(table, tbody); + var trs = []; + for (var i = 0; i < rows; i++) { + var tr = tableRow(); + for (var j = 0; j < columns; j++) { + var td = i < rowHeaders || j < columnHeaders ? tableHeaderCell() : tableCell(); + if (j < columnHeaders) { + set(td, 'scope', 'row'); + } + if (i < rowHeaders) { + set(td, 'scope', 'col'); + } + append(td, Element.fromTag('br')); + if (renderOpts.percentages) { + set$1(td, 'width', 100 / columns + '%'); + } + append(tr, td); + } + trs.push(tr); + } + append$1(tbody, trs); + return table; + }; + + var get$8 = function (element) { + return element.dom().innerHTML; + }; + var getOuter$2 = function (element) { + var container = Element.fromTag('div'); + var clone = Element.fromDom(element.dom().cloneNode(true)); + append(container, clone); + return get$8(container); + }; + + var placeCaretInCell = function (editor, cell) { + editor.selection.select(cell.dom(), true); + editor.selection.collapse(true); + }; + var selectFirstCellInTable = function (editor, tableElm) { + descendant$1(tableElm, 'td,th').each(curry(placeCaretInCell, editor)); + }; + var fireEvents = function (editor, table) { + each(descendants$1(table, 'tr'), function (row) { + fireNewRow(editor, row.dom()); + each(descendants$1(row, 'th,td'), function (cell) { + fireNewCell(editor, cell.dom()); + }); + }); + }; + var isPercentage = function (width) { + return isString(width) && width.indexOf('%') !== -1; + }; + var insert$1 = function (editor, columns, rows) { + var defaultStyles = getDefaultStyles(editor); + var options = { + styles: defaultStyles, + attributes: getDefaultAttributes(editor), + percentages: isPercentage(defaultStyles.width) && !isPixelsForced(editor) + }; + var table = render$1(rows, columns, 0, 0, options); + set(table, 'data-mce-id', '__mce'); + var html = getOuter$2(table); + editor.insertContent(html); + return descendant$1(getBody$1(editor), 'table[data-mce-id="__mce"]').map(function (table) { + if (isPixelsForced(editor)) { + set$1(table, 'width', get$2(table, 'width')); + } + remove(table, 'data-mce-id'); + fireEvents(editor, table); + selectFirstCellInTable(editor, table); + return table.dom(); + }).getOr(null); + }; + var InsertTable = { insert: insert$1 }; + + var getItems$2 = function (editor, hasClasses, insertNewTable) { + var rowColCountItems = !insertNewTable ? [] : [ + { + type: 'input', + name: 'cols', + label: 'Cols', + inputMode: 'numeric' + }, + { + type: 'input', + name: 'rows', + label: 'Rows', + inputMode: 'numeric' + } + ]; + var alwaysItems = [ + { + type: 'input', + name: 'width', + label: 'Width' + }, + { + type: 'input', + name: 'height', + label: 'Height' + } + ]; + var appearanceItems = hasAppearanceOptions(editor) ? [ + { + type: 'input', + name: 'cellspacing', + label: 'Cell spacing', + inputMode: 'numeric' + }, + { + type: 'input', + name: 'cellpadding', + label: 'Cell padding', + inputMode: 'numeric' + }, + { + type: 'input', + name: 'border', + label: 'Border width' + }, + { + type: 'label', + label: 'Caption', + items: [{ + type: 'checkbox', + name: 'caption', + label: 'Show caption' + }] + } + ] : []; + var alignmentItem = [{ + type: 'selectbox', + name: 'align', + label: 'Alignment', + items: [ + { + text: 'None', + value: '' + }, + { + text: 'Left', + value: 'left' + }, + { + text: 'Center', + value: 'center' + }, + { + text: 'Right', + value: 'right' + } + ] + }]; + var classListItem = hasClasses ? [{ + type: 'selectbox', + name: 'class', + label: 'Class', + items: Helpers.buildListItems(getTableClassList(editor), function (item) { + if (item.value) { + item.textStyle = function () { + return editor.formatter.getCssText({ + block: 'table', + classes: [item.value] + }); + }; + } + }) + }] : []; + return rowColCountItems.concat(alwaysItems).concat(appearanceItems).concat(alignmentItem).concat(classListItem); + }; + var TableDialogGeneralTab = { getItems: getItems$2 }; + + var styleTDTH = function (dom, elm, name, value) { + if (elm.tagName === 'TD' || elm.tagName === 'TH') { + if (isString(name)) { + dom.setStyle(elm, name, value); + } else { + dom.setStyle(elm, name); + } + } else { + if (elm.children) { + for (var i = 0; i < elm.children.length; i++) { + styleTDTH(dom, elm.children[i], name, value); + } + } + } + }; + var applyDataToElement = function (editor, tableElm, data) { + var dom = editor.dom; + var attrs = {}; + var styles = {}; + attrs.class = data.class; + styles.height = addSizeSuffix(data.height); + if (dom.getAttrib(tableElm, 'width') && !shouldStyleWithCss(editor)) { + attrs.width = removePxSuffix(data.width); + } else { + styles.width = addSizeSuffix(data.width); + } + if (shouldStyleWithCss(editor)) { + styles['border-width'] = addSizeSuffix(data.border); + styles['border-spacing'] = addSizeSuffix(data.cellspacing); + } else { + attrs.border = data.border; + attrs.cellpadding = data.cellpadding; + attrs.cellspacing = data.cellspacing; + } + if (shouldStyleWithCss(editor) && tableElm.children) { + for (var i = 0; i < tableElm.children.length; i++) { + styleTDTH(dom, tableElm.children[i], { + 'border-width': addSizeSuffix(data.border), + 'padding': addSizeSuffix(data.cellpadding) + }); + if (hasAdvancedTableTab(editor)) { + styleTDTH(dom, tableElm.children[i], { 'border-color': data.bordercolor }); + } + } + } + if (hasAdvancedTableTab(editor)) { + styles['background-color'] = data.backgroundcolor; + styles['border-color'] = data.bordercolor; + styles['border-style'] = data.borderstyle; + } + attrs.style = dom.serializeStyle(merge$3(getDefaultStyles(editor), styles)); + dom.setAttribs(tableElm, merge$3(getDefaultAttributes(editor), attrs)); + }; + var onSubmitTableForm = function (editor, tableElm, api) { + var dom = editor.dom; + var captionElm; + var data = api.getData(); + api.close(); + if (data.class === '') { + delete data.class; + } + editor.undoManager.transact(function () { + if (!tableElm) { + var cols = parseInt(data.cols, 10) || 1; + var rows = parseInt(data.rows, 10) || 1; + tableElm = InsertTable.insert(editor, cols, rows); + } + applyDataToElement(editor, tableElm, data); + captionElm = dom.select('caption', tableElm)[0]; + if (captionElm && !data.caption) { + dom.remove(captionElm); + } + if (!captionElm && data.caption) { + captionElm = dom.create('caption'); + captionElm.innerHTML = !global$2.ie ? '
' : '\xA0'; + tableElm.insertBefore(captionElm, tableElm.firstChild); + } + if (data.align === '') { + Styles$1.unApplyAlign(editor, tableElm); + } else { + Styles$1.applyAlign(editor, tableElm, data.align); + } + editor.focus(); + editor.addVisual(); + }); + }; + var open$2 = function (editor, insertNewTable) { + var dom = editor.dom; + var tableElm; + var data = Helpers.extractDataFromSettings(editor, hasAdvancedTableTab(editor)); + if (insertNewTable === false) { + tableElm = dom.getParent(editor.selection.getStart(), 'table'); + if (tableElm) { + data = Helpers.extractDataFromTableElement(editor, tableElm, hasAdvancedTableTab(editor)); + } else { + if (hasAdvancedTableTab(editor)) { + data.borderstyle = ''; + data.bordercolor = ''; + data.backgroundcolor = ''; + } + } + } else { + data.cols = '1'; + data.rows = '1'; + if (hasAdvancedTableTab(editor)) { + data.borderstyle = ''; + data.bordercolor = ''; + data.backgroundcolor = ''; + } + } + var hasClasses = getTableClassList(editor).length > 0; + if (hasClasses) { + if (data.class) { + data.class = data.class.replace(/\s*mce\-item\-table\s*/g, ''); + } + } + var generalPanel = { + type: 'grid', + columns: 2, + items: TableDialogGeneralTab.getItems(editor, hasClasses, insertNewTable) + }; + var nonAdvancedForm = function () { + return { + type: 'panel', + items: [generalPanel] + }; + }; + var advancedForm = function () { + return { + type: 'tabpanel', + tabs: [ + { + title: 'General', + name: 'general', + items: [generalPanel] + }, + Helpers.getAdvancedTab('table') + ] + }; + }; + var dialogBody = hasAdvancedTableTab(editor) ? advancedForm() : nonAdvancedForm(); + editor.windowManager.open({ + title: 'Table Properties', + size: 'normal', + body: dialogBody, + onSubmit: curry(onSubmitTableForm, editor, tableElm), + buttons: [ + { + type: 'cancel', + name: 'cancel', + text: 'Cancel' + }, + { + type: 'submit', + name: 'save', + text: 'Save', + primary: true + } + ], + initialData: data + }); + }; + var TableDialog = { open: open$2 }; + + var getSelectionStartFromSelector = function (selector) { + return function (editor) { + return Option.from(editor.dom.getParent(editor.selection.getStart(), selector)).map(Element.fromDom); + }; + }; + var getSelectionStartCell = getSelectionStartFromSelector('th,td'); + var getSelectionStartCellOrCaption = getSelectionStartFromSelector('th,td,caption'); + + var each$3 = global$1.each; + var registerCommands = function (editor, actions, cellSelection, selections, clipboardRows) { + var isRoot = getIsRoot(editor); + var eraseTable = function () { + getSelectionStartCellOrCaption(editor).each(function (cellOrCaption) { + var tableOpt = TableLookup.table(cellOrCaption, isRoot); + tableOpt.filter(not(isRoot)).each(function (table) { + var cursor = Element.fromText(''); + after(table, cursor); + remove$2(table); + if (editor.dom.isEmpty(editor.getBody())) { + editor.setContent(''); + editor.selection.setCursorLocation(); + } else { + var rng = editor.dom.createRng(); + rng.setStart(cursor.dom(), 0); + rng.setEnd(cursor.dom(), 0); + editor.selection.setRng(rng); + editor.nodeChanged(); + } + }); + }); + }; + var getTableFromCell = function (cell) { + return TableLookup.table(cell, isRoot); + }; + var getSize = function (table) { + return { + width: getPixelWidth$1(table.dom()), + height: getPixelWidth$1(table.dom()) + }; + }; + var resizeChange = function (editor, oldSize, table) { + var newSize = getSize(table); + if (oldSize.width !== newSize.width || oldSize.height !== newSize.height) { + fireObjectResizeStart(editor, table.dom(), oldSize.width, oldSize.height); + fireObjectResized(editor, table.dom(), newSize.width, newSize.height); + } + }; + var actOnSelection = function (execute) { + getSelectionStartCell(editor).each(function (cell) { + getTableFromCell(cell).each(function (table) { + var targets = TableTargets.forMenu(selections, table, cell); + var beforeSize = getSize(table); + execute(table, targets).each(function (rng) { + resizeChange(editor, beforeSize, table); + editor.selection.setRng(rng); + editor.focus(); + cellSelection.clear(table); + removeDataStyle(table); + }); + }); + }); + }; + var copyRowSelection = function (execute) { + return getSelectionStartCell(editor).map(function (cell) { + return getTableFromCell(cell).bind(function (table) { + var doc = Element.fromDom(editor.getDoc()); + var targets = TableTargets.forMenu(selections, table, cell); + var generators = TableFill.cellOperations(noop, doc, Option.none()); + return CopyRows.copyRows(table, targets, generators); + }); + }); + }; + var pasteOnSelection = function (execute) { + clipboardRows.get().each(function (rows) { + var clonedRows = map(rows, function (row) { + return deep(row); + }); + getSelectionStartCell(editor).each(function (cell) { + getTableFromCell(cell).each(function (table) { + var doc = Element.fromDom(editor.getDoc()); + var generators = TableFill.paste(doc); + var targets = TableTargets.pasteRows(selections, table, cell, clonedRows, generators); + execute(table, targets).each(function (rng) { + editor.selection.setRng(rng); + editor.focus(); + cellSelection.clear(table); + }); + }); + }); + }); + }; + each$3({ + mceTableSplitCells: function () { + actOnSelection(actions.unmergeCells); + }, + mceTableMergeCells: function () { + actOnSelection(actions.mergeCells); + }, + mceTableInsertRowBefore: function () { + actOnSelection(actions.insertRowsBefore); + }, + mceTableInsertRowAfter: function () { + actOnSelection(actions.insertRowsAfter); + }, + mceTableInsertColBefore: function () { + actOnSelection(actions.insertColumnsBefore); + }, + mceTableInsertColAfter: function () { + actOnSelection(actions.insertColumnsAfter); + }, + mceTableDeleteCol: function () { + actOnSelection(actions.deleteColumn); + }, + mceTableDeleteRow: function () { + actOnSelection(actions.deleteRow); + }, + mceTableCutRow: function (grid) { + copyRowSelection().each(function (selection) { + clipboardRows.set(selection); + actOnSelection(actions.deleteRow); + }); + }, + mceTableCopyRow: function (grid) { + copyRowSelection().each(function (selection) { + clipboardRows.set(selection); + }); + }, + mceTablePasteRowBefore: function (grid) { + pasteOnSelection(actions.pasteRowsBefore); + }, + mceTablePasteRowAfter: function (grid) { + pasteOnSelection(actions.pasteRowsAfter); + }, + mceTableDelete: eraseTable + }, function (func, name) { + editor.addCommand(name, func); + }); + each$3({ + mceInsertTable: curry(TableDialog.open, editor, true), + mceTableProps: curry(TableDialog.open, editor, false), + mceTableRowProps: curry(RowDialog.open, editor), + mceTableCellProps: curry(CellDialog.open, editor) + }, function (func, name) { + editor.addCommand(name, function () { + func(); + }); + }); + }; + var Commands = { registerCommands: registerCommands }; + + var only = function (element) { + var parent = Option.from(element.dom().documentElement).map(Element.fromDom).getOr(element); + return { + parent: constant(parent), + view: constant(element), + origin: constant(Position(0, 0)) + }; + }; + var detached = function (editable, chrome) { + var origin = function () { + return absolute(chrome); + }; + return { + parent: constant(chrome), + view: constant(editable), + origin: origin + }; + }; + var body$1 = function (editable, chrome) { + return { + parent: constant(chrome), + view: constant(editable), + origin: constant(Position(0, 0)) + }; + }; + var ResizeWire = { + only: only, + detached: detached, + body: body$1 + }; + + var Event = function (fields) { + var struct = Immutable.apply(null, fields); + var handlers = []; + var bind = function (handler) { + if (handler === undefined) { + throw new Error('Event bind error: undefined handler'); + } + handlers.push(handler); + }; + var unbind = function (handler) { + handlers = filter(handlers, function (h) { + return h !== handler; + }); + }; + var trigger = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var event = struct.apply(null, args); + each(handlers, function (handler) { + handler(event); + }); + }; + return { + bind: bind, + unbind: unbind, + trigger: trigger + }; + }; + + var create$1 = function (typeDefs) { + var registry = map$1(typeDefs, function (event) { + return { + bind: event.bind, + unbind: event.unbind + }; + }); + var trigger = map$1(typeDefs, function (event) { + return event.trigger; + }); + return { + registry: registry, + trigger: trigger + }; + }; + var Events = { create: create$1 }; + + var mkEvent = function (target, x, y, stop, prevent, kill, raw) { + return { + target: constant(target), + x: constant(x), + y: constant(y), + stop: stop, + prevent: prevent, + kill: kill, + raw: constant(raw) + }; + }; + var fromRawEvent = function (rawEvent) { + var target = Element.fromDom(rawEvent.target); + var stop = function () { + rawEvent.stopPropagation(); + }; + var prevent = function () { + rawEvent.preventDefault(); + }; + var kill = compose(prevent, stop); + return mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent); + }; + var handle = function (filter, handler) { + return function (rawEvent) { + if (!filter(rawEvent)) { + return; + } + handler(fromRawEvent(rawEvent)); + }; + }; + var binder = function (element, event, filter, handler, useCapture) { + var wrapped = handle(filter, handler); + element.dom().addEventListener(event, wrapped, useCapture); + return { unbind: curry(unbind, element, event, wrapped, useCapture) }; + }; + var bind$1 = function (element, event, filter, handler) { + return binder(element, event, filter, handler, false); + }; + var unbind = function (element, event, handler, useCapture) { + element.dom().removeEventListener(event, handler, useCapture); + }; + + var filter$1 = constant(true); + var bind$2 = function (element, event, handler) { + return bind$1(element, event, filter$1, handler); + }; + + var styles$1 = css('ephox-dragster'); + var Styles$2 = { resolve: styles$1.resolve }; + + var Blocker = function (options) { + var settings = merge$3({ layerClass: Styles$2.resolve('blocker') }, options); + var div = Element.fromTag('div'); + set(div, 'role', 'presentation'); + setAll$1(div, { + position: 'fixed', + left: '0px', + top: '0px', + width: '100%', + height: '100%' + }); + add$2(div, Styles$2.resolve('blocker')); + add$2(div, settings.layerClass); + var element = function () { + return div; + }; + var destroy = function () { + remove$2(div); + }; + return { + element: element, + destroy: destroy + }; + }; + + var DragMode = exactly([ + 'compare', + 'extract', + 'mutate', + 'sink' + ]); + var DragSink = exactly([ + 'element', + 'start', + 'stop', + 'destroy' + ]); + var DragApi = exactly([ + 'forceDrop', + 'drop', + 'move', + 'delayDrop' + ]); + + var compare = function (old, nu) { + return Position(nu.left() - old.left(), nu.top() - old.top()); + }; + var extract$1 = function (event) { + return Option.some(Position(event.x(), event.y())); + }; + var mutate = function (mutation, info) { + mutation.mutate(info.left(), info.top()); + }; + var sink = function (dragApi, settings) { + var blocker = Blocker(settings); + var mdown = bind$2(blocker.element(), 'mousedown', dragApi.forceDrop); + var mup = bind$2(blocker.element(), 'mouseup', dragApi.drop); + var mmove = bind$2(blocker.element(), 'mousemove', dragApi.move); + var mout = bind$2(blocker.element(), 'mouseout', dragApi.delayDrop); + var destroy = function () { + blocker.destroy(); + mup.unbind(); + mmove.unbind(); + mout.unbind(); + mdown.unbind(); + }; + var start = function (parent) { + append(parent, blocker.element()); + }; + var stop = function () { + remove$2(blocker.element()); + }; + return DragSink({ + element: blocker.element, + start: start, + stop: stop, + destroy: destroy + }); + }; + var MouseDrag = DragMode({ + compare: compare, + extract: extract$1, + sink: sink, + mutate: mutate + }); + + var last$2 = function (fn, rate) { + var timer = null; + var cancel = function () { + if (timer !== null) { + domGlobals.clearTimeout(timer); + timer = null; + } + }; + var throttle = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + if (timer !== null) { + domGlobals.clearTimeout(timer); + } + timer = domGlobals.setTimeout(function () { + fn.apply(null, args); + timer = null; + }, rate); + }; + return { + cancel: cancel, + throttle: throttle + }; + }; + + function InDrag () { + var previous = Option.none(); + var reset = function () { + previous = Option.none(); + }; + var update = function (mode, nu) { + var result = previous.map(function (old) { + return mode.compare(old, nu); + }); + previous = Option.some(nu); + return result; + }; + var onEvent = function (event, mode) { + var dataOption = mode.extract(event); + dataOption.each(function (data) { + var offset = update(mode, data); + offset.each(function (d) { + events.trigger.move(d); + }); + }); + }; + var events = Events.create({ move: Event(['info']) }); + return { + onEvent: onEvent, + reset: reset, + events: events.registry + }; + } + + function NoDrag () { + return { + onEvent: noop, + reset: noop + }; + } + + function Movement () { + var noDragState = NoDrag(); + var inDragState = InDrag(); + var dragState = noDragState; + var on = function () { + dragState.reset(); + dragState = inDragState; + }; + var off = function () { + dragState.reset(); + dragState = noDragState; + }; + var onEvent = function (event, mode) { + dragState.onEvent(event, mode); + }; + var isOn = function () { + return dragState === inDragState; + }; + return { + on: on, + off: off, + isOn: isOn, + onEvent: onEvent, + events: inDragState.events + }; + } + + var setup = function (mutation, mode, settings) { + var active = false; + var events = Events.create({ + start: Event([]), + stop: Event([]) + }); + var movement = Movement(); + var drop = function () { + sink.stop(); + if (movement.isOn()) { + movement.off(); + events.trigger.stop(); + } + }; + var throttledDrop = last$2(drop, 200); + var go = function (parent) { + sink.start(parent); + movement.on(); + events.trigger.start(); + }; + var mousemove = function (event) { + throttledDrop.cancel(); + movement.onEvent(event, mode); + }; + movement.events.move.bind(function (event) { + mode.mutate(mutation, event.info()); + }); + var on = function () { + active = true; + }; + var off = function () { + active = false; + }; + var runIfActive = function (f) { + return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + if (active) { + f.apply(null, args); + } + }; + }; + var sink = mode.sink(DragApi({ + forceDrop: drop, + drop: runIfActive(drop), + move: runIfActive(mousemove), + delayDrop: runIfActive(throttledDrop.throttle) + }), settings); + var destroy = function () { + sink.destroy(); + }; + return { + element: sink.element, + go: go, + on: on, + off: off, + destroy: destroy, + events: events.registry + }; + }; + var Dragging = { setup: setup }; + + var transform$1 = function (mutation, settings) { + if (settings === void 0) { + settings = {}; + } + var mode = settings.mode !== undefined ? settings.mode : MouseDrag; + return Dragging.setup(mutation, mode, settings); + }; + var Dragger = { transform: transform$1 }; + + var Mutation = function () { + var events = Events.create({ + drag: Event([ + 'xDelta', + 'yDelta' + ]) + }); + var mutate = function (x, y) { + events.trigger.drag(x, y); + }; + return { + mutate: mutate, + events: events.registry + }; + }; + + var BarMutation = function () { + var events = Events.create({ + drag: Event([ + 'xDelta', + 'yDelta', + 'target' + ]) + }); + var target = Option.none(); + var delegate = Mutation(); + delegate.events.drag.bind(function (event) { + target.each(function (t) { + events.trigger.drag(event.xDelta(), event.yDelta(), t); + }); + }); + var assign = function (t) { + target = Option.some(t); + }; + var get = function () { + return target; + }; + return { + assign: assign, + get: get, + mutate: delegate.mutate, + events: events.registry + }; + }; + + var isContentEditableTrue = function (elm) { + return get$1(elm, 'contenteditable') === 'true'; + }; + var findClosestContentEditable = function (target, isRoot) { + return closest$1(target, '[contenteditable]', isRoot); + }; + + var resizeBarDragging = Styles.resolve('resizer-bar-dragging'); + var BarManager = function (wire, direction, hdirection) { + var mutation = BarMutation(); + var resizing = Dragger.transform(mutation, {}); + var hoverTable = Option.none(); + var getResizer = function (element, type) { + return Option.from(get$1(element, type)); + }; + mutation.events.drag.bind(function (event) { + getResizer(event.target(), 'data-row').each(function (_dataRow) { + var currentRow = CellUtils.getInt(event.target(), 'top'); + set$1(event.target(), 'top', currentRow + event.yDelta() + 'px'); + }); + getResizer(event.target(), 'data-column').each(function (_dataCol) { + var currentCol = CellUtils.getInt(event.target(), 'left'); + set$1(event.target(), 'left', currentCol + event.xDelta() + 'px'); + }); + }); + var getDelta = function (target, dir) { + var newX = CellUtils.getInt(target, dir); + var oldX = parseInt(get$1(target, 'data-initial-' + dir), 10); + return newX - oldX; + }; + resizing.events.stop.bind(function () { + mutation.get().each(function (target) { + hoverTable.each(function (table) { + getResizer(target, 'data-row').each(function (row) { + var delta = getDelta(target, 'top'); + remove(target, 'data-initial-top'); + events.trigger.adjustHeight(table, delta, parseInt(row, 10)); + }); + getResizer(target, 'data-column').each(function (column) { + var delta = getDelta(target, 'left'); + remove(target, 'data-initial-left'); + events.trigger.adjustWidth(table, delta, parseInt(column, 10)); + }); + Bars.refresh(wire, table, hdirection, direction); + }); + }); + }); + var handler = function (target, dir) { + events.trigger.startAdjust(); + mutation.assign(target); + set(target, 'data-initial-' + dir, parseInt(get$2(target, dir), 10)); + add$2(target, resizeBarDragging); + set$1(target, 'opacity', '0.2'); + resizing.go(wire.parent()); + }; + var mousedown = bind$2(wire.parent(), 'mousedown', function (event) { + if (Bars.isRowBar(event.target())) { + handler(event.target(), 'top'); + } + if (Bars.isColBar(event.target())) { + handler(event.target(), 'left'); + } + }); + var isRoot = function (e) { + return eq(e, wire.view()); + }; + var findClosestEditableTable = function (target) { + return closest$1(target, 'table', isRoot).filter(function (table) { + return findClosestContentEditable(table, isRoot).exists(isContentEditableTrue); + }); + }; + var mouseover = bind$2(wire.view(), 'mouseover', function (event) { + findClosestEditableTable(event.target()).fold(function () { + if (inBody(event.target())) { + Bars.destroy(wire); + } + }, function (table) { + hoverTable = Option.some(table); + Bars.refresh(wire, table, hdirection, direction); + }); + }); + var destroy = function () { + mousedown.unbind(); + mouseover.unbind(); + resizing.destroy(); + Bars.destroy(wire); + }; + var refresh = function (tbl) { + Bars.refresh(wire, tbl, hdirection, direction); + }; + var events = Events.create({ + adjustHeight: Event([ + 'table', + 'delta', + 'row' + ]), + adjustWidth: Event([ + 'table', + 'delta', + 'column' + ]), + startAdjust: Event([]) + }); + return { + destroy: destroy, + refresh: refresh, + on: resizing.on, + off: resizing.off, + hideBars: curry(Bars.hide, wire), + showBars: curry(Bars.show, wire), + events: events.registry + }; + }; + + var create$2 = function (wire, vdirection) { + var hdirection = BarPositions.height; + var manager = BarManager(wire, vdirection, hdirection); + var events = Events.create({ + beforeResize: Event(['table']), + afterResize: Event(['table']), + startDrag: Event([]) + }); + manager.events.adjustHeight.bind(function (event) { + events.trigger.beforeResize(event.table()); + var delta = hdirection.delta(event.delta(), event.table()); + Adjustments.adjustHeight(event.table(), delta, event.row(), hdirection); + events.trigger.afterResize(event.table()); + }); + manager.events.startAdjust.bind(function (event) { + events.trigger.startDrag(); + }); + manager.events.adjustWidth.bind(function (event) { + events.trigger.beforeResize(event.table()); + var delta = vdirection.delta(event.delta(), event.table()); + Adjustments.adjustWidth(event.table(), delta, event.column(), vdirection); + events.trigger.afterResize(event.table()); + }); + return { + on: manager.on, + off: manager.off, + hideBars: manager.hideBars, + showBars: manager.showBars, + destroy: manager.destroy, + events: events.registry + }; + }; + var TableResize = { create: create$2 }; + + var createContainer = function () { + var container = Element.fromTag('div'); + setAll$1(container, { + position: 'static', + height: '0', + width: '0', + padding: '0', + margin: '0', + border: '0' + }); + append(body(), container); + return container; + }; + var get$9 = function (editor, container) { + return editor.inline ? ResizeWire.body(getBody$1(editor), createContainer()) : ResizeWire.only(Element.fromDom(editor.getDoc())); + }; + var remove$6 = function (editor, wire) { + if (editor.inline) { + remove$2(wire.parent()); + } + }; + var TableWire = { + get: get$9, + remove: remove$6 + }; + + var calculatePercentageWidth = function (element, parent) { + return getPixelWidth$1(element.dom()) / getPixelWidth$1(parent.dom()) * 100 + '%'; + }; + var enforcePercentage = function (rawTable) { + var table = Element.fromDom(rawTable); + parent(table).map(function (parent) { + return calculatePercentageWidth(table, parent); + }).each(function (tablePercentage) { + set$1(table, 'width', tablePercentage); + each(descendants$1(table, 'tr'), function (tr) { + each(children(tr), function (td) { + set$1(td, 'width', calculatePercentageWidth(td, tr)); + }); + }); + }); + }; + var enforcePixels = function (table) { + set$1(Element.fromDom(table), 'width', getPixelWidth$1(table).toString() + 'px'); + }; + + var getResizeHandler = function (editor) { + var selectionRng = Option.none(); + var resize = Option.none(); + var wire = Option.none(); + var percentageBasedSizeRegex = /(\d+(\.\d+)?)%/; + var startW; + var startRawW; + var isTable = function (elm) { + return elm.nodeName === 'TABLE'; + }; + var getRawWidth = function (elm) { + var raw = editor.dom.getStyle(elm, 'width') || editor.dom.getAttrib(elm, 'width'); + return Option.from(raw).filter(function (s) { + return s.length > 0; + }); + }; + var lazyResize = function () { + return resize; + }; + var lazyWire = function () { + return wire.getOr(ResizeWire.only(Element.fromDom(editor.getBody()))); + }; + var destroy = function () { + resize.each(function (sz) { + sz.destroy(); + }); + wire.each(function (w) { + TableWire.remove(editor, w); + }); + }; + editor.on('init', function () { + var direction = TableDirection(Direction.directionAt); + var rawWire = TableWire.get(editor); + wire = Option.some(rawWire); + if (hasObjectResizing(editor) && hasTableResizeBars(editor)) { + var sz = TableResize.create(rawWire, direction); + sz.on(); + sz.events.startDrag.bind(function (event) { + selectionRng = Option.some(editor.selection.getRng()); + }); + sz.events.beforeResize.bind(function (event) { + var rawTable = event.table().dom(); + fireObjectResizeStart(editor, rawTable, getPixelWidth$1(rawTable), getPixelHeight(rawTable)); + }); + sz.events.afterResize.bind(function (event) { + var table = event.table(); + var rawTable = table.dom(); + removeDataStyle(table); + selectionRng.each(function (rng) { + editor.selection.setRng(rng); + editor.focus(); + }); + fireObjectResized(editor, rawTable, getPixelWidth$1(rawTable), getPixelHeight(rawTable)); + editor.undoManager.add(); + }); + resize = Option.some(sz); + } + }); + editor.on('ObjectResizeStart', function (e) { + var targetElm = e.target; + if (isTable(targetElm)) { + var tableHasPercentage = getRawWidth(targetElm).map(function (w) { + return percentageBasedSizeRegex.test(w); + }).getOr(false); + if (tableHasPercentage && isPixelsForced(editor)) { + enforcePixels(targetElm); + } else if (!tableHasPercentage && isPercentagesForced(editor)) { + enforcePercentage(targetElm); + } + startW = e.width; + startRawW = getRawWidth(targetElm).getOr(''); + } + }); + editor.on('ObjectResized', function (e) { + var targetElm = e.target; + if (isTable(targetElm)) { + var table = targetElm; + if (percentageBasedSizeRegex.test(startRawW)) { + var percentW = parseFloat(percentageBasedSizeRegex.exec(startRawW)[1]); + var targetPercentW = e.width * percentW / startW; + editor.dom.setStyle(table, 'width', targetPercentW + '%'); + } else { + var newCellSizes_1 = []; + global$1.each(table.rows, function (row) { + global$1.each(row.cells, function (cell) { + var width = editor.dom.getStyle(cell, 'width', true); + newCellSizes_1.push({ + cell: cell, + width: width + }); + }); + }); + global$1.each(newCellSizes_1, function (newCellSize) { + editor.dom.setStyle(newCellSize.cell, 'width', newCellSize.width); + editor.dom.setAttrib(newCellSize.cell, 'width', null); + }); + } + } + }); + editor.on('SwitchMode', function () { + lazyResize().each(function (resize) { + if (editor.readonly) { + resize.hideBars(); + } else { + resize.showBars(); + } + }); + }); + return { + lazyResize: lazyResize, + lazyWire: lazyWire, + destroy: destroy + }; + }; + + var adt$1 = Adt.generate([ + { none: ['current'] }, + { first: ['current'] }, + { + middle: [ + 'current', + 'target' + ] + }, + { last: ['current'] } + ]); + var none$1 = function (current) { + if (current === void 0) { + current = undefined; + } + return adt$1.none(current); + }; + var CellLocation = __assign(__assign({}, adt$1), { none: none$1 }); + + var detect$4 = function (current, isRoot) { + return TableLookup.table(current, isRoot).bind(function (table) { + var all = TableLookup.cells(table); + var index = findIndex(all, function (x) { + return eq(current, x); + }); + return index.map(function (ind) { + return { + index: constant(ind), + all: constant(all) + }; + }); + }); + }; + var next = function (current, isRoot) { + var detection = detect$4(current, isRoot); + return detection.fold(function () { + return CellLocation.none(current); + }, function (info) { + return info.index() + 1 < info.all().length ? CellLocation.middle(current, info.all()[info.index() + 1]) : CellLocation.last(current); + }); + }; + var prev = function (current, isRoot) { + var detection = detect$4(current, isRoot); + return detection.fold(function () { + return CellLocation.none(); + }, function (info) { + return info.index() - 1 >= 0 ? CellLocation.middle(current, info.all()[info.index() - 1]) : CellLocation.first(current); + }); + }; + var CellNavigation = { + next: next, + prev: prev + }; + + var create$3 = Immutable('start', 'soffset', 'finish', 'foffset'); + var SimRange = { create: create$3 }; + + var adt$2 = Adt.generate([ + { before: ['element'] }, + { + on: [ + 'element', + 'offset' + ] + }, + { after: ['element'] } + ]); + var cata$1 = function (subject, onBefore, onOn, onAfter) { + return subject.fold(onBefore, onOn, onAfter); + }; + var getStart = function (situ) { + return situ.fold(identity, identity, identity); + }; + var before$2 = adt$2.before; + var on = adt$2.on; + var after$2 = adt$2.after; + var Situ = { + before: before$2, + on: on, + after: after$2, + cata: cata$1, + getStart: getStart + }; + + var adt$3 = Adt.generate([ + { domRange: ['rng'] }, + { + relative: [ + 'startSitu', + 'finishSitu' + ] + }, + { + exact: [ + 'start', + 'soffset', + 'finish', + 'foffset' + ] + } + ]); + var exactFromRange = function (simRange) { + return adt$3.exact(simRange.start(), simRange.soffset(), simRange.finish(), simRange.foffset()); + }; + var getStart$1 = function (selection) { + return selection.match({ + domRange: function (rng) { + return Element.fromDom(rng.startContainer); + }, + relative: function (startSitu, finishSitu) { + return Situ.getStart(startSitu); + }, + exact: function (start, soffset, finish, foffset) { + return start; + } + }); + }; + var domRange = adt$3.domRange; + var relative = adt$3.relative; + var exact = adt$3.exact; + var getWin = function (selection) { + var start = getStart$1(selection); + return defaultView(start); + }; + var range$1 = SimRange.create; + var Selection = { + domRange: domRange, + relative: relative, + exact: exact, + exactFromRange: exactFromRange, + getWin: getWin, + range: range$1 + }; + + var selectNodeContents = function (win, element) { + var rng = win.document.createRange(); + selectNodeContentsUsing(rng, element); + return rng; + }; + var selectNodeContentsUsing = function (rng, element) { + rng.selectNodeContents(element.dom()); + }; + var setStart = function (rng, situ) { + situ.fold(function (e) { + rng.setStartBefore(e.dom()); + }, function (e, o) { + rng.setStart(e.dom(), o); + }, function (e) { + rng.setStartAfter(e.dom()); + }); + }; + var setFinish = function (rng, situ) { + situ.fold(function (e) { + rng.setEndBefore(e.dom()); + }, function (e, o) { + rng.setEnd(e.dom(), o); + }, function (e) { + rng.setEndAfter(e.dom()); + }); + }; + var relativeToNative = function (win, startSitu, finishSitu) { + var range = win.document.createRange(); + setStart(range, startSitu); + setFinish(range, finishSitu); + return range; + }; + var exactToNative = function (win, start, soffset, finish, foffset) { + var rng = win.document.createRange(); + rng.setStart(start.dom(), soffset); + rng.setEnd(finish.dom(), foffset); + return rng; + }; + var toRect = function (rect) { + return { + left: constant(rect.left), + top: constant(rect.top), + right: constant(rect.right), + bottom: constant(rect.bottom), + width: constant(rect.width), + height: constant(rect.height) + }; + }; + var getFirstRect = function (rng) { + var rects = rng.getClientRects(); + var rect = rects.length > 0 ? rects[0] : rng.getBoundingClientRect(); + return rect.width > 0 || rect.height > 0 ? Option.some(rect).map(toRect) : Option.none(); + }; + + var adt$4 = Adt.generate([ + { + ltr: [ + 'start', + 'soffset', + 'finish', + 'foffset' + ] + }, + { + rtl: [ + 'start', + 'soffset', + 'finish', + 'foffset' + ] + } + ]); + var fromRange = function (win, type, range) { + return type(Element.fromDom(range.startContainer), range.startOffset, Element.fromDom(range.endContainer), range.endOffset); + }; + var getRanges = function (win, selection) { + return selection.match({ + domRange: function (rng) { + return { + ltr: constant(rng), + rtl: Option.none + }; + }, + relative: function (startSitu, finishSitu) { + return { + ltr: cached(function () { + return relativeToNative(win, startSitu, finishSitu); + }), + rtl: cached(function () { + return Option.some(relativeToNative(win, finishSitu, startSitu)); + }) + }; + }, + exact: function (start, soffset, finish, foffset) { + return { + ltr: cached(function () { + return exactToNative(win, start, soffset, finish, foffset); + }), + rtl: cached(function () { + return Option.some(exactToNative(win, finish, foffset, start, soffset)); + }) + }; + } + }); + }; + var doDiagnose = function (win, ranges) { + var rng = ranges.ltr(); + if (rng.collapsed) { + var reversed = ranges.rtl().filter(function (rev) { + return rev.collapsed === false; + }); + return reversed.map(function (rev) { + return adt$4.rtl(Element.fromDom(rev.endContainer), rev.endOffset, Element.fromDom(rev.startContainer), rev.startOffset); + }).getOrThunk(function () { + return fromRange(win, adt$4.ltr, rng); + }); + } else { + return fromRange(win, adt$4.ltr, rng); + } + }; + var diagnose = function (win, selection) { + var ranges = getRanges(win, selection); + return doDiagnose(win, ranges); + }; + var asLtrRange = function (win, selection) { + var diagnosis = diagnose(win, selection); + return diagnosis.match({ + ltr: function (start, soffset, finish, foffset) { + var rng = win.document.createRange(); + rng.setStart(start.dom(), soffset); + rng.setEnd(finish.dom(), foffset); + return rng; + }, + rtl: function (start, soffset, finish, foffset) { + var rng = win.document.createRange(); + rng.setStart(finish.dom(), foffset); + rng.setEnd(start.dom(), soffset); + return rng; + } + }); + }; + + var searchForPoint = function (rectForOffset, x, y, maxX, length) { + if (length === 0) { + return 0; + } else if (x === maxX) { + return length - 1; + } + var xDelta = maxX; + for (var i = 1; i < length; i++) { + var rect = rectForOffset(i); + var curDeltaX = Math.abs(x - rect.left); + if (y <= rect.bottom) { + if (y < rect.top || curDeltaX > xDelta) { + return i - 1; + } else { + xDelta = curDeltaX; + } + } + } + return 0; + }; + var inRect = function (rect, x, y) { + return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom; + }; + + var locateOffset = function (doc, textnode, x, y, rect) { + var rangeForOffset = function (o) { + var r = doc.dom().createRange(); + r.setStart(textnode.dom(), o); + r.collapse(true); + return r; + }; + var rectForOffset = function (o) { + var r = rangeForOffset(o); + return r.getBoundingClientRect(); + }; + var length = get$3(textnode).length; + var offset = searchForPoint(rectForOffset, x, y, rect.right, length); + return rangeForOffset(offset); + }; + var locate = function (doc, node, x, y) { + var r = doc.dom().createRange(); + r.selectNode(node.dom()); + var rects = r.getClientRects(); + var foundRect = findMap(rects, function (rect) { + return inRect(rect, x, y) ? Option.some(rect) : Option.none(); + }); + return foundRect.map(function (rect) { + return locateOffset(doc, node, x, y, rect); + }); + }; + + var searchInChildren = function (doc, node, x, y) { + var r = doc.dom().createRange(); + var nodes = children(node); + return findMap(nodes, function (n) { + r.selectNode(n.dom()); + return inRect(r.getBoundingClientRect(), x, y) ? locateNode(doc, n, x, y) : Option.none(); + }); + }; + var locateNode = function (doc, node, x, y) { + return isText(node) ? locate(doc, node, x, y) : searchInChildren(doc, node, x, y); + }; + var locate$1 = function (doc, node, x, y) { + var r = doc.dom().createRange(); + r.selectNode(node.dom()); + var rect = r.getBoundingClientRect(); + var boundedX = Math.max(rect.left, Math.min(rect.right, x)); + var boundedY = Math.max(rect.top, Math.min(rect.bottom, y)); + return locateNode(doc, node, boundedX, boundedY); + }; + + var COLLAPSE_TO_LEFT = true; + var COLLAPSE_TO_RIGHT = false; + var getCollapseDirection = function (rect, x) { + return x - rect.left < rect.right - x ? COLLAPSE_TO_LEFT : COLLAPSE_TO_RIGHT; + }; + var createCollapsedNode = function (doc, target, collapseDirection) { + var r = doc.dom().createRange(); + r.selectNode(target.dom()); + r.collapse(collapseDirection); + return r; + }; + var locateInElement = function (doc, node, x) { + var cursorRange = doc.dom().createRange(); + cursorRange.selectNode(node.dom()); + var rect = cursorRange.getBoundingClientRect(); + var collapseDirection = getCollapseDirection(rect, x); + var f = collapseDirection === COLLAPSE_TO_LEFT ? first : last$1; + return f(node).map(function (target) { + return createCollapsedNode(doc, target, collapseDirection); + }); + }; + var locateInEmpty = function (doc, node, x) { + var rect = node.dom().getBoundingClientRect(); + var collapseDirection = getCollapseDirection(rect, x); + return Option.some(createCollapsedNode(doc, node, collapseDirection)); + }; + var search = function (doc, node, x) { + var f = children(node).length === 0 ? locateInEmpty : locateInElement; + return f(doc, node, x); + }; + + var caretPositionFromPoint = function (doc, x, y) { + return Option.from(doc.dom().caretPositionFromPoint(x, y)).bind(function (pos) { + if (pos.offsetNode === null) { + return Option.none(); + } + var r = doc.dom().createRange(); + r.setStart(pos.offsetNode, pos.offset); + r.collapse(); + return Option.some(r); + }); + }; + var caretRangeFromPoint = function (doc, x, y) { + return Option.from(doc.dom().caretRangeFromPoint(x, y)); + }; + var searchTextNodes = function (doc, node, x, y) { + var r = doc.dom().createRange(); + r.selectNode(node.dom()); + var rect = r.getBoundingClientRect(); + var boundedX = Math.max(rect.left, Math.min(rect.right, x)); + var boundedY = Math.max(rect.top, Math.min(rect.bottom, y)); + return locate$1(doc, node, boundedX, boundedY); + }; + var searchFromPoint = function (doc, x, y) { + return Element.fromPoint(doc, x, y).bind(function (elem) { + var fallback = function () { + return search(doc, elem, x); + }; + return children(elem).length === 0 ? fallback() : searchTextNodes(doc, elem, x, y).orThunk(fallback); + }); + }; + var availableSearch = document.caretPositionFromPoint ? caretPositionFromPoint : document.caretRangeFromPoint ? caretRangeFromPoint : searchFromPoint; + var fromPoint$1 = function (win, x, y) { + var doc = Element.fromDom(win.document); + return availableSearch(doc, x, y).map(function (rng) { + return SimRange.create(Element.fromDom(rng.startContainer), rng.startOffset, Element.fromDom(rng.endContainer), rng.endOffset); + }); + }; + + var beforeSpecial = function (element, offset) { + var name$1 = name(element); + if ('input' === name$1) { + return Situ.after(element); + } else if (!contains([ + 'br', + 'img' + ], name$1)) { + return Situ.on(element, offset); + } else { + return offset === 0 ? Situ.before(element) : Situ.after(element); + } + }; + var preprocessRelative = function (startSitu, finishSitu) { + var start = startSitu.fold(Situ.before, beforeSpecial, Situ.after); + var finish = finishSitu.fold(Situ.before, beforeSpecial, Situ.after); + return Selection.relative(start, finish); + }; + var preprocessExact = function (start, soffset, finish, foffset) { + var startSitu = beforeSpecial(start, soffset); + var finishSitu = beforeSpecial(finish, foffset); + return Selection.relative(startSitu, finishSitu); + }; + var preprocess = function (selection) { + return selection.match({ + domRange: function (rng) { + var start = Element.fromDom(rng.startContainer); + var finish = Element.fromDom(rng.endContainer); + return preprocessExact(start, rng.startOffset, finish, rng.endOffset); + }, + relative: preprocessRelative, + exact: preprocessExact + }); + }; + + var makeRange = function (start, soffset, finish, foffset) { + var doc = owner(start); + var rng = doc.dom().createRange(); + rng.setStart(start.dom(), soffset); + rng.setEnd(finish.dom(), foffset); + return rng; + }; + var after$3 = function (start, soffset, finish, foffset) { + var r = makeRange(start, soffset, finish, foffset); + var same = eq(start, finish) && soffset === foffset; + return r.collapsed && !same; + }; + + var doSetNativeRange = function (win, rng) { + Option.from(win.getSelection()).each(function (selection) { + selection.removeAllRanges(); + selection.addRange(rng); + }); + }; + var doSetRange = function (win, start, soffset, finish, foffset) { + var rng = exactToNative(win, start, soffset, finish, foffset); + doSetNativeRange(win, rng); + }; + var setLegacyRtlRange = function (win, selection, start, soffset, finish, foffset) { + selection.collapse(start.dom(), soffset); + selection.extend(finish.dom(), foffset); + }; + var setRangeFromRelative = function (win, relative) { + return diagnose(win, relative).match({ + ltr: function (start, soffset, finish, foffset) { + doSetRange(win, start, soffset, finish, foffset); + }, + rtl: function (start, soffset, finish, foffset) { + var selection = win.getSelection(); + if (selection.setBaseAndExtent) { + selection.setBaseAndExtent(start.dom(), soffset, finish.dom(), foffset); + } else if (selection.extend) { + try { + setLegacyRtlRange(win, selection, start, soffset, finish, foffset); + } catch (e) { + doSetRange(win, finish, foffset, start, soffset); + } + } else { + doSetRange(win, finish, foffset, start, soffset); + } + } + }); + }; + var setExact = function (win, start, soffset, finish, foffset) { + var relative = preprocessExact(start, soffset, finish, foffset); + setRangeFromRelative(win, relative); + }; + var setRelative = function (win, startSitu, finishSitu) { + var relative = preprocessRelative(startSitu, finishSitu); + setRangeFromRelative(win, relative); + }; + var toNative = function (selection) { + var win = Selection.getWin(selection).dom(); + var getDomRange = function (start, soffset, finish, foffset) { + return exactToNative(win, start, soffset, finish, foffset); + }; + var filtered = preprocess(selection); + return diagnose(win, filtered).match({ + ltr: getDomRange, + rtl: getDomRange + }); + }; + var readRange = function (selection) { + if (selection.rangeCount > 0) { + var firstRng = selection.getRangeAt(0); + var lastRng = selection.getRangeAt(selection.rangeCount - 1); + return Option.some(SimRange.create(Element.fromDom(firstRng.startContainer), firstRng.startOffset, Element.fromDom(lastRng.endContainer), lastRng.endOffset)); + } else { + return Option.none(); + } + }; + var doGetExact = function (selection) { + var anchor = Element.fromDom(selection.anchorNode); + var focus = Element.fromDom(selection.focusNode); + return after$3(anchor, selection.anchorOffset, focus, selection.focusOffset) ? Option.some(SimRange.create(anchor, selection.anchorOffset, focus, selection.focusOffset)) : readRange(selection); + }; + var setToElement = function (win, element) { + var rng = selectNodeContents(win, element); + doSetNativeRange(win, rng); + }; + var getExact = function (win) { + return Option.from(win.getSelection()).filter(function (sel) { + return sel.rangeCount > 0; + }).bind(doGetExact); + }; + var get$a = function (win) { + return getExact(win).map(function (range) { + return Selection.exact(range.start(), range.soffset(), range.finish(), range.foffset()); + }); + }; + var getFirstRect$1 = function (win, selection) { + var rng = asLtrRange(win, selection); + return getFirstRect(rng); + }; + var getAtPoint = function (win, x, y) { + return fromPoint$1(win, x, y); + }; + var clear = function (win) { + var selection = win.getSelection(); + selection.removeAllRanges(); + }; + + var global$3 = tinymce.util.Tools.resolve('tinymce.util.VK'); + + var forward = function (editor, isRoot, cell, lazyWire) { + return go(editor, isRoot, CellNavigation.next(cell), lazyWire); + }; + var backward = function (editor, isRoot, cell, lazyWire) { + return go(editor, isRoot, CellNavigation.prev(cell), lazyWire); + }; + var getCellFirstCursorPosition = function (editor, cell) { + var selection = Selection.exact(cell, 0, cell, 0); + return toNative(selection); + }; + var getNewRowCursorPosition = function (editor, table) { + var rows = descendants$1(table, 'tr'); + return last(rows).bind(function (last) { + return descendant$1(last, 'td,th').map(function (first) { + return getCellFirstCursorPosition(editor, first); + }); + }); + }; + var go = function (editor, isRoot, cell, actions, lazyWire) { + return cell.fold(Option.none, Option.none, function (current, next) { + return first(next).map(function (cell) { + return getCellFirstCursorPosition(editor, cell); + }); + }, function (current) { + return TableLookup.table(current, isRoot).bind(function (table) { + var targets = TableTargets.noMenu(current); + editor.undoManager.transact(function () { + actions.insertRowsAfter(table, targets); + }); + return getNewRowCursorPosition(editor, table); + }); + }); + }; + var rootElements = [ + 'table', + 'li', + 'dl' + ]; + var handle$1 = function (event, editor, actions, lazyWire) { + if (event.keyCode === global$3.TAB) { + var body_1 = getBody$1(editor); + var isRoot_1 = function (element) { + var name$1 = name(element); + return eq(element, body_1) || contains(rootElements, name$1); + }; + var rng = editor.selection.getRng(); + if (rng.collapsed) { + var start = Element.fromDom(rng.startContainer); + TableLookup.cell(start, isRoot_1).each(function (cell) { + event.preventDefault(); + var navigation = event.shiftKey ? backward : forward; + var rng = navigation(editor, isRoot_1, cell, actions, lazyWire); + rng.each(function (range) { + editor.selection.setRng(range); + }); + }); + } + } + }; + var TabContext = { handle: handle$1 }; + + var create$4 = Immutable('selection', 'kill'); + var Response = { create: create$4 }; + + var create$5 = function (start, soffset, finish, foffset) { + return { + start: constant(Situ.on(start, soffset)), + finish: constant(Situ.on(finish, foffset)) + }; + }; + var Situs = { create: create$5 }; + + var convertToRange = function (win, selection) { + var rng = asLtrRange(win, selection); + return SimRange.create(Element.fromDom(rng.startContainer), rng.startOffset, Element.fromDom(rng.endContainer), rng.endOffset); + }; + var makeSitus = Situs.create; + var Util = { + convertToRange: convertToRange, + makeSitus: makeSitus + }; + + var sync = function (container, isRoot, start, soffset, finish, foffset, selectRange) { + if (!(eq(start, finish) && soffset === foffset)) { + return closest$1(start, 'td,th', isRoot).bind(function (s) { + return closest$1(finish, 'td,th', isRoot).bind(function (f) { + return detect$5(container, isRoot, s, f, selectRange); + }); + }); + } else { + return Option.none(); + } + }; + var detect$5 = function (container, isRoot, start, finish, selectRange) { + if (!eq(start, finish)) { + return CellSelection.identify(start, finish, isRoot).bind(function (cellSel) { + var boxes = cellSel.boxes().getOr([]); + if (boxes.length > 0) { + selectRange(container, boxes, cellSel.start(), cellSel.finish()); + return Option.some(Response.create(Option.some(Util.makeSitus(start, 0, start, getEnd(start))), true)); + } else { + return Option.none(); + } + }); + } else { + return Option.none(); + } + }; + var update = function (rows, columns, container, selected, annotations) { + var updateSelection = function (newSels) { + annotations.clearBeforeUpdate(container); + annotations.selectRange(container, newSels.boxes(), newSels.start(), newSels.finish()); + return newSels.boxes(); + }; + return CellSelection.shiftSelection(selected, rows, columns, annotations.firstSelectedSelector(), annotations.lastSelectedSelector()).map(updateSelection); + }; + var KeySelection = { + sync: sync, + detect: detect$5, + update: update + }; + + var traverse = Immutable('item', 'mode'); + var backtrack = function (universe, item, _direction, transition) { + if (transition === void 0) { + transition = sidestep; + } + return universe.property().parent(item).map(function (p) { + return traverse(p, transition); + }); + }; + var sidestep = function (universe, item, direction, transition) { + if (transition === void 0) { + transition = advance; + } + return direction.sibling(universe, item).map(function (p) { + return traverse(p, transition); + }); + }; + var advance = function (universe, item, direction, transition) { + if (transition === void 0) { + transition = advance; + } + var children = universe.property().children(item); + var result = direction.first(children); + return result.map(function (r) { + return traverse(r, transition); + }); + }; + var successors = [ + { + current: backtrack, + next: sidestep, + fallback: Option.none() + }, + { + current: sidestep, + next: advance, + fallback: Option.some(backtrack) + }, + { + current: advance, + next: advance, + fallback: Option.some(sidestep) + } + ]; + var go$1 = function (universe, item, mode, direction, rules) { + if (rules === void 0) { + rules = successors; + } + var ruleOpt = find(rules, function (succ) { + return succ.current === mode; + }); + return ruleOpt.bind(function (rule) { + return rule.current(universe, item, direction, rule.next).orThunk(function () { + return rule.fallback.bind(function (fb) { + return go$1(universe, item, fb, direction); + }); + }); + }); + }; + + var left = function () { + var sibling = function (universe, item) { + return universe.query().prevSibling(item); + }; + var first = function (children) { + return children.length > 0 ? Option.some(children[children.length - 1]) : Option.none(); + }; + return { + sibling: sibling, + first: first + }; + }; + var right = function () { + var sibling = function (universe, item) { + return universe.query().nextSibling(item); + }; + var first = function (children) { + return children.length > 0 ? Option.some(children[0]) : Option.none(); + }; + return { + sibling: sibling, + first: first + }; + }; + var Walkers = { + left: left, + right: right + }; + + var hone = function (universe, item, predicate, mode, direction, isRoot) { + var next = go$1(universe, item, mode, direction); + return next.bind(function (n) { + if (isRoot(n.item())) { + return Option.none(); + } else { + return predicate(n.item()) ? Option.some(n.item()) : hone(universe, n.item(), predicate, n.mode(), direction, isRoot); + } + }); + }; + var left$1 = function (universe, item, predicate, isRoot) { + return hone(universe, item, predicate, sidestep, Walkers.left(), isRoot); + }; + var right$1 = function (universe, item, predicate, isRoot) { + return hone(universe, item, predicate, sidestep, Walkers.right(), isRoot); + }; + + var isLeaf = function (universe) { + return function (element) { + return universe.property().children(element).length === 0; + }; + }; + var before$3 = function (universe, item, isRoot) { + return seekLeft(universe, item, isLeaf(universe), isRoot); + }; + var after$4 = function (universe, item, isRoot) { + return seekRight(universe, item, isLeaf(universe), isRoot); + }; + var seekLeft = left$1; + var seekRight = right$1; + + var universe$2 = DomUniverse(); + var before$4 = function (element, isRoot) { + return before$3(universe$2, element, isRoot); + }; + var after$5 = function (element, isRoot) { + return after$4(universe$2, element, isRoot); + }; + var seekLeft$1 = function (element, predicate, isRoot) { + return seekLeft(universe$2, element, predicate, isRoot); + }; + var seekRight$1 = function (element, predicate, isRoot) { + return seekRight(universe$2, element, predicate, isRoot); + }; + + var ancestor$2 = function (scope, predicate, isRoot) { + return ancestor(scope, predicate, isRoot).isSome(); + }; + + var point = Immutable('element', 'offset'); + var delta = Immutable('element', 'deltaOffset'); + var range$2 = Immutable('element', 'start', 'finish'); + var points = Immutable('begin', 'end'); + var text = Immutable('element', 'text'); + + var adt$5 = Adt.generate([ + { none: ['message'] }, + { success: [] }, + { failedUp: ['cell'] }, + { failedDown: ['cell'] } + ]); + var isOverlapping = function (bridge, before, after) { + var beforeBounds = bridge.getRect(before); + var afterBounds = bridge.getRect(after); + return afterBounds.right > beforeBounds.left && afterBounds.left < beforeBounds.right; + }; + var isRow = function (elem) { + return closest$1(elem, 'tr'); + }; + var verify = function (bridge, before, beforeOffset, after, afterOffset, failure, isRoot) { + return closest$1(after, 'td,th', isRoot).bind(function (afterCell) { + return closest$1(before, 'td,th', isRoot).map(function (beforeCell) { + if (!eq(afterCell, beforeCell)) { + return DomParent.sharedOne(isRow, [ + afterCell, + beforeCell + ]).fold(function () { + return isOverlapping(bridge, beforeCell, afterCell) ? adt$5.success() : failure(beforeCell); + }, function (_sharedRow) { + return failure(beforeCell); + }); + } else { + return eq(after, afterCell) && getEnd(afterCell) === afterOffset ? failure(beforeCell) : adt$5.none('in same cell'); + } + }); + }).getOr(adt$5.none('default')); + }; + var cata$2 = function (subject, onNone, onSuccess, onFailedUp, onFailedDown) { + return subject.fold(onNone, onSuccess, onFailedUp, onFailedDown); + }; + var BeforeAfter = __assign(__assign({}, adt$5), { + verify: verify, + cata: cata$2 + }); + + var inAncestor = Immutable('ancestor', 'descendants', 'element', 'index'); + var inParent = Immutable('parent', 'children', 'element', 'index'); + var indexInParent = function (element) { + return parent(element).bind(function (parent) { + var children$1 = children(parent); + return indexOf(children$1, element).map(function (index) { + return inParent(parent, children$1, element, index); + }); + }); + }; + var indexOf = function (elements, element) { + return findIndex(elements, curry(eq, element)); + }; + + var isBr = function (elem) { + return name(elem) === 'br'; + }; + var gatherer = function (cand, gather, isRoot) { + return gather(cand, isRoot).bind(function (target) { + return isText(target) && get$3(target).trim().length === 0 ? gatherer(target, gather, isRoot) : Option.some(target); + }); + }; + var handleBr = function (isRoot, element, direction) { + return direction.traverse(element).orThunk(function () { + return gatherer(element, direction.gather, isRoot); + }).map(direction.relative); + }; + var findBr = function (element, offset) { + return child(element, offset).filter(isBr).orThunk(function () { + return child(element, offset - 1).filter(isBr); + }); + }; + var handleParent = function (isRoot, element, offset, direction) { + return findBr(element, offset).bind(function (br) { + return direction.traverse(br).fold(function () { + return gatherer(br, direction.gather, isRoot).map(direction.relative); + }, function (adjacent) { + return indexInParent(adjacent).map(function (info) { + return Situ.on(info.parent(), info.index()); + }); + }); + }); + }; + var tryBr = function (isRoot, element, offset, direction) { + var target = isBr(element) ? handleBr(isRoot, element, direction) : handleParent(isRoot, element, offset, direction); + return target.map(function (tgt) { + return { + start: constant(tgt), + finish: constant(tgt) + }; + }); + }; + var process = function (analysis) { + return BeforeAfter.cata(analysis, function (message) { + return Option.none(); + }, function () { + return Option.none(); + }, function (cell) { + return Option.some(point(cell, 0)); + }, function (cell) { + return Option.some(point(cell, getEnd(cell))); + }); + }; + var BrTags = { + tryBr: tryBr, + process: process + }; + + var nu$3 = MixedBag([ + 'left', + 'top', + 'right', + 'bottom' + ], []); + var moveDown = function (caret, amount) { + return nu$3({ + left: caret.left(), + top: caret.top() + amount, + right: caret.right(), + bottom: caret.bottom() + amount + }); + }; + var moveUp = function (caret, amount) { + return nu$3({ + left: caret.left(), + top: caret.top() - amount, + right: caret.right(), + bottom: caret.bottom() - amount + }); + }; + var moveBottomTo = function (caret, bottom) { + var height = caret.bottom() - caret.top(); + return nu$3({ + left: caret.left(), + top: bottom - height, + right: caret.right(), + bottom: bottom + }); + }; + var moveTopTo = function (caret, top) { + var height = caret.bottom() - caret.top(); + return nu$3({ + left: caret.left(), + top: top, + right: caret.right(), + bottom: top + height + }); + }; + var translate = function (caret, xDelta, yDelta) { + return nu$3({ + left: caret.left() + xDelta, + top: caret.top() + yDelta, + right: caret.right() + xDelta, + bottom: caret.bottom() + yDelta + }); + }; + var getTop$1 = function (caret) { + return caret.top(); + }; + var getBottom = function (caret) { + return caret.bottom(); + }; + var toString = function (caret) { + return '(' + caret.left() + ', ' + caret.top() + ') -> (' + caret.right() + ', ' + caret.bottom() + ')'; + }; + var Carets = { + nu: nu$3, + moveUp: moveUp, + moveDown: moveDown, + moveBottomTo: moveBottomTo, + moveTopTo: moveTopTo, + getTop: getTop$1, + getBottom: getBottom, + translate: translate, + toString: toString + }; + + var getPartialBox = function (bridge, element, offset) { + if (offset >= 0 && offset < getEnd(element)) { + return bridge.getRangedRect(element, offset, element, offset + 1); + } else if (offset > 0) { + return bridge.getRangedRect(element, offset - 1, element, offset); + } + return Option.none(); + }; + var toCaret = function (rect) { + return Carets.nu({ + left: rect.left, + top: rect.top, + right: rect.right, + bottom: rect.bottom + }); + }; + var getElemBox = function (bridge, element) { + return Option.some(bridge.getRect(element)); + }; + var getBoxAt = function (bridge, element, offset) { + if (isElement(element)) { + return getElemBox(bridge, element).map(toCaret); + } else if (isText(element)) { + return getPartialBox(bridge, element, offset).map(toCaret); + } else { + return Option.none(); + } + }; + var getEntireBox = function (bridge, element) { + if (isElement(element)) { + return getElemBox(bridge, element).map(toCaret); + } else if (isText(element)) { + return bridge.getRangedRect(element, 0, element, getEnd(element)).map(toCaret); + } else { + return Option.none(); + } + }; + var Rectangles = { + getBoxAt: getBoxAt, + getEntireBox: getEntireBox + }; + + var JUMP_SIZE = 5; + var NUM_RETRIES = 100; + var adt$6 = Adt.generate([ + { none: [] }, + { retry: ['caret'] } + ]); + var isOutside = function (caret, box) { + return caret.left() < box.left() || Math.abs(box.right() - caret.left()) < 1 || caret.left() > box.right(); + }; + var inOutsideBlock = function (bridge, element, caret) { + return closest(element, DomStructure.isBlock).fold(constant(false), function (cell) { + return Rectangles.getEntireBox(bridge, cell).exists(function (box) { + return isOutside(caret, box); + }); + }); + }; + var adjustDown = function (bridge, element, guessBox, original, caret) { + var lowerCaret = Carets.moveDown(caret, JUMP_SIZE); + if (Math.abs(guessBox.bottom() - original.bottom()) < 1) { + return adt$6.retry(lowerCaret); + } else if (guessBox.top() > caret.bottom()) { + return adt$6.retry(lowerCaret); + } else if (guessBox.top() === caret.bottom()) { + return adt$6.retry(Carets.moveDown(caret, 1)); + } else { + return inOutsideBlock(bridge, element, caret) ? adt$6.retry(Carets.translate(lowerCaret, JUMP_SIZE, 0)) : adt$6.none(); + } + }; + var adjustUp = function (bridge, element, guessBox, original, caret) { + var higherCaret = Carets.moveUp(caret, JUMP_SIZE); + if (Math.abs(guessBox.top() - original.top()) < 1) { + return adt$6.retry(higherCaret); + } else if (guessBox.bottom() < caret.top()) { + return adt$6.retry(higherCaret); + } else if (guessBox.bottom() === caret.top()) { + return adt$6.retry(Carets.moveUp(caret, 1)); + } else { + return inOutsideBlock(bridge, element, caret) ? adt$6.retry(Carets.translate(higherCaret, JUMP_SIZE, 0)) : adt$6.none(); + } + }; + var upMovement = { + point: Carets.getTop, + adjuster: adjustUp, + move: Carets.moveUp, + gather: before$4 + }; + var downMovement = { + point: Carets.getBottom, + adjuster: adjustDown, + move: Carets.moveDown, + gather: after$5 + }; + var isAtTable = function (bridge, x, y) { + return bridge.elementFromPoint(x, y).filter(function (elm) { + return name(elm) === 'table'; + }).isSome(); + }; + var adjustForTable = function (bridge, movement, original, caret, numRetries) { + return adjustTil(bridge, movement, original, movement.move(caret, JUMP_SIZE), numRetries); + }; + var adjustTil = function (bridge, movement, original, caret, numRetries) { + if (numRetries === 0) { + return Option.some(caret); + } + if (isAtTable(bridge, caret.left(), movement.point(caret))) { + return adjustForTable(bridge, movement, original, caret, numRetries - 1); + } + return bridge.situsFromPoint(caret.left(), movement.point(caret)).bind(function (guess) { + return guess.start().fold(Option.none, function (element) { + return Rectangles.getEntireBox(bridge, element).bind(function (guessBox) { + return movement.adjuster(bridge, element, guessBox, original, caret).fold(Option.none, function (newCaret) { + return adjustTil(bridge, movement, original, newCaret, numRetries - 1); + }); + }).orThunk(function () { + return Option.some(caret); + }); + }, Option.none); + }); + }; + var ieTryDown = function (bridge, caret) { + return bridge.situsFromPoint(caret.left(), caret.bottom() + JUMP_SIZE); + }; + var ieTryUp = function (bridge, caret) { + return bridge.situsFromPoint(caret.left(), caret.top() - JUMP_SIZE); + }; + var checkScroll = function (movement, adjusted, bridge) { + if (movement.point(adjusted) > bridge.getInnerHeight()) { + return Option.some(movement.point(adjusted) - bridge.getInnerHeight()); + } else if (movement.point(adjusted) < 0) { + return Option.some(-movement.point(adjusted)); + } else { + return Option.none(); + } + }; + var retry = function (movement, bridge, caret) { + var moved = movement.move(caret, JUMP_SIZE); + var adjusted = adjustTil(bridge, movement, caret, moved, NUM_RETRIES).getOr(moved); + return checkScroll(movement, adjusted, bridge).fold(function () { + return bridge.situsFromPoint(adjusted.left(), movement.point(adjusted)); + }, function (delta) { + bridge.scrollBy(0, delta); + return bridge.situsFromPoint(adjusted.left(), movement.point(adjusted) - delta); + }); + }; + var Retries = { + tryUp: curry(retry, upMovement), + tryDown: curry(retry, downMovement), + ieTryUp: ieTryUp, + ieTryDown: ieTryDown, + getJumpSize: constant(JUMP_SIZE) + }; + + var MAX_RETRIES = 20; + var platform$2 = detect$3(); + var findSpot = function (bridge, isRoot, direction) { + return bridge.getSelection().bind(function (sel) { + return BrTags.tryBr(isRoot, sel.finish(), sel.foffset(), direction).fold(function () { + return Option.some(point(sel.finish(), sel.foffset())); + }, function (brNeighbour) { + var range = bridge.fromSitus(brNeighbour); + var analysis = BeforeAfter.verify(bridge, sel.finish(), sel.foffset(), range.finish(), range.foffset(), direction.failure, isRoot); + return BrTags.process(analysis); + }); + }); + }; + var scan = function (bridge, isRoot, element, offset, direction, numRetries) { + if (numRetries === 0) { + return Option.none(); + } + return tryCursor(bridge, isRoot, element, offset, direction).bind(function (situs) { + var range = bridge.fromSitus(situs); + var analysis = BeforeAfter.verify(bridge, element, offset, range.finish(), range.foffset(), direction.failure, isRoot); + return BeforeAfter.cata(analysis, function () { + return Option.none(); + }, function () { + return Option.some(situs); + }, function (cell) { + if (eq(element, cell) && offset === 0) { + return tryAgain(bridge, element, offset, Carets.moveUp, direction); + } else { + return scan(bridge, isRoot, cell, 0, direction, numRetries - 1); + } + }, function (cell) { + if (eq(element, cell) && offset === getEnd(cell)) { + return tryAgain(bridge, element, offset, Carets.moveDown, direction); + } else { + return scan(bridge, isRoot, cell, getEnd(cell), direction, numRetries - 1); + } + }); + }); + }; + var tryAgain = function (bridge, element, offset, move, direction) { + return Rectangles.getBoxAt(bridge, element, offset).bind(function (box) { + return tryAt(bridge, direction, move(box, Retries.getJumpSize())); + }); + }; + var tryAt = function (bridge, direction, box) { + if (platform$2.browser.isChrome() || platform$2.browser.isSafari() || platform$2.browser.isFirefox() || platform$2.browser.isEdge()) { + return direction.otherRetry(bridge, box); + } else if (platform$2.browser.isIE()) { + return direction.ieRetry(bridge, box); + } else { + return Option.none(); + } + }; + var tryCursor = function (bridge, isRoot, element, offset, direction) { + return Rectangles.getBoxAt(bridge, element, offset).bind(function (box) { + return tryAt(bridge, direction, box); + }); + }; + var handle$2 = function (bridge, isRoot, direction) { + return findSpot(bridge, isRoot, direction).bind(function (spot) { + return scan(bridge, isRoot, spot.element(), spot.offset(), direction, MAX_RETRIES).map(bridge.fromSitus); + }); + }; + var TableKeys = { handle: handle$2 }; + + var detection = detect$3(); + var inSameTable = function (elem, table) { + return ancestor$2(elem, function (e) { + return parent(e).exists(function (p) { + return eq(p, table); + }); + }); + }; + var simulate = function (bridge, isRoot, direction, initial, anchor) { + return closest$1(initial, 'td,th', isRoot).bind(function (start) { + return closest$1(start, 'table', isRoot).bind(function (table) { + if (!inSameTable(anchor, table)) { + return Option.none(); + } + return TableKeys.handle(bridge, isRoot, direction).bind(function (range) { + return closest$1(range.finish(), 'td,th', isRoot).map(function (finish) { + return { + start: constant(start), + finish: constant(finish), + range: constant(range) + }; + }); + }); + }); + }); + }; + var navigate = function (bridge, isRoot, direction, initial, anchor, precheck) { + if (detection.browser.isIE()) { + return Option.none(); + } else { + return precheck(initial, isRoot).orThunk(function () { + return simulate(bridge, isRoot, direction, initial, anchor).map(function (info) { + var range = info.range(); + return Response.create(Option.some(Util.makeSitus(range.start(), range.soffset(), range.finish(), range.foffset())), true); + }); + }); + } + }; + var firstUpCheck = function (initial, isRoot) { + return closest$1(initial, 'tr', isRoot).bind(function (startRow) { + return closest$1(startRow, 'table', isRoot).bind(function (table) { + var rows = descendants$1(table, 'tr'); + if (eq(startRow, rows[0])) { + return seekLeft$1(table, function (element) { + return last$1(element).isSome(); + }, isRoot).map(function (last) { + var lastOffset = getEnd(last); + return Response.create(Option.some(Util.makeSitus(last, lastOffset, last, lastOffset)), true); + }); + } else { + return Option.none(); + } + }); + }); + }; + var lastDownCheck = function (initial, isRoot) { + return closest$1(initial, 'tr', isRoot).bind(function (startRow) { + return closest$1(startRow, 'table', isRoot).bind(function (table) { + var rows = descendants$1(table, 'tr'); + if (eq(startRow, rows[rows.length - 1])) { + return seekRight$1(table, function (element) { + return first(element).isSome(); + }, isRoot).map(function (first) { + return Response.create(Option.some(Util.makeSitus(first, 0, first, 0)), true); + }); + } else { + return Option.none(); + } + }); + }); + }; + var select = function (bridge, container, isRoot, direction, initial, anchor, selectRange) { + return simulate(bridge, isRoot, direction, initial, anchor).bind(function (info) { + return KeySelection.detect(container, isRoot, info.start(), info.finish(), selectRange); + }); + }; + var VerticalMovement = { + navigate: navigate, + select: select, + firstUpCheck: firstUpCheck, + lastDownCheck: lastDownCheck + }; + + var findCell = function (target, isRoot) { + return closest$1(target, 'td,th', isRoot); + }; + function MouseSelection (bridge, container, isRoot, annotations) { + var cursor = Option.none(); + var clearState = function () { + cursor = Option.none(); + }; + var mousedown = function (event) { + annotations.clear(container); + cursor = findCell(event.target(), isRoot); + }; + var mouseover = function (event) { + cursor.each(function (start) { + annotations.clearBeforeUpdate(container); + findCell(event.target(), isRoot).each(function (finish) { + CellSelection.identify(start, finish, isRoot).each(function (cellSel) { + var boxes = cellSel.boxes().getOr([]); + if (boxes.length > 1 || boxes.length === 1 && !eq(start, finish)) { + annotations.selectRange(container, boxes, cellSel.start(), cellSel.finish()); + bridge.selectContents(finish); + } + }); + }); + }); + }; + var mouseup = function (_event) { + cursor.each(clearState); + }; + return { + mousedown: mousedown, + mouseover: mouseover, + mouseup: mouseup + }; + } + + var down = { + traverse: nextSibling, + gather: after$5, + relative: Situ.before, + otherRetry: Retries.tryDown, + ieRetry: Retries.ieTryDown, + failure: BeforeAfter.failedDown + }; + var up = { + traverse: prevSibling, + gather: before$4, + relative: Situ.before, + otherRetry: Retries.tryUp, + ieRetry: Retries.ieTryUp, + failure: BeforeAfter.failedUp + }; + var KeyDirection = { + down: down, + up: up + }; + + var isKey = function (key) { + return function (keycode) { + return keycode === key; + }; + }; + var isUp = isKey(38); + var isDown = isKey(40); + var isNavigation = function (keycode) { + return keycode >= 37 && keycode <= 40; + }; + var SelectionKeys = { + ltr: { + isBackward: isKey(37), + isForward: isKey(39) + }, + rtl: { + isBackward: isKey(39), + isForward: isKey(37) + }, + isUp: isUp, + isDown: isDown, + isNavigation: isNavigation + }; + + var toRaw = function (sr) { + return { + left: sr.left(), + top: sr.top(), + right: sr.right(), + bottom: sr.bottom(), + width: sr.width(), + height: sr.height() + }; + }; + var Rect = { toRaw: toRaw }; + + var isSafari = detect$3().browser.isSafari(); + var get$b = function (_DOC) { + var doc = _DOC !== undefined ? _DOC.dom() : domGlobals.document; + var x = doc.body.scrollLeft || doc.documentElement.scrollLeft; + var y = doc.body.scrollTop || doc.documentElement.scrollTop; + return Position(x, y); + }; + var by = function (x, y, _DOC) { + var doc = _DOC !== undefined ? _DOC.dom() : domGlobals.document; + var win = doc.defaultView; + win.scrollBy(x, y); + }; + + var WindowBridge = function (win) { + var elementFromPoint = function (x, y) { + return Element.fromPoint(Element.fromDom(win.document), x, y); + }; + var getRect = function (element) { + return element.dom().getBoundingClientRect(); + }; + var getRangedRect = function (start, soffset, finish, foffset) { + var sel = Selection.exact(start, soffset, finish, foffset); + return getFirstRect$1(win, sel).map(Rect.toRaw); + }; + var getSelection = function () { + return get$a(win).map(function (exactAdt) { + return Util.convertToRange(win, exactAdt); + }); + }; + var fromSitus = function (situs) { + var relative = Selection.relative(situs.start(), situs.finish()); + return Util.convertToRange(win, relative); + }; + var situsFromPoint = function (x, y) { + return getAtPoint(win, x, y).map(function (exact) { + return Situs.create(exact.start(), exact.soffset(), exact.finish(), exact.foffset()); + }); + }; + var clearSelection = function () { + clear(win); + }; + var collapseSelection = function (toStart) { + if (toStart === void 0) { + toStart = false; + } + get$a(win).each(function (sel) { + return sel.fold(function (rng) { + return rng.collapse(toStart); + }, function (startSitu, finishSitu) { + var situ = toStart ? startSitu : finishSitu; + setRelative(win, situ, situ); + }, function (start, soffset, finish, foffset) { + var node = toStart ? start : finish; + var offset = toStart ? soffset : foffset; + setExact(win, node, offset, node, offset); + }); + }); + }; + var selectContents = function (element) { + setToElement(win, element); + }; + var setSelection = function (sel) { + setExact(win, sel.start(), sel.soffset(), sel.finish(), sel.foffset()); + }; + var setRelativeSelection = function (start, finish) { + setRelative(win, start, finish); + }; + var getInnerHeight = function () { + return win.innerHeight; + }; + var getScrollY = function () { + var pos = get$b(Element.fromDom(win.document)); + return pos.top(); + }; + var scrollBy = function (x, y) { + by(x, y, Element.fromDom(win.document)); + }; + return { + elementFromPoint: elementFromPoint, + getRect: getRect, + getRangedRect: getRangedRect, + getSelection: getSelection, + fromSitus: fromSitus, + situsFromPoint: situsFromPoint, + clearSelection: clearSelection, + collapseSelection: collapseSelection, + setSelection: setSelection, + setRelativeSelection: setRelativeSelection, + selectContents: selectContents, + getInnerHeight: getInnerHeight, + getScrollY: getScrollY, + scrollBy: scrollBy + }; + }; + + var rc = Immutable('rows', 'cols'); + var mouse = function (win, container, isRoot, annotations) { + var bridge = WindowBridge(win); + var handlers = MouseSelection(bridge, container, isRoot, annotations); + return { + mousedown: handlers.mousedown, + mouseover: handlers.mouseover, + mouseup: handlers.mouseup + }; + }; + var keyboard = function (win, container, isRoot, annotations) { + var bridge = WindowBridge(win); + var clearToNavigate = function () { + annotations.clear(container); + return Option.none(); + }; + var keydown = function (event, start, soffset, finish, foffset, direction) { + var realEvent = event.raw(); + var keycode = realEvent.which; + var shiftKey = realEvent.shiftKey === true; + var handler = CellSelection.retrieve(container, annotations.selectedSelector()).fold(function () { + if (SelectionKeys.isDown(keycode) && shiftKey) { + return curry(VerticalMovement.select, bridge, container, isRoot, KeyDirection.down, finish, start, annotations.selectRange); + } else if (SelectionKeys.isUp(keycode) && shiftKey) { + return curry(VerticalMovement.select, bridge, container, isRoot, KeyDirection.up, finish, start, annotations.selectRange); + } else if (SelectionKeys.isDown(keycode)) { + return curry(VerticalMovement.navigate, bridge, isRoot, KeyDirection.down, finish, start, VerticalMovement.lastDownCheck); + } else if (SelectionKeys.isUp(keycode)) { + return curry(VerticalMovement.navigate, bridge, isRoot, KeyDirection.up, finish, start, VerticalMovement.firstUpCheck); + } else { + return Option.none; + } + }, function (selected) { + var update = function (attempts) { + return function () { + var navigation = findMap(attempts, function (delta) { + return KeySelection.update(delta.rows(), delta.cols(), container, selected, annotations); + }); + return navigation.fold(function () { + return CellSelection.getEdges(container, annotations.firstSelectedSelector(), annotations.lastSelectedSelector()).map(function (edges) { + var relative = SelectionKeys.isDown(keycode) || direction.isForward(keycode) ? Situ.after : Situ.before; + bridge.setRelativeSelection(Situ.on(edges.first(), 0), relative(edges.table())); + annotations.clear(container); + return Response.create(Option.none(), true); + }); + }, function (_) { + return Option.some(Response.create(Option.none(), true)); + }); + }; + }; + if (SelectionKeys.isDown(keycode) && shiftKey) { + return update([rc(+1, 0)]); + } else if (SelectionKeys.isUp(keycode) && shiftKey) { + return update([rc(-1, 0)]); + } else if (direction.isBackward(keycode) && shiftKey) { + return update([ + rc(0, -1), + rc(-1, 0) + ]); + } else if (direction.isForward(keycode) && shiftKey) { + return update([ + rc(0, +1), + rc(+1, 0) + ]); + } else if (SelectionKeys.isNavigation(keycode) && shiftKey === false) { + return clearToNavigate; + } else { + return Option.none; + } + }); + return handler(); + }; + var keyup = function (event, start, soffset, finish, foffset) { + return CellSelection.retrieve(container, annotations.selectedSelector()).fold(function () { + var realEvent = event.raw(); + var keycode = realEvent.which; + var shiftKey = realEvent.shiftKey === true; + if (shiftKey === false) { + return Option.none(); + } + if (SelectionKeys.isNavigation(keycode)) { + return KeySelection.sync(container, isRoot, start, soffset, finish, foffset, annotations.selectRange); + } else { + return Option.none(); + } + }, Option.none); + }; + return { + keydown: keydown, + keyup: keyup + }; + }; + var external = function (win, container, isRoot, annotations) { + var bridge = WindowBridge(win); + return function (start, finish) { + annotations.clearBeforeUpdate(container); + CellSelection.identify(start, finish, isRoot).each(function (cellSel) { + var boxes = cellSel.boxes().getOr([]); + annotations.selectRange(container, boxes, cellSel.start(), cellSel.finish()); + bridge.selectContents(finish); + bridge.collapseSelection(); + }); + }; + }; + var InputHandlers = { + mouse: mouse, + keyboard: keyboard, + external: external + }; + + var remove$7 = function (element, classes) { + each(classes, function (x) { + remove$5(element, x); + }); + }; + + var addClass = function (clazz) { + return function (element) { + add$2(element, clazz); + }; + }; + var removeClasses = function (classes) { + return function (element) { + remove$7(element, classes); + }; + }; + + var byClass = function (ephemera) { + var addSelectionClass = addClass(ephemera.selected()); + var removeSelectionClasses = removeClasses([ + ephemera.selected(), + ephemera.lastSelected(), + ephemera.firstSelected() + ]); + var clear = function (container) { + var sels = descendants$1(container, ephemera.selectedSelector()); + each(sels, removeSelectionClasses); + }; + var selectRange = function (container, cells, start, finish) { + clear(container); + each(cells, addSelectionClass); + add$2(start, ephemera.firstSelected()); + add$2(finish, ephemera.lastSelected()); + }; + return { + clearBeforeUpdate: clear, + clear: clear, + selectRange: selectRange, + selectedSelector: ephemera.selectedSelector, + firstSelectedSelector: ephemera.firstSelectedSelector, + lastSelectedSelector: ephemera.lastSelectedSelector + }; + }; + var byAttr = function (ephemera, onSelection, onClear) { + var removeSelectionAttributes = function (element) { + remove(element, ephemera.selected()); + remove(element, ephemera.firstSelected()); + remove(element, ephemera.lastSelected()); + }; + var addSelectionAttribute = function (element) { + set(element, ephemera.selected(), '1'); + }; + var clear = function (container) { + clearBeforeUpdate(container); + onClear(); + }; + var clearBeforeUpdate = function (container) { + var sels = descendants$1(container, ephemera.selectedSelector()); + each(sels, removeSelectionAttributes); + }; + var selectRange = function (container, cells, start, finish) { + clear(container); + each(cells, addSelectionAttribute); + set(start, ephemera.firstSelected(), '1'); + set(finish, ephemera.lastSelected(), '1'); + onSelection(cells, start, finish); + }; + return { + clearBeforeUpdate: clearBeforeUpdate, + clear: clear, + selectRange: selectRange, + selectedSelector: ephemera.selectedSelector, + firstSelectedSelector: ephemera.firstSelectedSelector, + lastSelectedSelector: ephemera.lastSelectedSelector + }; + }; + var SelectionAnnotation = { + byClass: byClass, + byAttr: byAttr + }; + + var getUpOrLeftCells = function (grid, selectedCells, generators) { + var upGrid = grid.slice(0, selectedCells[selectedCells.length - 1].row() + 1); + var upDetails = toDetailList(upGrid, generators); + return bind(upDetails, function (detail) { + var slicedCells = detail.cells().slice(0, selectedCells[selectedCells.length - 1].column() + 1); + return map(slicedCells, function (cell) { + return cell.element(); + }); + }); + }; + var getDownOrRightCells = function (grid, selectedCells, generators) { + var downGrid = grid.slice(selectedCells[0].row() + selectedCells[0].rowspan() - 1, grid.length); + var downDetails = toDetailList(downGrid, generators); + return bind(downDetails, function (detail) { + var slicedCells = detail.cells().slice(selectedCells[0].column() + selectedCells[0].colspan() - 1, +detail.cells().length); + return map(slicedCells, function (cell) { + return cell.element(); + }); + }); + }; + var getOtherCells = function (table, target, generators) { + var list = DetailsList.fromTable(table); + var house = Warehouse.generate(list); + var details = onCells(house, target); + return details.map(function (selectedCells) { + var grid = Transitions.toGrid(house, generators, false); + var upOrLeftCells = getUpOrLeftCells(grid, selectedCells, generators); + var downOrRightCells = getDownOrRightCells(grid, selectedCells, generators); + return { + upOrLeftCells: upOrLeftCells, + downOrRightCells: downOrRightCells + }; + }); + }; + var OtherCells = { getOtherCells: getOtherCells }; + + var hasInternalTarget = function (e) { + return has$2(Element.fromDom(e.target), 'ephox-snooker-resizer-bar') === false; + }; + function CellSelection$1 (editor, lazyResize, selectionTargets) { + var handlerStruct = MixedBag([ + 'mousedown', + 'mouseover', + 'mouseup', + 'keyup', + 'keydown' + ], []); + var handlers = Option.none(); + var cloneFormats = getCloneElements(editor); + var onSelection = function (cells, start, finish) { + selectionTargets.targets().each(function (targets) { + var tableOpt = TableLookup.table(start); + tableOpt.each(function (table) { + var doc = Element.fromDom(editor.getDoc()); + var generators = TableFill.cellOperations(noop, doc, cloneFormats); + var otherCells = OtherCells.getOtherCells(table, targets, generators); + fireTableSelectionChange(editor, cells, start, finish, otherCells); + }); + }); + }; + var onClear = function () { + fireTableSelectionClear(editor); + }; + var annotations = SelectionAnnotation.byAttr(Ephemera, onSelection, onClear); + editor.on('init', function (e) { + var win = editor.getWin(); + var body = getBody$1(editor); + var isRoot = getIsRoot(editor); + var syncSelection = function () { + var sel = editor.selection; + var start = Element.fromDom(sel.getStart()); + var end = Element.fromDom(sel.getEnd()); + var shared = DomParent.sharedOne(TableLookup.table, [ + start, + end + ]); + shared.fold(function () { + annotations.clear(body); + }, noop); + }; + var mouseHandlers = InputHandlers.mouse(win, body, isRoot, annotations); + var keyHandlers = InputHandlers.keyboard(win, body, isRoot, annotations); + var external = InputHandlers.external(win, body, isRoot, annotations); + var hasShiftKey = function (event) { + return event.raw().shiftKey === true; + }; + editor.on('TableSelectorChange', function (e) { + external(e.start, e.finish); + }); + var handleResponse = function (event, response) { + if (!hasShiftKey(event)) { + return; + } + if (response.kill()) { + event.kill(); + } + response.selection().each(function (ns) { + var relative = Selection.relative(ns.start(), ns.finish()); + var rng = asLtrRange(win, relative); + editor.selection.setRng(rng); + }); + }; + var keyup = function (event) { + var wrappedEvent = wrapEvent(event); + if (wrappedEvent.raw().shiftKey && SelectionKeys.isNavigation(wrappedEvent.raw().which)) { + var rng = editor.selection.getRng(); + var start = Element.fromDom(rng.startContainer); + var end = Element.fromDom(rng.endContainer); + keyHandlers.keyup(wrappedEvent, start, rng.startOffset, end, rng.endOffset).each(function (response) { + handleResponse(wrappedEvent, response); + }); + } + }; + var keydown = function (event) { + var wrappedEvent = wrapEvent(event); + lazyResize().each(function (resize) { + resize.hideBars(); + }); + var rng = editor.selection.getRng(); + var startContainer = Element.fromDom(editor.selection.getStart()); + var start = Element.fromDom(rng.startContainer); + var end = Element.fromDom(rng.endContainer); + var direction = Direction.directionAt(startContainer).isRtl() ? SelectionKeys.rtl : SelectionKeys.ltr; + keyHandlers.keydown(wrappedEvent, start, rng.startOffset, end, rng.endOffset, direction).each(function (response) { + handleResponse(wrappedEvent, response); + }); + lazyResize().each(function (resize) { + resize.showBars(); + }); + }; + var isMouseEvent = function (event) { + return event.hasOwnProperty('x') && event.hasOwnProperty('y'); + }; + var wrapEvent = function (event) { + var target = Element.fromDom(event.target); + var stop = function () { + event.stopPropagation(); + }; + var prevent = function () { + event.preventDefault(); + }; + var kill = compose(prevent, stop); + return { + target: constant(target), + x: constant(isMouseEvent(event) ? event.x : null), + y: constant(isMouseEvent(event) ? event.y : null), + stop: stop, + prevent: prevent, + kill: kill, + raw: constant(event) + }; + }; + var isLeftMouse = function (raw) { + return raw.button === 0; + }; + var isLeftButtonPressed = function (raw) { + if (raw.buttons === undefined) { + return true; + } + return (raw.buttons & 1) !== 0; + }; + var mouseDown = function (e) { + if (isLeftMouse(e) && hasInternalTarget(e)) { + mouseHandlers.mousedown(wrapEvent(e)); + } + }; + var mouseOver = function (e) { + if (isLeftButtonPressed(e) && hasInternalTarget(e)) { + mouseHandlers.mouseover(wrapEvent(e)); + } + }; + var mouseUp = function (e) { + if (isLeftMouse(e) && hasInternalTarget(e)) { + mouseHandlers.mouseup(wrapEvent(e)); + } + }; + var getDoubleTap = function () { + var lastTarget = Cell(Element.fromDom(body)); + var lastTimeStamp = Cell(0); + var touchEnd = function (t) { + var target = Element.fromDom(t.target); + if (name(target) === 'td' || name(target) === 'th') { + var lT = lastTarget.get(); + var lTS = lastTimeStamp.get(); + if (eq(lT, target) && t.timeStamp - lTS < 300) { + t.preventDefault(); + external(target, target); + } + } + lastTarget.set(target); + lastTimeStamp.set(t.timeStamp); + }; + return { touchEnd: touchEnd }; + }; + var doubleTap = getDoubleTap(); + editor.on('mousedown', mouseDown); + editor.on('mouseover', mouseOver); + editor.on('mouseup', mouseUp); + editor.on('touchend', doubleTap.touchEnd); + editor.on('keyup', keyup); + editor.on('keydown', keydown); + editor.on('NodeChange', syncSelection); + handlers = Option.some(handlerStruct({ + mousedown: mouseDown, + mouseover: mouseOver, + mouseup: mouseUp, + keyup: keyup, + keydown: keydown + })); + }); + var destroy = function () { + handlers.each(function (handlers) { + }); + }; + return { + clear: annotations.clear, + destroy: destroy + }; + } + + var Selections = function (editor) { + var get = function () { + var body = getBody$1(editor); + return TableSelection.retrieve(body, Ephemera.selectedSelector()).fold(function () { + if (editor.selection.getStart() === undefined) { + return SelectionTypes.none(); + } else { + return SelectionTypes.single(editor.selection); + } + }, function (cells) { + return SelectionTypes.multiple(cells); + }); + }; + return { get: get }; + }; + + var getSelectionTargets = function (editor, selections) { + var targets = Cell(Option.none()); + var changeHandlers = Cell([]); + var findTargets = function () { + return getSelectionStartCellOrCaption(editor).bind(function (cellOrCaption) { + var table = TableLookup.table(cellOrCaption); + return table.map(function (table) { + if (name(cellOrCaption) === 'caption') { + return TableTargets.notCell(cellOrCaption); + } else { + return TableTargets.forMenu(selections, table, cellOrCaption); + } + }); + }); + }; + var resetTargets = function () { + targets.set(cached(findTargets)()); + each(changeHandlers.get(), function (handler) { + return handler(); + }); + }; + var onSetup = function (api, isDisabled) { + var handler = function () { + return targets.get().fold(function () { + api.setDisabled(true); + }, function (targets) { + api.setDisabled(isDisabled(targets)); + }); + }; + handler(); + changeHandlers.set(changeHandlers.get().concat([handler])); + return function () { + changeHandlers.set(filter(changeHandlers.get(), function (h) { + return h !== handler; + })); + }; + }; + var onSetupTable = function (api) { + return onSetup(api, function (_) { + return false; + }); + }; + var onSetupCellOrRow = function (api) { + return onSetup(api, function (targets) { + return name(targets.element()) === 'caption'; + }); + }; + var onSetupMergeable = function (api) { + return onSetup(api, function (targets) { + return targets.mergable().isNone(); + }); + }; + var onSetupUnmergeable = function (api) { + return onSetup(api, function (targets) { + return targets.unmergable().isNone(); + }); + }; + editor.on('NodeChange TableSelectorChange', resetTargets); + return { + onSetupTable: onSetupTable, + onSetupCellOrRow: onSetupCellOrRow, + onSetupMergeable: onSetupMergeable, + onSetupUnmergeable: onSetupUnmergeable, + resetTargets: resetTargets, + targets: function () { + return targets.get(); + } + }; + }; + + var addButtons = function (editor, selectionTargets) { + editor.ui.registry.addMenuButton('table', { + tooltip: 'Table', + icon: 'table', + fetch: function (callback) { + return callback('inserttable | cell row column | advtablesort | tableprops deletetable'); + } + }); + var cmd = function (command) { + return function () { + return editor.execCommand(command); + }; + }; + editor.ui.registry.addButton('tableprops', { + tooltip: 'Table properties', + onAction: cmd('mceTableProps'), + icon: 'table', + onSetup: selectionTargets.onSetupTable + }); + editor.ui.registry.addButton('tabledelete', { + tooltip: 'Delete table', + onAction: cmd('mceTableDelete'), + icon: 'table-delete-table', + onSetup: selectionTargets.onSetupTable + }); + editor.ui.registry.addButton('tablecellprops', { + tooltip: 'Cell properties', + onAction: cmd('mceTableCellProps'), + icon: 'table-cell-properties', + onSetup: selectionTargets.onSetupCellOrRow + }); + editor.ui.registry.addButton('tablemergecells', { + tooltip: 'Merge cells', + onAction: cmd('mceTableMergeCells'), + icon: 'table-merge-cells', + onSetup: selectionTargets.onSetupMergeable + }); + editor.ui.registry.addButton('tablesplitcells', { + tooltip: 'Split cell', + onAction: cmd('mceTableSplitCells'), + icon: 'table-split-cells', + onSetup: selectionTargets.onSetupUnmergeable + }); + editor.ui.registry.addButton('tableinsertrowbefore', { + tooltip: 'Insert row before', + onAction: cmd('mceTableInsertRowBefore'), + icon: 'table-insert-row-above', + onSetup: selectionTargets.onSetupCellOrRow + }); + editor.ui.registry.addButton('tableinsertrowafter', { + tooltip: 'Insert row after', + onAction: cmd('mceTableInsertRowAfter'), + icon: 'table-insert-row-after', + onSetup: selectionTargets.onSetupCellOrRow + }); + editor.ui.registry.addButton('tabledeleterow', { + tooltip: 'Delete row', + onAction: cmd('mceTableDeleteRow'), + icon: 'table-delete-row', + onSetup: selectionTargets.onSetupCellOrRow + }); + editor.ui.registry.addButton('tablerowprops', { + tooltip: 'Row properties', + onAction: cmd('mceTableRowProps'), + icon: 'table-row-properties', + onSetup: selectionTargets.onSetupCellOrRow + }); + editor.ui.registry.addButton('tableinsertcolbefore', { + tooltip: 'Insert column before', + onAction: cmd('mceTableInsertColBefore'), + icon: 'table-insert-column-before', + onSetup: selectionTargets.onSetupCellOrRow + }); + editor.ui.registry.addButton('tableinsertcolafter', { + tooltip: 'Insert column after', + onAction: cmd('mceTableInsertColAfter'), + icon: 'table-insert-column-after', + onSetup: selectionTargets.onSetupCellOrRow + }); + editor.ui.registry.addButton('tabledeletecol', { + tooltip: 'Delete column', + onAction: cmd('mceTableDeleteCol'), + icon: 'table-delete-column', + onSetup: selectionTargets.onSetupCellOrRow + }); + editor.ui.registry.addButton('tablecutrow', { + tooltip: 'Cut row', + onAction: cmd('mceTableCutRow'), + icon: 'temporary-placeholder', + onSetup: selectionTargets.onSetupCellOrRow + }); + editor.ui.registry.addButton('tablecopyrow', { + tooltip: 'Copy row', + onAction: cmd('mceTableCopyRow'), + icon: 'temporary-placeholder', + onSetup: selectionTargets.onSetupCellOrRow + }); + editor.ui.registry.addButton('tablepasterowbefore', { + tooltip: 'Paste row before', + onAction: cmd('mceTablePasteRowBefore'), + icon: 'temporary-placeholder', + onSetup: selectionTargets.onSetupCellOrRow + }); + editor.ui.registry.addButton('tablepasterowafter', { + tooltip: 'Paste row after', + onAction: cmd('mceTablePasteRowAfter'), + icon: 'temporary-placeholder', + onSetup: selectionTargets.onSetupCellOrRow + }); + editor.ui.registry.addButton('tableinsertdialog', { + tooltip: 'Insert table', + onAction: cmd('mceInsertTable'), + icon: 'table' + }); + }; + var addToolbars = function (editor) { + var isTable = function (table) { + return editor.dom.is(table, 'table') && editor.getBody().contains(table); + }; + var toolbar = getToolbar(editor); + if (toolbar.length > 0) { + editor.ui.registry.addContextToolbar('table', { + predicate: isTable, + items: toolbar, + scope: 'node', + position: 'node' + }); + } + }; + var Buttons = { + addButtons: addButtons, + addToolbars: addToolbars + }; + + var addMenuItems = function (editor, selectionTargets) { + var cmd = function (command) { + return function () { + return editor.execCommand(command); + }; + }; + var insertTableAction = function (_a) { + var numRows = _a.numRows, numColumns = _a.numColumns; + editor.undoManager.transact(function () { + InsertTable.insert(editor, numColumns, numRows); + }); + editor.addVisual(); + }; + var tableProperties = { + text: 'Table properties', + onSetup: selectionTargets.onSetupTable, + onAction: cmd('mceTableProps') + }; + var deleteTable = { + text: 'Delete table', + icon: 'table-delete-table', + onSetup: selectionTargets.onSetupTable, + onAction: cmd('mceTableDelete') + }; + var rowItems = [ + { + type: 'menuitem', + text: 'Insert row before', + icon: 'table-insert-row-above', + onAction: cmd('mceTableInsertRowBefore'), + onSetup: selectionTargets.onSetupCellOrRow + }, + { + type: 'menuitem', + text: 'Insert row after', + icon: 'table-insert-row-after', + onAction: cmd('mceTableInsertRowAfter'), + onSetup: selectionTargets.onSetupCellOrRow + }, + { + type: 'menuitem', + text: 'Delete row', + icon: 'table-delete-row', + onAction: cmd('mceTableDeleteRow'), + onSetup: selectionTargets.onSetupCellOrRow + }, + { + type: 'menuitem', + text: 'Row properties', + icon: 'table-row-properties', + onAction: cmd('mceTableRowProps'), + onSetup: selectionTargets.onSetupCellOrRow + }, + { type: 'separator' }, + { + type: 'menuitem', + text: 'Cut row', + onAction: cmd('mceTableCutRow'), + onSetup: selectionTargets.onSetupCellOrRow + }, + { + type: 'menuitem', + text: 'Copy row', + onAction: cmd('mceTableCopyRow'), + onSetup: selectionTargets.onSetupCellOrRow + }, + { + type: 'menuitem', + text: 'Paste row before', + onAction: cmd('mceTablePasteRowBefore'), + onSetup: selectionTargets.onSetupCellOrRow + }, + { + type: 'menuitem', + text: 'Paste row after', + onAction: cmd('mceTablePasteRowAfter'), + onSetup: selectionTargets.onSetupCellOrRow + } + ]; + var row = { + type: 'nestedmenuitem', + text: 'Row', + getSubmenuItems: function () { + return rowItems; + } + }; + var columnItems = [ + { + type: 'menuitem', + text: 'Insert column before', + icon: 'table-insert-column-before', + onAction: cmd('mceTableInsertColBefore'), + onSetup: selectionTargets.onSetupCellOrRow + }, + { + type: 'menuitem', + text: 'Insert column after', + icon: 'table-insert-column-after', + onAction: cmd('mceTableInsertColAfter'), + onSetup: selectionTargets.onSetupCellOrRow + }, + { + type: 'menuitem', + text: 'Delete column', + icon: 'table-delete-column', + onAction: cmd('mceTableDeleteCol'), + onSetup: selectionTargets.onSetupCellOrRow + } + ]; + var column = { + type: 'nestedmenuitem', + text: 'Column', + getSubmenuItems: function () { + return columnItems; + } + }; + var cellItems = [ + { + type: 'menuitem', + text: 'Cell properties', + icon: 'table-cell-properties', + onAction: cmd('mceTableCellProps'), + onSetup: selectionTargets.onSetupCellOrRow + }, + { + type: 'menuitem', + text: 'Merge cells', + icon: 'table-merge-cells', + onAction: cmd('mceTableMergeCells'), + onSetup: selectionTargets.onSetupMergeable + }, + { + type: 'menuitem', + text: 'Split cell', + icon: 'table-split-cells', + onAction: cmd('mceTableSplitCells'), + onSetup: selectionTargets.onSetupUnmergeable + } + ]; + var cell = { + type: 'nestedmenuitem', + text: 'Cell', + getSubmenuItems: function () { + return cellItems; + } + }; + if (hasTableGrid(editor) === false) { + editor.ui.registry.addMenuItem('inserttable', { + text: 'Table', + icon: 'table', + onAction: cmd('mceInsertTable') + }); + } else { + editor.ui.registry.addNestedMenuItem('inserttable', { + text: 'Table', + icon: 'table', + getSubmenuItems: function () { + return [{ + type: 'fancymenuitem', + fancytype: 'inserttable', + onAction: insertTableAction + }]; + } + }); + } + editor.ui.registry.addMenuItem('inserttabledialog', { + text: 'Insert table', + icon: 'table', + onAction: cmd('mceInsertTable') + }); + editor.ui.registry.addMenuItem('tableprops', tableProperties); + editor.ui.registry.addMenuItem('deletetable', deleteTable); + editor.ui.registry.addNestedMenuItem('row', row); + editor.ui.registry.addNestedMenuItem('column', column); + editor.ui.registry.addNestedMenuItem('cell', cell); + editor.ui.registry.addContextMenu('table', { + update: function () { + selectionTargets.resetTargets(); + return selectionTargets.targets().fold(function () { + return ''; + }, function (targets) { + if (name(targets.element()) === 'caption') { + return 'tableprops deletetable'; + } else { + return 'cell row column | advtablesort | tableprops deletetable'; + } + }); + } + }); + }; + var MenuItems = { addMenuItems: addMenuItems }; + + var getClipboardRows = function (clipboardRows) { + return clipboardRows.get().fold(function () { + return; + }, function (rows) { + return map(rows, function (row) { + return row.dom(); + }); + }); + }; + var setClipboardRows = function (rows, clipboardRows) { + var sugarRows = map(rows, Element.fromDom); + clipboardRows.set(Option.from(sugarRows)); + }; + var getApi = function (editor, clipboardRows, resizeHandler, selectionTargets) { + return { + insertTable: function (columns, rows) { + return InsertTable.insert(editor, columns, rows); + }, + setClipboardRows: function (rows) { + return setClipboardRows(rows, clipboardRows); + }, + getClipboardRows: function () { + return getClipboardRows(clipboardRows); + }, + resizeHandler: resizeHandler, + selectionTargets: selectionTargets + }; + }; + + function Plugin(editor) { + var selections = Selections(editor); + var selectionTargets = getSelectionTargets(editor, selections); + var resizeHandler = getResizeHandler(editor); + var cellSelection = CellSelection$1(editor, resizeHandler.lazyResize, selectionTargets); + var actions = TableActions(editor, resizeHandler.lazyWire); + var clipboardRows = Cell(Option.none()); + Commands.registerCommands(editor, actions, cellSelection, selections, clipboardRows); + Clipboard.registerEvents(editor, selections, actions, cellSelection); + MenuItems.addMenuItems(editor, selectionTargets); + Buttons.addButtons(editor, selectionTargets); + Buttons.addToolbars(editor); + editor.on('PreInit', function () { + editor.serializer.addTempAttr(Ephemera.firstSelected()); + editor.serializer.addTempAttr(Ephemera.lastSelected()); + }); + if (hasTabNavigation(editor)) { + editor.on('keydown', function (e) { + TabContext.handle(e, editor, actions, resizeHandler.lazyWire); + }); + } + editor.on('remove', function () { + resizeHandler.destroy(); + cellSelection.destroy(); + }); + return getApi(editor, clipboardRows, resizeHandler, selectionTargets); + } + function Plugin$1 () { + global.add('table', Plugin); + } + + Plugin$1(); + +}(window)); diff --git a/lib/tinymce/js/tinymce/plugins/table/plugin.min.js b/lib/tinymce/js/tinymce/plugins/table/plugin.min.js index fb6152f9..a6780939 100644 --- a/lib/tinymce/js/tinymce/plugins/table/plugin.min.js +++ b/lib/tinymce/js/tinymce/plugins/table/plugin.min.js @@ -1 +1,9 @@ -(function(e,t){"use strict";function n(e,t){for(var n,o=[],r=0;e.length>r;++r){if(n=i[e[r]]||l(e[r]),!n)throw"module definition dependecy not found: "+e[r];o.push(n)}t.apply(null,o)}function o(e,o,r){if("string"!=typeof e)throw"invalid module definition, module id must be defined and be a string";if(o===t)throw"invalid module definition, dependencies must be specified";if(r===t)throw"invalid module definition, definition function must be specified";n(o,function(){i[e]=r.apply(null,arguments)})}function r(e){return!!i[e]}function l(t){for(var n=e,o=t.split(/[.\/]/),r=0;o.length>r;++r){if(!n[o[r]])return;n=n[o[r]]}return n}function a(n){for(var o=0;n.length>o;o++){for(var r=e,l=n[o],a=l.split(/[.\/]/),c=0;a.length-1>c;++c)r[a[c]]===t&&(r[a[c]]={}),r=r[a[c]];r[a[a.length-1]]=i[l]}}var i={},c="tinymce/tableplugin/TableGrid",s="tinymce/util/Tools",d="tinymce/Env",u="tinymce/tableplugin/Quirks",f="tinymce/util/VK",m="tinymce/tableplugin/CellSelection",g="tinymce/dom/TreeWalker",p="tinymce/tableplugin/Plugin",h="tinymce/PluginManager";o(c,[s,d],function(e,n){function o(e,t){return parseInt(e.getAttribute(t)||1,10)}var r=e.each;return function(l,a){function i(){var e=0;I=[],r(["thead","tbody","tfoot"],function(t){var n=E.select("> "+t+" tr",a);r(n,function(n,l){l+=e,r(E.select("> td, > th",n),function(e,n){var r,a,i,c;if(I[l])for(;I[l][n];)n++;for(i=o(e,"rowspan"),c=o(e,"colspan"),a=l;l+i>a;a++)for(I[a]||(I[a]=[]),r=n;n+c>r;r++)I[a][r]={part:t,real:a==l&&r==n,elm:e,rowspan:i,colspan:c}})}),e+=n.length})}function c(e,t){return e=e.cloneNode(t),e.removeAttribute("id"),e}function s(e,n){var o;return o=I[n],o?o[e]:t}function d(e,t,n){e&&(n=parseInt(n,10),1===n?e.removeAttribute(t,1):e.setAttribute(t,n,1))}function u(e){return e&&(E.hasClass(e.elm,"mce-item-selected")||e==D)}function f(){var e=[];return r(a.rows,function(n){r(n.cells,function(o){return E.hasClass(o,"mce-item-selected")||o==D.elm?(e.push(n),!1):t})}),e}function m(){var e=E.createRng();e.setStartAfter(a),e.setEndAfter(a),l.setRng(e),E.remove(a)}function g(o){var l;return e.walk(o,function(e){var a;return 3==e.nodeType?(r(E.getParents(e.parentNode,null,o).reverse(),function(e){e=c(e,!1),l?a&&a.appendChild(e):l=a=e,a=e}),a&&(a.innerHTML=n.ie?" ":'
'),!1):t},"childNodes"),o=c(o,!1),d(o,"rowSpan",1),d(o,"colSpan",1),l?o.appendChild(l):n.ie||(o.innerHTML='
'),o}function p(){var e=E.createRng(),n;return r(E.select("tr",a),function(e){0===e.cells.length&&E.remove(e)}),0===E.select("tr",a).length?(e.setStartAfter(a),e.setEndAfter(a),l.setRng(e),E.remove(a),t):(r(E.select("thead,tbody,tfoot",a),function(e){0===e.rows.length&&E.remove(e)}),i(),n=I[Math.min(I.length-1,k.y)],n&&(l.select(n[Math.min(n.length-1,k.x)].elm,!0),l.collapse(!0)),t)}function h(e,t,n,o){var r,l,a,i,c;for(r=I[t][e].elm.parentNode,a=1;n>=a;a++)if(r=E.getNext(r,"tr")){for(l=e;l>=0;l--)if(c=I[t+a][l].elm,c.parentNode==r){for(i=1;o>=i;i++)E.insertAfter(g(c),c);break}if(-1==l)for(i=1;o>=i;i++)r.insertBefore(g(r.cells[0]),r.cells[0])}}function b(){r(I,function(e,t){r(e,function(e,n){var r,l,a;if(u(e)&&(e=e.elm,r=o(e,"colspan"),l=o(e,"rowspan"),r>1||l>1)){for(d(e,"rowSpan",1),d(e,"colSpan",1),a=0;r-1>a;a++)E.insertAfter(g(e),e);h(n,t,l-1,r)}})})}function v(t,n,o){var l,a,c,f,m,g,h,v,w,x,y;if(t?(l=P(t),a=l.x,c=l.y,f=a+(n-1),m=c+(o-1)):(k=M=null,r(I,function(e,t){r(e,function(e,n){u(e)&&(k||(k={x:n,y:t}),M={x:n,y:t})})}),a=k.x,c=k.y,f=M.x,m=M.y),v=s(a,c),w=s(f,m),v&&w&&v.part==w.part){for(b(),i(),v=s(a,c).elm,d(v,"colSpan",f-a+1),d(v,"rowSpan",m-c+1),h=c;m>=h;h++)for(g=a;f>=g;g++)I[h]&&I[h][g]&&(t=I[h][g].elm,t!=v&&(x=e.grep(t.childNodes),r(x,function(e){v.appendChild(e)}),x.length&&(x=e.grep(v.childNodes),y=0,r(x,function(e){"BR"==e.nodeName&&E.getAttrib(e,"data-mce-bogus")&&y++i;i++)if(I[n][i]&&(l=I[n][i].elm,l!=a)){if(e){if(n>0&&I[n-1][i]&&(p=I[n-1][i].elm,h=o(p,"rowSpan"),h>1)){d(p,"rowSpan",h+1);continue}}else if(h=o(l,"rowspan"),h>1){d(l,"rowSpan",h+1);continue}m=g(l),d(m,"colSpan",l.colSpan),f.appendChild(m),a=l}f.hasChildNodes()&&(e?s.parentNode.insertBefore(f,s):E.insertAfter(f,s))}function x(e){var n,l;r(I,function(o){return r(o,function(o,r){return u(o)&&(n=r,e)?!1:t}),e?!n:t}),r(I,function(t,r){var a,i,c;t[n]&&(a=t[n].elm,a!=l&&(c=o(a,"colspan"),i=o(a,"rowspan"),1==c?e?(a.parentNode.insertBefore(g(a),a),h(n,r,i-1,c)):(E.insertAfter(g(a),a),h(n,r,i-1,c)):d(a,"colSpan",a.colSpan+1),l=a))})}function y(){var t=[];r(I,function(n){r(n,function(n,l){u(n)&&-1===e.inArray(t,l)&&(r(I,function(e){var t=e[l].elm,n;n=o(t,"colSpan"),n>1?d(t,"colSpan",n-1):E.remove(t)}),t.push(l))})}),p()}function C(){function e(e){var t,n,l;t=E.getNext(e,"tr"),r(e.cells,function(e){var t=o(e,"rowSpan");t>1&&(d(e,"rowSpan",t-1),n=P(e),h(n.x,n.y,1,1))}),n=P(e.cells[0]),r(I[n.y],function(e){var t;e=e.elm,e!=l&&(t=o(e,"rowSpan"),1>=t?E.remove(e):d(e,"rowSpan",t-1),l=e)})}var t;t=f(),r(t.reverse(),function(t){e(t)}),p()}function R(){var e=f();return E.remove(e),p(),e}function N(){var e=f();return r(e,function(t,n){e[n]=c(t,!0)}),e}function T(e,n){var o=f(),l=o[n?0:o.length-1],a=l.cells.length;e&&(r(I,function(e){var n;return a=0,r(e,function(e){e.real&&(a+=e.colspan),e.elm.parentNode==l&&(n=1)}),n?!1:t}),n||e.reverse(),r(e,function(e){var t,o=e.cells.length,r;for(t=0;o>t;t++)r=e.cells[t],d(r,"colSpan",1),d(r,"rowSpan",1);for(t=o;a>t;t++)e.appendChild(g(e.cells[o-1]));for(t=a;o>t;t++)E.remove(e.cells[t]);n?l.parentNode.insertBefore(e,l):E.insertAfter(e,l)}),E.removeClass(E.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"))}function P(e){var n;return r(I,function(o,l){return r(o,function(o,r){return o.elm==e?(n={x:r,y:l},!1):t}),!n}),n}function S(e){k=P(e)}function A(){var e,t;return e=t=0,r(I,function(n,o){r(n,function(n,r){var l,a;u(n)&&(n=I[o][r],r>e&&(e=r),o>t&&(t=o),n.real&&(l=n.colspan-1,a=n.rowspan-1,l&&r+l>e&&(e=r+l),a&&o+a>t&&(t=o+a)))})}),{x:e,y:t}}function B(e){var t,n,o,r,l,a,i,c,s,d;if(M=P(e),k&&M){for(t=Math.min(k.x,M.x),n=Math.min(k.y,M.y),o=Math.max(k.x,M.x),r=Math.max(k.y,M.y),l=o,a=r,d=n;a>=d;d++)e=I[d][t],e.real||t>t-(e.colspan-1)&&(t-=e.colspan-1);for(s=t;l>=s;s++)e=I[n][s],e.real||n>n-(e.rowspan-1)&&(n-=e.rowspan-1);for(d=n;r>=d;d++)for(s=t;o>=s;s++)e=I[d][s],e.real&&(i=e.colspan-1,c=e.rowspan-1,i&&s+i>l&&(l=s+i),c&&d+c>a&&(a=d+c));for(E.removeClass(E.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),d=n;a>=d;d++)for(s=t;l>=s;s++)I[d][s]&&E.addClass(I[d][s].elm,"mce-item-selected")}}var I,k,M,D,E=l.dom;a=a||E.getParent(l.getNode(),"table"),i(),D=E.getParent(l.getStart(),"th,td"),D&&(k=P(D),M=A(),D=s(k.x,k.y)),e.extend(this,{deleteTable:m,split:b,merge:v,insertRow:w,insertCol:x,deleteCols:y,deleteRows:C,cutRows:R,copyRows:N,pasteRows:T,getPos:P,setStartCell:S,setEndCell:B})}}),o(u,[f,d,s],function(e,n,o){function r(e,t){return parseInt(e.getAttribute(t)||1,10)}var l=o.each;return function(o){function a(){function n(n){function a(e,t){var r=e?"previousSibling":"nextSibling",l=o.dom.getParent(t,"tr"),a=l[r];if(a)return b(o,t,a,e),n.preventDefault(),!0;var c=o.dom.getParent(l,"table"),u=l.parentNode,f=u.nodeName.toLowerCase();if("tbody"===f||f===(e?"tfoot":"thead")){var m=i(e,c,u,"tbody");if(null!==m)return s(e,m,t)}return d(e,l,r,c)}function i(e,t,n,r){var l=o.dom.select(">"+r,t),a=l.indexOf(n);if(e&&0===a||!e&&a===l.length-1)return c(e,t);if(-1===a){var i="thead"===n.tagName.toLowerCase()?0:l.length-1;return l[i]}return l[a+(e?-1:1)]}function c(e,t){var n=e?"thead":"tfoot",r=o.dom.select(">"+n,t);return 0!==r.length?r[0]:null}function s(e,t,r){var l=u(t,e);return l&&b(o,r,l,e),n.preventDefault(),!0}function d(e,t,r,l){var i=l[r];if(i)return f(i),!0;var c=o.dom.getParent(l,"td,th");if(c)return a(e,c,n);var s=u(t,!e);return f(s),n.preventDefault(),!1}function u(e,t){var n=e&&e[t?"lastChild":"firstChild"];return n&&"BR"===n.nodeName?o.dom.getParent(n,"td,th"):n}function f(e){o.selection.setCursorLocation(e,0)}function m(){return x==e.UP||x==e.DOWN}function g(e){var t=e.selection.getNode(),n=e.dom.getParent(t,"tr");return null!==n}function p(e){for(var t=0,n=e;n.previousSibling;)n=n.previousSibling,t+=r(n,"colspan");return t}function h(e,n){var o=0,a=0;return l(e.children,function(e,l){return o+=r(e,"colspan"),a=l,o>n?!1:t}),a}function b(e,t,n,r){var l=p(o.dom.getParent(t,"td,th")),a=h(n,l),i=n.childNodes[a],c=u(i,r);f(c||i)}function v(e){var t=o.selection.getNode(),n=o.dom.getParent(t,"td,th"),r=o.dom.getParent(e,"td,th");return n&&n!==r&&w(n,r)}function w(e,t){return o.dom.getParent(e,"TABLE")===o.dom.getParent(t,"TABLE")}var x=n.keyCode;if(m()&&g(o)){var y=o.selection.getNode();setTimeout(function(){v(y)&&a(!n.shiftKey&&x===e.UP,y,n)},0)}}o.on("KeyDown",function(e){n(e)})}function i(){function e(e,t){var n=t.ownerDocument,o=n.createRange(),r;return o.setStartBefore(t),o.setEnd(e.endContainer,e.endOffset),r=n.createElement("body"),r.appendChild(o.cloneContents()),0===r.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length}o.on("KeyDown",function(t){var n,r,l=o.dom;(37==t.keyCode||38==t.keyCode)&&(n=o.selection.getRng(),r=l.getParent(n.startContainer,"table"),r&&o.getBody().firstChild==r&&e(n,r)&&(n=l.createRng(),n.setStartBefore(r),n.setEndBefore(r),o.selection.setRng(n),t.preventDefault()))})}function c(){o.on("KeyDown SetContent VisualAid",function(){var e;for(e=o.getBody().lastChild;e;e=e.previousSibling)if(3==e.nodeType){if(e.nodeValue.length>0)break}else if(1==e.nodeType&&!e.getAttribute("data-mce-bogus"))break;e&&"TABLE"==e.nodeName&&(o.settings.forced_root_block?o.dom.add(o.getBody(),o.settings.forced_root_block,null,n.ie?" ":'
'):o.dom.add(o.getBody(),"br",{"data-mce-bogus":"1"}))}),o.on("PreProcess",function(e){var t=e.node.lastChild;t&&("BR"==t.nodeName||1==t.childNodes.length&&("BR"==t.firstChild.nodeName||"\u00a0"==t.firstChild.nodeValue))&&t.previousSibling&&"TABLE"==t.previousSibling.nodeName&&o.dom.remove(t)})}function s(){function e(e,t,n,o){var r=3,l=e.dom.getParent(t.startContainer,"TABLE"),a,i,c;return l&&(a=l.parentNode),i=t.startContainer.nodeType==r&&0===t.startOffset&&0===t.endOffset&&o&&("TR"==n.nodeName||n==a),c=("TD"==n.nodeName||"TH"==n.nodeName)&&!o,i||c}function t(){var t=o.selection.getRng(),n=o.selection.getNode(),r=o.dom.getParent(t.startContainer,"TD,TH");if(e(o,t,n,r)){r||(r=n);for(var l=r.lastChild;l.lastChild;)l=l.lastChild;t.setEnd(l,l.nodeValue.length),o.selection.setRng(t)}}o.on("KeyDown",function(){t()}),o.on("MouseDown",function(e){2!=e.button&&t()})}n.webkit&&(a(),s()),n.gecko&&(i(),c())}}),o(m,[c,g,s],function(e,n,o){return function(r){function l(){r.getBody().style.webkitUserSelect="",d&&(r.dom.removeClass(r.dom.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),d=!1)}var a=r.dom,i,c,s,d=!0;return r.on("MouseDown",function(e){2!=e.button&&(l(),c=a.getParent(e.target,"td,th"),s=a.getParent(c,"table"))}),a.bind(r.getDoc(),"mouseover",function(t){var n,o,l=t.target;if(c&&(i||l!=c)&&("TD"==l.nodeName||"TH"==l.nodeName)){o=a.getParent(l,"table"),o==s&&(i||(i=new e(r.selection,o),i.setStartCell(c),r.getBody().style.webkitUserSelect="none"),i.setEndCell(l),d=!0),n=r.selection.getSel();try{n.removeAllRanges?n.removeAllRanges():n.empty()}catch(u){}t.preventDefault()}}),r.on("MouseUp",function(){function e(e,r){var a=new n(e,e);do{if(3==e.nodeType&&0!==o.trim(e.nodeValue).length)return r?l.setStart(e,0):l.setEnd(e,e.nodeValue.length),t;if("BR"==e.nodeName)return r?l.setStartBefore(e):l.setEndBefore(e),t}while(e=r?a.next():a.prev())}var l,d=r.selection,u,f,m,g,p;if(c){if(i&&(r.getBody().style.webkitUserSelect=""),u=a.select("td.mce-item-selected,th.mce-item-selected"),u.length>0){l=a.createRng(),m=u[0],p=u[u.length-1],l.setStartBefore(m),l.setEndAfter(m),e(m,1),f=new n(m,a.getParent(u[0],"table"));do if("TD"==m.nodeName||"TH"==m.nodeName){if(!a.hasClass(m,"mce-item-selected"))break;g=m}while(m=f.next());e(g),d.setRng(l)}r.nodeChanged(),c=i=s=null}}),r.on("KeyUp",function(){l()}),{clear:l}}}),o(p,[c,u,m,s,g,d,h],function(e,n,o,r,l,a,i){function c(r){function l(e){return e?e.replace(/px$/,""):""}function i(e){return/^[0-9]+$/.test(e)&&(e+="px"),e}function c(){var e=r.dom,t,n;t=r.dom.getParent(r.selection.getNode(),"table"),n={width:l(e.getStyle(t,"width")||e.getAttrib(t,"width")),height:l(e.getStyle(t,"height")||e.getAttrib(t,"height")),cellspacing:e.getAttrib(t,"cellspacing"),cellpadding:e.getAttrib(t,"cellpadding"),border:e.getAttrib(t,"border"),caption:!!e.select("caption",t)[0]},s("left center right".split(" "),function(e){r.formatter.matchNode(t,"align"+e)&&(n.align=e)}),r.windowManager.open({title:"Table properties",items:{type:"form",layout:"grid",columns:2,data:n,defaults:{type:"textbox",maxWidth:50},items:[{label:"Cols",name:"cols"},{label:"Rows",name:"rows"},{label:"Width",name:"width"},{label:"Height",name:"height"},{label:"Cell spacing",name:"cellspacing"},{label:"Cell padding",name:"cellpadding"},{label:"Border",name:"border"},{label:"Caption",name:"caption",type:"checkbox"},{label:"Alignment",minWidth:90,name:"align",type:"listbox",text:"None",maxWidth:null,values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]}]},onsubmit:function(){var n=this.toJSON(),o;r.undoManager.transact(function(){r.dom.setAttribs(t,{cellspacing:n.cellspacing,cellpadding:n.cellpadding,border:n.border}),r.dom.setStyles(t,{width:i(n.width),height:i(n.height)}),o=e.select("caption",t)[0],o&&!n.caption&&e.remove(o),!o&&n.caption&&(o=e.create("caption"),a.ie||(o.innerHTML='
'),t.insertBefore(o,t.firstChild)),n.align?r.formatter.apply("align"+n.align,{},t):s("left center right".split(" "),function(e){r.formatter.remove("align"+e,{},t)}),r.focus(),r.addVisual()})}})}function d(e,t){r.windowManager.open({title:"Merge cells",body:[{label:"Columns",name:"cols",type:"textbox",size:5},{label:"Rows",name:"rows",type:"textbox",size:5}],onsubmit:function(){var n=this.toJSON();r.undoManager.transact(function(){e.merge(t,n.cols,n.rows)})}})}function u(){var e=r.dom,t,n,o=[];o=r.dom.select("td.mce-item-selected,th.mce-item-selected"),t=r.dom.getParent(r.selection.getNode(),"td,th"),!o.length&&t&&o.push(t),t=t||o[0],n={width:l(e.getStyle(t,"width")||e.getAttrib(t,"width")),height:l(e.getStyle(t,"height")||e.getAttrib(t,"height")),scope:e.getAttrib(t,"scope")},n.type=t.nodeName.toLowerCase(),s("left center right".split(" "),function(e){r.formatter.matchNode(t,"align"+e)&&(n.align=e)}),r.windowManager.open({title:"Cell properties",items:{type:"form",data:n,layout:"grid",columns:2,defaults:{type:"textbox",maxWidth:50},items:[{label:"Width",name:"width"},{label:"Height",name:"height"},{label:"Cell type",name:"type",type:"listbox",text:"None",minWidth:90,maxWidth:null,menu:[{text:"Cell",value:"td"},{text:"Header cell",value:"th"}]},{label:"Scope",name:"scope",type:"listbox",text:"None",minWidth:90,maxWidth:null,menu:[{text:"None",value:""},{text:"Row",value:"row"},{text:"Column",value:"col"},{text:"Row group",value:"rowgroup"},{text:"Column group",value:"colgroup"}]},{label:"Alignment",name:"align",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]}]},onsubmit:function(){var t=this.toJSON();r.undoManager.transact(function(){s(o,function(n){r.dom.setAttrib(n,"scope",t.scope),r.dom.setStyles(n,{width:i(t.width),height:i(t.height)}),t.type&&n.nodeName.toLowerCase()!=t.type&&(n=e.rename(n,t.type)),t.align?r.formatter.apply("align"+t.align,{},n):s("left center right".split(" "),function(e){r.formatter.remove("align"+e,{},n)})}),r.focus()})}})}function f(){var e=r.dom,n,o,a,c,d=[];n=r.dom.getParent(r.selection.getNode(),"table"),o=r.dom.getParent(r.selection.getNode(),"td,th"),s(n.rows,function(n){s(n.cells,function(r){return e.hasClass(r,"mce-item-selected")||r==o?(d.push(n),!1):t})}),a=d[0],c={height:l(e.getStyle(a,"height")||e.getAttrib(a,"height")),scope:e.getAttrib(a,"scope")},c.type=a.parentNode.nodeName.toLowerCase(),s("left center right".split(" "),function(e){r.formatter.matchNode(a,"align"+e)&&(c.align=e)}),r.windowManager.open({title:"Row properties",items:{type:"form",data:c,columns:2,defaults:{type:"textbox"},items:[{type:"listbox",name:"type",label:"Row type",text:"None",maxWidth:null,menu:[{text:"header",value:"thead"},{text:"body",value:"tbody"},{text:"footer",value:"tfoot"}]},{type:"listbox",name:"align",label:"Alignment",text:"None",maxWidth:null,menu:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]},{label:"Height",name:"height"}]},onsubmit:function(){var t=this.toJSON(),n,o,l;r.undoManager.transact(function(){s(d,function(a){r.dom.setAttrib(a,"scope",t.scope),r.dom.setStyles(a,{height:i(t.height)}),t.type!=a.parentNode.nodeName.toLowerCase()&&(n=e.getParent(a,"table"),o=a.parentNode,l=e.select(n,t.type)[0],l||(l=e.create(t.type),n.firstChild?n.insertBefore(l,n.firstChild):n.appendChild(l)),l.insertBefore(a,l.firstChild),o.hasChildNodes()||e.remove(o)),t.align?r.formatter.apply("align"+t.align,{},a):s("left center right".split(" "),function(e){r.formatter.remove("align"+e,{},a)})}),r.focus()})}})}function m(e){return function(){r.execCommand(e)}}function g(e,t){var n,o,l;for(l="",n=0;t>n;n++){for(l+="
",r.insertContent(l)}function p(){function e(){t.disabled(!r.dom.getParent(r.selection.getNode(),"table")),r.selection.selectorChanged("table",function(e){t.disabled(!e)})}var t=this;r.initialized?e():r.on("init",e)}function h(){var e="";e='",o=0;e>o;o++)l+=" "}l+=""+(a.ie?" ":" ";l+="
")+"';for(var t=0;10>t;t++){e+="
",e+='";for(var n=0;10>n;n++)e+=' "}return e+="';e+=" 0 x 0'}var b,v,w=this;s([["table","Insert/edit table","mceInsertTable"],["delete_table","Delete table","mceTableDelete"],["delete_col","Delete column","mceTableDeleteCol"],["delete_row","Delete row","mceTableDeleteRow"],["col_after","Insert column after","mceTableInsertColAfter"],["col_before","Insert column before","mceTableInsertColBefore"],["row_after","Insert row after","mceTableInsertRowAfter"],["row_before","Insert row before","mceTableInsertRowBefore"],["row_props","Row properties","mceTableRowProps"],["cell_props","Cell properties","mceTableCellProps"],["split_cells","Split cells","mceTableSplitCells"],["merge_cells","Merge cells","mceTableMergeCells"]],function(e){r.addButton(e[0],{title:e[1],cmd:e[2],onPostRender:p})}),r.addMenuItem("inserttable",{text:"Insert table",icon:"table",context:"table",onhide:function(){r.dom.removeClass(this.menu.items()[0].getEl().getElementsByTagName("a"),"mce-active")},menu:[{type:"container",html:h(),onmousemove:function(e){var t=e.target;if("A"==t.nodeName){var n=r.dom.getParent(t,"table"),o=t.getAttribute("data-mce-index");if(o!=this.lastPos){o=o.split(","),o[0]=parseInt(o[0],10),o[1]=parseInt(o[1],10);for(var l=0;10>l;l++)for(var a=0;10>a;a++)r.dom.toggleClass(n.rows[l].childNodes[a].firstChild,"mce-active",o[0]>=a&&o[1]>=l);n.nextSibling.innerHTML=o[0]+1+" x "+(o[1]+1),this.lastPos=o}}},onclick:function(e){"A"==e.target.nodeName&&this.lastPos&&(e.preventDefault(),g(this.lastPos[0]+1,this.lastPos[1]+1),this.parent().cancel())}}]}),r.addMenuItem("tableprops",{text:"Table properties",context:"table",onPostRender:p,onclick:c}),r.addMenuItem("deletetable",{text:"Delete table",context:"table",onPostRender:p,cmd:"mceTableDelete"}),r.addMenuItem("cell",{separator:"before",text:"Cell",context:"table",menu:[{text:"Cell properties",onclick:m("mceTableCellProps"),onPostRender:p},{text:"Merge cells",onclick:m("mceTableMergeCells"),onPostRender:p},{text:"Split cell",onclick:m("mceTableSplitCells"),onPostRender:p}]}),r.addMenuItem("row",{text:"Row",context:"table",menu:[{text:"Insert row before",onclick:m("mceTableInsertRowBefore"),onPostRender:p},{text:"Insert row after",onclick:m("mceTableInsertRowAfter"),onPostRender:p},{text:"Delete row",onclick:m("mceTableDeleteRow"),onPostRender:p},{text:"Row properties",onclick:m("mceTableRowProps"),onPostRender:p},{text:"-"},{text:"Cut row",onclick:m("mceTableCutRow"),onPostRender:p},{text:"Copy row",onclick:m("mceTableCopyRow"),onPostRender:p},{text:"Paste row before",onclick:m("mceTablePasteRowBefore"),onPostRender:p},{text:"Paste row after",onclick:m("mceTablePasteRowAfter"),onPostRender:p}]}),r.addMenuItem("column",{text:"Column",context:"table",menu:[{text:"Insert column before",onclick:m("mceTableInsertColBefore"),onPostRender:p},{text:"Insert column after",onclick:m("mceTableInsertColAfter"),onPostRender:p},{text:"Delete column",onclick:m("mceTableDeleteCol"),onPostRender:p}]}),a.isIE||r.on("click",function(e){e=e.target,"TABLE"===e.nodeName&&(r.selection.select(e),r.nodeChanged())}),w.quirks=new n(r),r.on("Init",function(){b=r.windowManager,w.cellSelection=new o(r)}),s({mceTableSplitCells:function(e){e.split()},mceTableMergeCells:function(e){var t,n,o;o=r.dom.getParent(r.selection.getNode(),"th,td"),o&&(t=o.rowSpan,n=o.colSpan),r.dom.select("td.mce-item-selected,th.mce-item-selected").length?e.merge():d(e,o)},mceTableInsertRowBefore:function(e){e.insertRow(!0)},mceTableInsertRowAfter:function(e){e.insertRow()},mceTableInsertColBefore:function(e){e.insertCol(!0)},mceTableInsertColAfter:function(e){e.insertCol()},mceTableDeleteCol:function(e){e.deleteCols()},mceTableDeleteRow:function(e){e.deleteRows()},mceTableCutRow:function(e){v=e.cutRows()},mceTableCopyRow:function(e){v=e.copyRows()},mceTablePasteRowBefore:function(e){e.pasteRows(v,!0)},mceTablePasteRowAfter:function(e){e.pasteRows(v)},mceTableDelete:function(e){e.deleteTable()}},function(t,n){r.addCommand(n,function(){var n=new e(r.selection);n&&(t(n),r.execCommand("mceRepaint"),w.cellSelection.clear())})}),s({mceInsertTable:function(){c()},mceTableRowProps:f,mceTableCellProps:u},function(e,t){r.addCommand(t,function(t,n){e(n)})})}var s=r.each;i.add("table",c)}),a([c,u,m,p])})(this); \ No newline at end of file +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.1.6 (2020-01-28) + */ +!function(f){"use strict";function o(e){return e}var R=function(e){function n(){return t}var t=e;return{get:n,set:function(e){t=e},clone:function(){return R(n())}}},T=function(){},O=function(t,r){return function(){for(var e=[],n=0;nt.maxRow()||s t.maxCol()))gt.getAt(n,l,s).filter(r).isNone()?(o=f,void 0,i=e[l].element(),u=on.fromTag("td"),Wn(u,on.fromTag("br")),(o?Wn:Te)(i,u)):f=!0}}(r,o,i,t),function(e,n){var t=h(ct.firstLayer(e,"tr"),function(e){return 0===e.dom().childElementCount});p(t,_n),n.minCol()!==n.maxCol()&&n.minRow()!==n.maxRow()||p(ct.firstLayer(e,"th,td"),function(e){Y(e,"rowspan"),Y(e,"colspan")}),Y(e,"width"),Y(e,"height"),ue(e,"width"),ue(e,"height")}(e,i),e};function vt(e){return Pt.get(e)}function bt(e){return Pt.getOption(e)}function wt(e,n){Pt.set(e,n)}function yt(e){return"img"===en(e)?1:bt(e).fold(function(){return Ce(e).length},function(e){return e.length})}function Ct(e){return function(e){return bt(e).filter(function(e){return 0!==e.trim().length||-1 =e.startCol()&&n.column()+n.colspan()-1<=e.finishCol()&&n.row()>=e.startRow()&&n.row()+n.rowspan()-1<=e.finishRow()}function Bt(e,n,t){var r=gt.findItem(e,n,Bn),o=gt.findItem(e,t,Bn);return r.bind(function(n){return o.map(function(e){return function(e,n){return Kn(Math.min(e.row(),n.row()),Math.min(e.column(),n.column()),Math.max(e.row()+e.rowspan()-1,n.row()+n.rowspan()-1),Math.max(e.column()+e.colspan()-1,n.column()+n.colspan()-1))}(n,e)})})}var Pt=function Zf(t,r){var n=function(e){return t(e)?Me.from(e.dom().nodeValue):Me.none()};return{get:function(e){if(!t(e))throw new Error("Can only get "+r+" value of a "+r+" node");return n(e).getOr("")},getOption:n,set:function(e,n){if(!t(e))throw new Error("Can only set raw "+r+" value of a "+r+" node");e.dom().nodeValue=n}}}(tn,"text"),Mt=["img","br"],Wt=function(e,i){var u=function(e){for(var n=Ce(e),t=n.length-1;0<=t;t--){var r=n[t];if(i(r))return Me.some(r);var o=u(r);if(o.isSome())return o}return Me.none()};return u(e)},_t={cellOperations:function(i,e,u){return{row:kt(e),cell:function(e){var n=he(e.element()),t=on.fromTag(en(e.element()),n.dom()),r=u.getOr(["strong","em","b","i","span","font","h1","h2","h3","h4","h5","h6","p","div"]),o=0 =e.startCol()&&o<=e.finishRow()&&i>=e.startRow()},jt=function(e,n){for(var t=!0,r=b(It,n),o=n.startRow();o<=n.finishRow();o++)for(var i=n.startCol();i<=n.finishCol();i++)t=t&>.getAt(e,o,i).exists(r);return t?Me.some(n):Me.none()},zt=Bt,Ht=function(n,e,t){return Bt(n,e,t).bind(function(e){return jt(n,e)})},Ft=function(r,e,o,i){return gt.findItem(r,e,Bn).bind(function(e){var n=0 =n.length-1)return Me.none();var e=n[t].fold(function(){var e=E(n.slice(0,t));return wo(e,function(e,n){return e.map(function(e){return{value:e,delta:n+1}})})},function(e){return Me.some({value:e,delta:0})}),r=n[t+1].fold(function(){var e=n.slice(t+1);return wo(e,function(e,n){return e.map(function(e){return{value:e,delta:n+1}})})},function(e){return Me.some({value:e,delta:1})});return e.bind(function(t){return r.map(function(e){var n=e.delta+t.delta;return Math.abs(e.value-t.value)/n})})}function No(e){var n=e.replace(/\./g,"-");return{resolve:function(e){return n+"-"+e}}}function ko(e){var n=Be(e.parent(),"."+uu);p(n,_n)}function Io(t,e,r){var o=t.origin();p(e,function(e,n){e.each(function(e){var n=r(o,e);To(n,uu),Wn(t.parent(),n)})})}function Bo(e,n,t,r,o,i){var u=qr(n);!function(e,n,r,o){Io(e,n,function(e,n){var t=iu(n.row(),r.left()-e.left(),n.y()-e.top(),o,7);return To(t,cu),t})}(e,0 ',r.insertBefore(o,r.firstChild)),""===u.align?kc(t,r):Ec(t,r,u.align),t.focus(),t.addVisual()})}function Gi(n){return function(e){return Me.from(e.dom.getParent(e.selection.getStart(),n)).map(on.fromDom)}}function Yi(e){function n(){e.stopPropagation()}function t(){e.preventDefault()}var r=on.fromDom(e.target),o=O(t,n);return function(e,n,t,r,o,i,u){return{target:D(e),x:D(n),y:D(t),stop:r,prevent:o,kill:i,raw:D(u)}}(r,e.clientX,e.clientY,n,t,o,e)}function Ki(e,n,t,r,o){var i=function(n,t){return function(e){n(e)&&t(Yi(e))}}(t,r);return e.dom().addEventListener(n,i,o),{unbind:b(da,e,n,i,o)}}function Xi(e,n,t){return function(e,n,t,r){return Ki(e,n,t,r,!1)}(e,n,ma,t)}var $i,Ji=function(e){var n=st(e);return gt.generate(n).grid()},Qi=function(o,e){function n(e,n){0 =n.length||e.column()>hu.cellLength(n[0]))return Su.error("invalid start address out of table bounds, row: "+e.row()+", column: "+e.column());var r=n.slice(e.row()),o=r[0].cells().slice(e.column()),i=hu.cellLength(t[0]),u=t.length;return Su.value({rowDelta:D(r.length-u),colDelta:D(o.length-i)})},Ru=function(e,n){var t=hu.cellLength(e[0]),r=hu.cellLength(n[0]);return{rowDelta:D(0),colDelta:D(t-r)}},Tu=function(e,n,t){var r=n.colDelta()<0?Go:o;return(n.rowDelta()<0?Vo:o)(r(e,Math.abs(n.colDelta()),t),Math.abs(n.rowDelta()),t)},Ou=function(e,n,t,r){if(0===e.length)return e;for(var o=n.startRow();o<=n.finishRow();o++)for(var i=n.startCol();i<=n.finishCol();i++)hu.mutateCell(e[o],i,qn(r(),!1));return e},Du=function(e,n,t,r){for(var o=!0,i=0;i =e.left&&n<=e.right&&t>=e.top&&t<=e.bottom}function Ia(t,r,e,n,o){function i(e){var n=t.dom().createRange();return n.setStart(r.dom(),e),n.collapse(!0),n}var u=vt(r).length,c=function(e,n,t,r,o){if(0===o)return 0;if(n===r)return o-1;for(var i=r,u=1;u n.right()}(t,e)})})}function ml(n,t,e){var r=n.move(e,5),o=yf(t,n,e,r,100).getOr(r);return function(e,n,t){return e.point(n)>t.getInnerHeight()?Me.some(e.point(n)-t.getInnerHeight()):e.point(n)<0?Me.some(-e.point(n)):Me.none()}(n,o,t).fold(function(){return t.situsFromPoint(o.left(),n.point(o))},function(e){return t.scrollBy(0,e),t.situsFromPoint(o.left(),n.point(o)-e)})}function gl(e,n){return function(e,n,t){return Jn(e,n,t).isSome()}(e,function(e){return ve(e).exists(function(e){return Bn(e,n)})})}function pl(n,r,o,e,i){return nt(e,"td,th",r).bind(function(t){return nt(t,"table",r).bind(function(e){return gl(i,e)?Df(n,r,o).bind(function(n){return nt(n.finish(),"td,th",r).map(function(e){return{start:D(t),finish:D(e),range:D(n)}})}):Me.none()})})}function hl(e,n){return nt(e,"td,th",n)}var vl=function(n,t,e){function r(){l.stop(),u.isOn()&&(u.off(),i.trigger.stop())}var o=!1,i=sa.create({start:fa([]),stop:fa([])}),u=ya(),c=function(t,r){var o=null;return{cancel:function(){null!==o&&(f.clearTimeout(o),o=null)},throttle:function(){for(var e=[],n=0;n r.left&&o.left ("+e.right()+", "+e.bottom()+")"}},pf=function(e,n,t){return nn(n)?sl(e,n).map(fl):tn(n)?function(e,n,t){return 0<=t&&t o.bottom()?vf.retry(i):t.top()===o.bottom()?vf.retry(gf.moveDown(o,1)):dl(e,n,o)?vf.retry(gf.translate(i,5,0)):vf.none()},move:gf.moveDown,gather:ul},yf=function(t,r,o,i,u){return 0===u?Me.some(i):function(e,n,t){return e.elementFromPoint(n,t).filter(function(e){return"table"===en(e)}).isSome()}(t,i.left(),r.point(i))?function(e,n,t,r,o){return yf(e,n,t,n.move(r,5),o)}(t,r,o,i,u-1):t.situsFromPoint(i.left(),r.point(i)).bind(function(e){return e.start().fold(Me.none,function(n){return hf(t,n).bind(function(e){return r.adjuster(t,n,e,o,i).fold(Me.none,function(e){return yf(t,r,o,e,u-1)})}).orThunk(function(){return Me.some(i)})},Me.none)})},Cf={tryUp:b(ml,bf),tryDown:b(ml,wf),ieTryUp:function(e,n){return e.situsFromPoint(n.left(),n.top()-5)},ieTryDown:function(e,n){return e.situsFromPoint(n.left(),n.bottom()+5)},getJumpSize:D(5)},Sf=me(),xf=function(r,o,i,u,c,a){return 0===a?Me.none():Of(r,o,i,u,c).bind(function(e){var n=r.fromSitus(e),t=cf.verify(r,i,u,n.finish(),n.foffset(),c.failure,o);return cf.cata(t,function(){return Me.none()},function(){return Me.some(e)},function(e){return Bn(i,e)&&0===u?Rf(r,i,u,gf.moveUp,c):xf(r,o,e,0,c,a-1)},function(e){return Bn(i,e)&&u===yt(e)?Rf(r,i,u,gf.moveDown,c):xf(r,o,e,yt(e),c,a-1)})})},Rf=function(n,e,t,r,o){return pf(n,e,t).bind(function(e){return Tf(n,o,r(e,Cf.getJumpSize()))})},Tf=function(e,n,t){return Sf.browser.isChrome()||Sf.browser.isSafari()||Sf.browser.isFirefox()||Sf.browser.isEdge()?n.otherRetry(e,t):Sf.browser.isIE()?n.ieRetry(e,t):Me.none()},Of=function(n,e,t,r,o){return pf(n,t,r).bind(function(e){return Tf(n,o,e)})},Df=function(n,t,r){return function(o,i,u){return o.getSelection().bind(function(r){return sf(i,r.finish(),r.foffset(),u).fold(function(){return Me.some(of(r.finish(),r.foffset()))},function(e){var n=o.fromSitus(e),t=cf.verify(o,r.finish(),r.foffset(),n.finish(),n.foffset(),u.failure,i);return df(t)})})}(n,t,r).bind(function(e){return xf(n,t,e.element(),e.offset(),r,20).map(n.fromSitus)})},Af=me(),Ef=function(e,n,t,r,o,i){return Af.browser.isIE()?Me.none():i(r,n).orThunk(function(){return pl(e,n,t,r,o).map(function(e){var n=e.range();return Fl.create(Me.some(ql.makeSitus(n.start(),n.soffset(),n.finish(),n.foffset())),!0)})})},Nf=function(e,n,t,r,o,i,u){return pl(e,t,r,o,i).bind(function(e){return Gl.detect(n,t,e.start(),e.finish(),u)})},kf=function(e,r){return nt(e,"tr",r).bind(function(t){return nt(t,"table",r).bind(function(e){var n=Be(e,"tr");return Bn(t,n[0])?function(e,n,t){return nf(rf,e,n,t)}(e,function(e){return xt(e).isSome()},r).map(function(e){var n=yt(e);return Fl.create(Me.some(ql.makeSitus(e,n,e,n)),!0)}):Me.none()})})},If=function(e,r){return nt(e,"tr",r).bind(function(t){return nt(t,"table",r).bind(function(e){var n=Be(e,"tr");return Bn(t,n[n.length-1])?function(e,n,t){return tf(rf,e,n,t)}(e,function(e){return St(e).isSome()},r).map(function(e){return Fl.create(Me.some(ql.makeSitus(e,0,e,0)),!0)}):Me.none()})})};function Bf(n){return function(e){return e===n}}function Pf(c){return{elementFromPoint:function(e,n){return on.fromPoint(on.fromDom(c.document),e,n)},getRect:function(e){return e.dom().getBoundingClientRect()},getRangedRect:function(e,n,t,r){var o=Il.exact(e,n,t,r);return Ja(c,o).map(zf)},getSelection:function(){return $a(c).map(function(e){return ql.convertToRange(c,e)})},fromSitus:function(e){var n=Il.relative(e.start(),e.finish());return ql.convertToRange(c,n)},situsFromPoint:function(e,n){return Qa(c,e,n).map(function(e){return Ul(e.start(),e.soffset(),e.finish(),e.foffset())})},clearSelection:function(){!function(e){e.getSelection().removeAllRanges()}(c)},collapseSelection:function(u){void 0===u&&(u=!1),$a(c).each(function(e){return e.fold(function(e){return e.collapse(u)},function(e,n){var t=u?e:n;Ga(c,t,t)},function(e,n,t,r){var o=u?e:t,i=u?n:r;Va(c,o,i,o,i)})})},setSelection:function(e){Va(c,e.start(),e.soffset(),e.finish(),e.foffset())},setRelativeSelection:function(e,n){Ga(c,e,n)},selectContents:function(e){Xa(c,e)},getInnerHeight:function(){return c.innerHeight},getScrollY:function(){return function(e){var n=e!==undefined?e.dom():f.document,t=n.body.scrollLeft||n.documentElement.scrollLeft,r=n.body.scrollTop||n.documentElement.scrollTop;return fo(t,r)}(on.fromDom(c.document)).top()},scrollBy:function(e,n){!function(e,n,t){(t!==undefined?t.dom():f.document).defaultView.scrollBy(e,n)}(e,n,on.fromDom(c.document))}}}function Mf(n,e){p(e,function(e){!function(e,n){So(e)?e.dom().classList.remove(n):Ro(e,n);Oo(e)}(n,e)})}var Wf={down:{traverse:ye,gather:ul,relative:Nl.before,otherRetry:Cf.tryDown,ieRetry:Cf.ieTryDown,failure:cf.failedDown},up:{traverse:we,gather:il,relative:Nl.before,otherRetry:Cf.tryUp,ieRetry:Cf.ieTryUp,failure:cf.failedUp}},_f=Bf(38),Lf=Bf(40),jf={ltr:{isBackward:Bf(37),isForward:Bf(39)},rtl:{isBackward:Bf(39),isForward:Bf(37)},isUp:_f,isDown:Lf,isNavigation:function(e){return 37<=e&&e<=40}},zf=function(e){return{left:e.left(),top:e.top(),right:e.right(),bottom:e.bottom(),width:e.width(),height:e.height()}},Hf=(me().browser.isSafari(),B("rows","cols")),Ff={mouse:function(e,n,t,r){var o=function c(o,i,n,u){function t(){r=Me.none()}var r=Me.none();return{mousedown:function(e){u.clear(i),r=hl(e.target(),n)},mouseover:function(e){r.each(function(r){u.clearBeforeUpdate(i),hl(e.target(),n).each(function(t){mr(r,t,n).each(function(e){var n=e.boxes().getOr([]);(1 0) { - el = dom.create('div', null); - el.appendChild(n[0].cloneNode(true)); - } - - function hasClass(n, c) { - return new RegExp('\\b' + c + '\\b', 'g').test(n.className); - } - - each(dom.select('*', el), function(n) { - // Replace cdate - if (hasClass(n, editor.getParam('template_cdate_classes', 'cdate').replace(/\s+/g, '|'))) { - n.innerHTML = getDateTime(editor.getParam("template_cdate_format", editor.getLang("template.cdate_format"))); - } - - // Replace mdate - if (hasClass(n, editor.getParam('template_mdate_classes', 'mdate').replace(/\s+/g, '|'))) { - n.innerHTML = getDateTime(editor.getParam("template_mdate_format", editor.getLang("template.mdate_format"))); - } - - // Replace selection - if (hasClass(n, editor.getParam('template_selected_content_classes', 'selcontent').replace(/\s+/g, '|'))) { - n.innerHTML = sel; - } - }); - - replaceVals(el); - - editor.execCommand('mceInsertContent', false, el.innerHTML); - editor.addVisual(); - } - - editor.addCommand('mceInsertTemplate', insertTemplate); - - editor.addButton('template', { - title: 'Insert template', - onclick: showDialog - }); - - editor.addMenuItem('image', { - text: 'Insert template', - onclick: showDialog, - context: 'insert' - }); - - editor.on('PreProcess', function(o) { - var dom = editor.dom; - - each(dom.select('div', o.node), function(e) { - if (dom.hasClass(e, 'mceTmpl')) { - each(dom.select('*', e), function(e) { - if (dom.hasClass(e, editor.getParam('template_mdate_classes', 'mdate').replace(/\s+/g, '|'))) { - e.innerHTML = getDateTime(editor.getParam("template_mdate_format", editor.getLang("template.mdate_format"))); - } - }); - - replaceVals(e); - } - }); - }); -}); \ No newline at end of file +(function () { + 'use strict'; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var noop = function () { + }; + var constant = function (value) { + return function () { + return value; + }; + }; + function curry(fn) { + var initialArgs = []; + for (var _i = 1; _i < arguments.length; _i++) { + initialArgs[_i - 1] = arguments[_i]; + } + return function () { + var restArgs = []; + for (var _i = 0; _i < arguments.length; _i++) { + restArgs[_i] = arguments[_i]; + } + var all = initialArgs.concat(restArgs); + return fn.apply(null, all); + }; + } + var never = constant(false); + var always = constant(true); + + var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + + var global$2 = tinymce.util.Tools.resolve('tinymce.util.XHR'); + + var getCreationDateClasses = function (editor) { + return editor.getParam('template_cdate_classes', 'cdate'); + }; + var getModificationDateClasses = function (editor) { + return editor.getParam('template_mdate_classes', 'mdate'); + }; + var getSelectedContentClasses = function (editor) { + return editor.getParam('template_selected_content_classes', 'selcontent'); + }; + var getPreviewReplaceValues = function (editor) { + return editor.getParam('template_preview_replace_values'); + }; + var getTemplateReplaceValues = function (editor) { + return editor.getParam('template_replace_values'); + }; + var getTemplates = function (editorSettings) { + return editorSettings.templates; + }; + var getCdateFormat = function (editor) { + return editor.getParam('template_cdate_format', editor.translate('%Y-%m-%d')); + }; + var getMdateFormat = function (editor) { + return editor.getParam('template_mdate_format', editor.translate('%Y-%m-%d')); + }; + var Settings = { + getCreationDateClasses: getCreationDateClasses, + getModificationDateClasses: getModificationDateClasses, + getSelectedContentClasses: getSelectedContentClasses, + getPreviewReplaceValues: getPreviewReplaceValues, + getTemplateReplaceValues: getTemplateReplaceValues, + getTemplates: getTemplates, + getCdateFormat: getCdateFormat, + getMdateFormat: getMdateFormat + }; + + var addZeros = function (value, len) { + value = '' + value; + if (value.length < len) { + for (var i = 0; i < len - value.length; i++) { + value = '0' + value; + } + } + return value; + }; + var getDateTime = function (editor, fmt, date) { + var daysShort = 'Sun Mon Tue Wed Thu Fri Sat Sun'.split(' '); + var daysLong = 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday'.split(' '); + var monthsShort = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split(' '); + var monthsLong = 'January February March April May June July August September October November December'.split(' '); + date = date || new Date(); + fmt = fmt.replace('%D', '%m/%d/%Y'); + fmt = fmt.replace('%r', '%I:%M:%S %p'); + fmt = fmt.replace('%Y', '' + date.getFullYear()); + fmt = fmt.replace('%y', '' + date.getYear()); + fmt = fmt.replace('%m', addZeros(date.getMonth() + 1, 2)); + fmt = fmt.replace('%d', addZeros(date.getDate(), 2)); + fmt = fmt.replace('%H', '' + addZeros(date.getHours(), 2)); + fmt = fmt.replace('%M', '' + addZeros(date.getMinutes(), 2)); + fmt = fmt.replace('%S', '' + addZeros(date.getSeconds(), 2)); + fmt = fmt.replace('%I', '' + ((date.getHours() + 11) % 12 + 1)); + fmt = fmt.replace('%p', '' + (date.getHours() < 12 ? 'AM' : 'PM')); + fmt = fmt.replace('%B', '' + editor.translate(monthsLong[date.getMonth()])); + fmt = fmt.replace('%b', '' + editor.translate(monthsShort[date.getMonth()])); + fmt = fmt.replace('%A', '' + editor.translate(daysLong[date.getDay()])); + fmt = fmt.replace('%a', '' + editor.translate(daysShort[date.getDay()])); + fmt = fmt.replace('%%', '%'); + return fmt; + }; + var DateTimeHelper = { getDateTime: getDateTime }; + + var createTemplateList = function (editorSettings, callback) { + return function () { + var templateList = Settings.getTemplates(editorSettings); + if (typeof templateList === 'function') { + templateList(callback); + return; + } + if (typeof templateList === 'string') { + global$2.send({ + url: templateList, + success: function (text) { + callback(JSON.parse(text)); + } + }); + } else { + callback(templateList); + } + }; + }; + var replaceTemplateValues = function (html, templateValues) { + global$1.each(templateValues, function (v, k) { + if (typeof v === 'function') { + v = v(k); + } + html = html.replace(new RegExp('\\{\\$' + k + '\\}', 'g'), v); + }); + return html; + }; + var replaceVals = function (editor, e) { + var dom = editor.dom, vl = Settings.getTemplateReplaceValues(editor); + global$1.each(dom.select('*', e), function (e) { + global$1.each(vl, function (v, k) { + if (dom.hasClass(e, k)) { + if (typeof vl[k] === 'function') { + vl[k](e); + } + } + }); + }); + }; + var hasClass = function (n, c) { + return new RegExp('\\b' + c + '\\b', 'g').test(n.className); + }; + var insertTemplate = function (editor, ui, html) { + var el; + var n; + var dom = editor.dom; + var sel = editor.selection.getContent(); + html = replaceTemplateValues(html, Settings.getTemplateReplaceValues(editor)); + el = dom.create('div', null, html); + n = dom.select('.mceTmpl', el); + if (n && n.length > 0) { + el = dom.create('div', null); + el.appendChild(n[0].cloneNode(true)); + } + global$1.each(dom.select('*', el), function (n) { + if (hasClass(n, Settings.getCreationDateClasses(editor).replace(/\s+/g, '|'))) { + n.innerHTML = DateTimeHelper.getDateTime(editor, Settings.getCdateFormat(editor)); + } + if (hasClass(n, Settings.getModificationDateClasses(editor).replace(/\s+/g, '|'))) { + n.innerHTML = DateTimeHelper.getDateTime(editor, Settings.getMdateFormat(editor)); + } + if (hasClass(n, Settings.getSelectedContentClasses(editor).replace(/\s+/g, '|'))) { + n.innerHTML = sel; + } + }); + replaceVals(editor, el); + editor.execCommand('mceInsertContent', false, el.innerHTML); + editor.addVisual(); + }; + var Templates = { + createTemplateList: createTemplateList, + replaceTemplateValues: replaceTemplateValues, + replaceVals: replaceVals, + insertTemplate: insertTemplate + }; + + var register = function (editor) { + editor.addCommand('mceInsertTemplate', curry(Templates.insertTemplate, editor)); + }; + var Commands = { register: register }; + + var setup = function (editor) { + editor.on('PreProcess', function (o) { + var dom = editor.dom, dateFormat = Settings.getMdateFormat(editor); + global$1.each(dom.select('div', o.node), function (e) { + if (dom.hasClass(e, 'mceTmpl')) { + global$1.each(dom.select('*', e), function (e) { + if (dom.hasClass(e, editor.getParam('template_mdate_classes', 'mdate').replace(/\s+/g, '|'))) { + e.innerHTML = DateTimeHelper.getDateTime(editor, dateFormat); + } + }); + Templates.replaceVals(editor, e); + } + }); + }); + }; + var FilterContent = { setup: setup }; + + var none = function () { + return NONE; + }; + var NONE = function () { + var eq = function (o) { + return o.isNone(); + }; + var call = function (thunk) { + return thunk(); + }; + var id = function (n) { + return n; + }; + var me = { + fold: function (n, s) { + return n(); + }, + is: never, + isSome: never, + isNone: always, + getOr: id, + getOrThunk: call, + getOrDie: function (msg) { + throw new Error(msg || 'error: getOrDie called on none.'); + }, + getOrNull: constant(null), + getOrUndefined: constant(undefined), + or: id, + orThunk: call, + map: none, + each: noop, + bind: none, + exists: never, + forall: always, + filter: none, + equals: eq, + equals_: eq, + toArray: function () { + return []; + }, + toString: constant('none()') + }; + if (Object.freeze) { + Object.freeze(me); + } + return me; + }(); + var some = function (a) { + var constant_a = constant(a); + var self = function () { + return me; + }; + var bind = function (f) { + return f(a); + }; + var me = { + fold: function (n, s) { + return s(a); + }, + is: function (v) { + return a === v; + }, + isSome: always, + isNone: never, + getOr: constant_a, + getOrThunk: constant_a, + getOrDie: constant_a, + getOrNull: constant_a, + getOrUndefined: constant_a, + or: self, + orThunk: self, + map: function (f) { + return some(f(a)); + }, + each: function (f) { + f(a); + }, + bind: bind, + exists: bind, + forall: bind, + filter: function (f) { + return f(a) ? me : NONE; + }, + toArray: function () { + return [a]; + }, + toString: function () { + return 'some(' + a + ')'; + }, + equals: function (o) { + return o.is(a); + }, + equals_: function (o, elementEq) { + return o.fold(never, function (b) { + return elementEq(a, b); + }); + } + }; + return me; + }; + var from = function (value) { + return value === null || value === undefined ? NONE : some(value); + }; + var Option = { + some: some, + none: none, + from: from + }; + + var typeOf = function (x) { + if (x === null) { + return 'null'; + } + var t = typeof x; + if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) { + return 'array'; + } + if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) { + return 'string'; + } + return t; + }; + var isType = function (type) { + return function (value) { + return typeOf(value) === type; + }; + }; + var isFunction = isType('function'); + + var nativeSlice = Array.prototype.slice; + var map = function (xs, f) { + var len = xs.length; + var r = new Array(len); + for (var i = 0; i < len; i++) { + var x = xs[i]; + r[i] = f(x, i); + } + return r; + }; + var find = function (xs, pred) { + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + if (pred(x, i)) { + return Option.some(x); + } + } + return Option.none(); + }; + var from$1 = isFunction(Array.from) ? Array.from : function (x) { + return nativeSlice.call(x); + }; + + var global$3 = tinymce.util.Tools.resolve('tinymce.util.Promise'); + + var hasOwnProperty = Object.hasOwnProperty; + var get = function (obj, key) { + return has(obj, key) ? Option.from(obj[key]) : Option.none(); + }; + var has = function (obj, key) { + return hasOwnProperty.call(obj, key); + }; + + var entitiesAttr = { + '"': '"', + '<': '<', + '>': '>', + '&': '&', + '\'': ''' + }; + var htmlEscape = function (html) { + return html.replace(/["'<>&]/g, function (match) { + return get(entitiesAttr, match).getOr(match); + }); + }; + + var getPreviewContent = function (editor, html) { + if (html.indexOf('') === -1) { + var contentCssLinks_1 = ''; + global$1.each(editor.contentCSS, function (url) { + contentCssLinks_1 += ''; + }); + var bodyClass = editor.settings.body_class || ''; + if (bodyClass.indexOf('=') !== -1) { + bodyClass = editor.getParam('body_class', '', 'hash'); + bodyClass = bodyClass[editor.id] || ''; + } + var encode = editor.dom.encode; + var directionality = editor.getBody().dir; + var dirAttr = directionality ? ' dir="' + encode(directionality) + '"' : ''; + html = '' + '' + '' + contentCssLinks_1 + '' + '' + html + '' + ''; + } + return Templates.replaceTemplateValues(html, Settings.getPreviewReplaceValues(editor)); + }; + var open = function (editor, templateList) { + var createTemplates = function () { + if (!templateList || templateList.length === 0) { + var message = editor.translate('No templates defined.'); + editor.notificationManager.open({ + text: message, + type: 'info' + }); + return Option.none(); + } + return Option.from(global$1.map(templateList, function (template, index) { + var isUrlTemplate = function (t) { + return t.url !== undefined; + }; + return { + selected: index === 0, + text: template.title, + value: { + url: isUrlTemplate(template) ? Option.from(template.url) : Option.none(), + content: !isUrlTemplate(template) ? Option.from(template.content) : Option.none(), + description: template.description + } + }; + })); + }; + var createSelectBoxItems = function (templates) { + return map(templates, function (t) { + return { + text: t.text, + value: t.text + }; + }); + }; + var findTemplate = function (templates, templateTitle) { + return find(templates, function (t) { + return t.text === templateTitle; + }); + }; + var getTemplateContent = function (t) { + return new global$3(function (resolve, reject) { + t.value.url.fold(function () { + return resolve(t.value.content.getOr('')); + }, function (url) { + return global$2.send({ + url: url, + success: function (html) { + resolve(html); + }, + error: function (e) { + reject(e); + } + }); + }); + }); + }; + var onChange = function (templates, updateDialog) { + return function (api, change) { + if (change.name === 'template') { + var newTemplateTitle = api.getData().template; + findTemplate(templates, newTemplateTitle).each(function (t) { + api.block('Loading...'); + getTemplateContent(t).then(function (previewHtml) { + updateDialog(api, t, previewHtml); + api.unblock(); + }); + }); + } + }; + }; + var onSubmit = function (templates) { + return function (api) { + var data = api.getData(); + findTemplate(templates, data.template).each(function (t) { + getTemplateContent(t).then(function (previewHtml) { + Templates.insertTemplate(editor, false, previewHtml); + api.close(); + }); + }); + }; + }; + var openDialog = function (templates) { + var selectBoxItems = createSelectBoxItems(templates); + var buildDialogSpec = function (bodyItems, initialData) { + return { + title: 'Insert Template', + size: 'large', + body: { + type: 'panel', + items: bodyItems + }, + initialData: initialData, + buttons: [ + { + type: 'cancel', + name: 'cancel', + text: 'Cancel' + }, + { + type: 'submit', + name: 'save', + text: 'Save', + primary: true + } + ], + onSubmit: onSubmit(templates), + onChange: onChange(templates, updateDialog) + }; + }; + var updateDialog = function (dialogApi, template, previewHtml) { + var content = getPreviewContent(editor, previewHtml); + var bodyItems = [ + { + type: 'selectbox', + name: 'template', + label: 'Templates', + items: selectBoxItems + }, + { + type: 'htmlpanel', + html: ' ' + htmlEscape(template.value.description) + '
' + }, + { + label: 'Preview', + type: 'iframe', + name: 'preview', + sandboxed: false + } + ]; + var initialData = { + template: template.text, + preview: content + }; + dialogApi.unblock(); + dialogApi.redial(buildDialogSpec(bodyItems, initialData)); + dialogApi.focus('template'); + }; + var dialogApi = editor.windowManager.open(buildDialogSpec([], { + template: '', + preview: '' + })); + dialogApi.block('Loading...'); + getTemplateContent(templates[0]).then(function (previewHtml) { + updateDialog(dialogApi, templates[0], previewHtml); + }); + }; + var optTemplates = createTemplates(); + optTemplates.each(openDialog); + }; + var Dialog = { open: open }; + + var showDialog = function (editor) { + return function (templates) { + Dialog.open(editor, templates); + }; + }; + var register$1 = function (editor) { + editor.ui.registry.addButton('template', { + icon: 'template', + tooltip: 'Insert template', + onAction: Templates.createTemplateList(editor.settings, showDialog(editor)) + }); + editor.ui.registry.addMenuItem('template', { + icon: 'template', + text: 'Insert template...', + onAction: Templates.createTemplateList(editor.settings, showDialog(editor)) + }); + }; + var Buttons = { register: register$1 }; + + function Plugin () { + global.add('template', function (editor) { + Buttons.register(editor); + Commands.register(editor); + FilterContent.setup(editor); + }); + } + + Plugin(); + +}()); diff --git a/lib/tinymce/js/tinymce/plugins/template/plugin.min.js b/lib/tinymce/js/tinymce/plugins/template/plugin.min.js index bde4dbb4..14057a09 100644 --- a/lib/tinymce/js/tinymce/plugins/template/plugin.min.js +++ b/lib/tinymce/js/tinymce/plugins/template/plugin.min.js @@ -1 +1,9 @@ -tinymce.PluginManager.add("template",function(e){function t(){function t(e){var t=e.control.value();t.url?tinymce.util.XHR.send({url:t.url,success:function(e){a=e,n.find("iframe")[0].html(e)}}):(a=t.content,n.find("iframe")[0].html(t.content)),n.find("#description")[0].text(e.control.value().description)}var n,a,r=[];return e.settings.templates?(tinymce.each(e.settings.templates,function(e){r.push({text:e.title,value:{url:e.url,content:e.content,description:e.description}})}),n=e.windowManager.open({title:"Insert template",body:[{type:"listbox",name:"template",flex:0,label:"Templates",values:r,onselect:t},{type:"label",name:"description",label:"Description",text:""},{type:"iframe",minWidth:600,minHeight:400,border:1}],onsubmit:function(){i(!1,a)}}),void 0):(e.windowManager.alert("No templates defined"),void 0)}function n(t,n){function a(e,t){if(e=""+e,t>e.length)for(var n=0;t-e.length>n;n++)e="0"+e;return e}var i="Sun Mon Tue Wed Thu Fri Sat Sun".split(" "),r="Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(" "),o="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),l="January February March April May June July August September October November December".split(" ");return n=n||new Date,t=t.replace("%D","%m/%d/%Y"),t=t.replace("%r","%I:%M:%S %p"),t=t.replace("%Y",""+n.getFullYear()),t=t.replace("%y",""+n.getYear()),t=t.replace("%m",a(n.getMonth()+1,2)),t=t.replace("%d",a(n.getDate(),2)),t=t.replace("%H",""+a(n.getHours(),2)),t=t.replace("%M",""+a(n.getMinutes(),2)),t=t.replace("%S",""+a(n.getSeconds(),2)),t=t.replace("%I",""+((n.getHours()+11)%12+1)),t=t.replace("%p",""+(12>n.getHours()?"AM":"PM")),t=t.replace("%B",""+e.translate(l[n.getMonth()])),t=t.replace("%b",""+e.translate(o[n.getMonth()])),t=t.replace("%A",""+e.translate(r[n.getDay()])),t=t.replace("%a",""+e.translate(i[n.getDay()])),t=t.replace("%%","%")}function a(t){var n=e.dom,a=e.getParam("template_replace_values");r(n.select("*",t),function(e){r(a,function(t,i){n.hasClass(e,i)&&"function"==typeof a[i]&&a[i](e)})})}function i(t,i){function o(e,t){return RegExp("\\b"+t+"\\b","g").test(e.className)}var l,c,s=e.dom,d=e.selection.getContent();r(e.getParam("template_replace_values"),function(e,t){"function"!=typeof e&&(i=i.replace(RegExp("\\{\\$"+t+"\\}","g"),e))}),l=s.create("div",null,i),c=s.select(".mceTmpl",l),c&&c.length>0&&(l=s.create("div",null),l.appendChild(c[0].cloneNode(!0))),r(s.select("*",l),function(t){o(t,e.getParam("template_cdate_classes","cdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_cdate_format",e.getLang("template.cdate_format")))),o(t,e.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_mdate_format",e.getLang("template.mdate_format")))),o(t,e.getParam("template_selected_content_classes","selcontent").replace(/\s+/g,"|"))&&(t.innerHTML=d)}),a(l),e.execCommand("mceInsertContent",!1,l.innerHTML),e.addVisual()}var r=tinymce.each;e.addCommand("mceInsertTemplate",i),e.addButton("template",{title:"Insert template",onclick:t}),e.addMenuItem("image",{text:"Insert template",onclick:t,context:"insert"}),e.on("PreProcess",function(t){var i=e.dom;r(i.select("div",t.node),function(t){i.hasClass(t,"mceTmpl")&&(r(i.select("*",t),function(t){i.hasClass(t,e.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_mdate_format",e.getLang("template.mdate_format"))))}),a(t))})})}); \ No newline at end of file +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.1.6 (2020-01-28) + */ +!function(){"use strict";function e(){}function a(e){return function(){return e}}var t=tinymce.util.Tools.resolve("tinymce.PluginManager");function c(e,t){if((e=""+e).length&]/g,function(e){return function(e,t){return B(e,t)?L.from(e[t]):L.none()}(E,e).getOr(e)})}function k(t){return function(e){R(t,e)}}var I,J=function(n){function e(){return o}function t(e){return e(n)}var r=a(n),o={fold:function(e,t){return t(n)},is:function(e){return n===e},isSome:f,isNone:u,getOr:r,getOrThunk:r,getOrDie:r,getOrNull:r,getOrUndefined:r,or:e,orThunk:e,map:function(e){return J(e(n))},each:function(e){e(n)},bind:t,exists:t,forall:t,filter:function(e){return e(n)?o:w},toArray:function(){return[n]},toString:function(){return"some("+n+")"},equals:function(e){return e.is(n)},equals_:function(e,t){return e.fold(u,function(e){return t(n,e)})}};return o},L={some:J,none:n,from:function(e){return null===e||e===undefined?w:J(e)}},Y=(I="function",function(e){return function(e){if(null===e)return"null";var t=typeof e;return"object"==t&&(Array.prototype.isPrototypeOf(e)||e.constructor&&"Array"===e.constructor.name)?"array":"object"==t&&(String.prototype.isPrototypeOf(e)||e.constructor&&"String"===e.constructor.name)?"string":t}(e)===I}),j=Array.prototype.slice,q=(Y(Array.from)&&Array.from,tinymce.util.Tools.resolve("tinymce.util.Promise")),F=Object.hasOwnProperty,B=function(e,t){return F.call(e,t)},E={'"':""","<":"<",">":">","&":"&","'":"'"},R=function(i,t){function e(e){return function(e,t){for(var n=e.length,r=new Array(n),o=0;o ")){var n="";p.each(t.contentCSS,function(e){n+=''});var r=t.settings.body_class||"";-1!==r.indexOf("=")&&(r=(r=t.getParam("body_class","","hash"))[t.id]||"");var o=t.dom.encode,a=t.getBody().dir,u=a?' dir="'+o(a)+'"':"";e=""+n+'"+e+""}return S(e,y(t))}(i,n),o=[{type:"selectbox",name:"template",label:"Templates",items:c},{type:"htmlpanel",html:' '+H(t.value.description)+"
"},{label:"Preview",type:"iframe",name:"preview",sandboxed:!1}],a={template:t.text,preview:r};e.unblock(),e.redial(u(o,a)),e.focus("template")},t=i.windowManager.open(u([],{template:"",preview:""}));t.block("Loading..."),l(n[0]).then(function(e){r(t,n[0],e)})})},z=function(e){e.ui.registry.addButton("template",{icon:"template",tooltip:"Insert template",onAction:M(e.settings,k(e))}),e.ui.registry.addMenuItem("template",{icon:"template",text:"Insert template...",onAction:M(e.settings,k(e))})};!function U(){t.add("template",function(e){z(e),P(e),A(e)})}()}(); \ No newline at end of file diff --git a/lib/tinymce/js/tinymce/plugins/textcolor/plugin.js b/lib/tinymce/js/tinymce/plugins/textcolor/plugin.js new file mode 100644 index 00000000..2114d83c --- /dev/null +++ b/lib/tinymce/js/tinymce/plugins/textcolor/plugin.js @@ -0,0 +1,22 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.1.6 (2020-01-28) + */ +(function (domGlobals) { + 'use strict'; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + function Plugin () { + global.add('textcolor', function () { + domGlobals.console.warn('Text color plugin is now built in to the core editor, please remove it from your editor configuration'); + }); + } + + Plugin(); + +}(window)); diff --git a/lib/tinymce/js/tinymce/plugins/textcolor/plugin.min.js b/lib/tinymce/js/tinymce/plugins/textcolor/plugin.min.js new file mode 100644 index 00000000..ee182849 --- /dev/null +++ b/lib/tinymce/js/tinymce/plugins/textcolor/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.1.6 (2020-01-28) + */ +!function(o){"use strict";var i=tinymce.util.Tools.resolve("tinymce.PluginManager");!function n(){i.add("textcolor",function(){o.console.warn("Text color plugin is now built in to the core editor, please remove it from your editor configuration")})}()}(window); \ No newline at end of file diff --git a/lib/tinymce/js/tinymce/plugins/textpattern/plugin.js b/lib/tinymce/js/tinymce/plugins/textpattern/plugin.js new file mode 100644 index 00000000..24fcbb78 --- /dev/null +++ b/lib/tinymce/js/tinymce/plugins/textpattern/plugin.js @@ -0,0 +1,1444 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.1.6 (2020-01-28) + */ +(function (domGlobals) { + 'use strict'; + + var Cell = function (initial) { + var value = initial; + var get = function () { + return value; + }; + var set = function (v) { + value = v; + }; + var clone = function () { + return Cell(get()); + }; + return { + get: get, + set: set, + clone: clone + }; + }; + + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); + + var __assign = function () { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) + if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + function __spreadArrays() { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) + s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) + for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) + r[k] = a[j]; + return r; + } + + var noop = function () { + }; + var constant = function (value) { + return function () { + return value; + }; + }; + var identity = function (x) { + return x; + }; + var die = function (msg) { + return function () { + throw new Error(msg); + }; + }; + var never = constant(false); + var always = constant(true); + + var none = function () { + return NONE; + }; + var NONE = function () { + var eq = function (o) { + return o.isNone(); + }; + var call = function (thunk) { + return thunk(); + }; + var id = function (n) { + return n; + }; + var me = { + fold: function (n, s) { + return n(); + }, + is: never, + isSome: never, + isNone: always, + getOr: id, + getOrThunk: call, + getOrDie: function (msg) { + throw new Error(msg || 'error: getOrDie called on none.'); + }, + getOrNull: constant(null), + getOrUndefined: constant(undefined), + or: id, + orThunk: call, + map: none, + each: noop, + bind: none, + exists: never, + forall: always, + filter: none, + equals: eq, + equals_: eq, + toArray: function () { + return []; + }, + toString: constant('none()') + }; + if (Object.freeze) { + Object.freeze(me); + } + return me; + }(); + var some = function (a) { + var constant_a = constant(a); + var self = function () { + return me; + }; + var bind = function (f) { + return f(a); + }; + var me = { + fold: function (n, s) { + return s(a); + }, + is: function (v) { + return a === v; + }, + isSome: always, + isNone: never, + getOr: constant_a, + getOrThunk: constant_a, + getOrDie: constant_a, + getOrNull: constant_a, + getOrUndefined: constant_a, + or: self, + orThunk: self, + map: function (f) { + return some(f(a)); + }, + each: function (f) { + f(a); + }, + bind: bind, + exists: bind, + forall: bind, + filter: function (f) { + return f(a) ? me : NONE; + }, + toArray: function () { + return [a]; + }, + toString: function () { + return 'some(' + a + ')'; + }, + equals: function (o) { + return o.is(a); + }, + equals_: function (o, elementEq) { + return o.fold(never, function (b) { + return elementEq(a, b); + }); + } + }; + return me; + }; + var from = function (value) { + return value === null || value === undefined ? NONE : some(value); + }; + var Option = { + some: some, + none: none, + from: from + }; + + var typeOf = function (x) { + if (x === null) { + return 'null'; + } + var t = typeof x; + if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) { + return 'array'; + } + if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) { + return 'string'; + } + return t; + }; + var isType = function (type) { + return function (value) { + return typeOf(value) === type; + }; + }; + var isString = isType('string'); + var isObject = isType('object'); + var isArray = isType('array'); + var isFunction = isType('function'); + + var nativeSlice = Array.prototype.slice; + var nativeIndexOf = Array.prototype.indexOf; + var rawIndexOf = function (ts, t) { + return nativeIndexOf.call(ts, t); + }; + var contains = function (xs, x) { + return rawIndexOf(xs, x) > -1; + }; + var map = function (xs, f) { + var len = xs.length; + var r = new Array(len); + for (var i = 0; i < len; i++) { + var x = xs[i]; + r[i] = f(x, i); + } + return r; + }; + var each = function (xs, f) { + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + f(x, i); + } + }; + var eachr = function (xs, f) { + for (var i = xs.length - 1; i >= 0; i--) { + var x = xs[i]; + f(x, i); + } + }; + var filter = function (xs, pred) { + var r = []; + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + if (pred(x, i)) { + r.push(x); + } + } + return r; + }; + var foldr = function (xs, f, acc) { + eachr(xs, function (x) { + acc = f(acc, x); + }); + return acc; + }; + var foldl = function (xs, f, acc) { + each(xs, function (x) { + acc = f(acc, x); + }); + return acc; + }; + var find = function (xs, pred) { + for (var i = 0, len = xs.length; i < len; i++) { + var x = xs[i]; + if (pred(x, i)) { + return Option.some(x); + } + } + return Option.none(); + }; + var forall = function (xs, pred) { + for (var i = 0, len = xs.length; i < len; ++i) { + var x = xs[i]; + if (pred(x, i) !== true) { + return false; + } + } + return true; + }; + var sort = function (xs, comparator) { + var copy = nativeSlice.call(xs, 0); + copy.sort(comparator); + return copy; + }; + var head = function (xs) { + return xs.length === 0 ? Option.none() : Option.some(xs[0]); + }; + var from$1 = isFunction(Array.from) ? Array.from : function (x) { + return nativeSlice.call(x); + }; + + var keys = Object.keys; + var hasOwnProperty = Object.hasOwnProperty; + var get = function (obj, key) { + return has(obj, key) ? Option.from(obj[key]) : Option.none(); + }; + var has = function (obj, key) { + return hasOwnProperty.call(obj, key); + }; + + var generate = function (cases) { + if (!isArray(cases)) { + throw new Error('cases must be an array'); + } + if (cases.length === 0) { + throw new Error('there must be at least one case'); + } + var constructors = []; + var adt = {}; + each(cases, function (acase, count) { + var keys$1 = keys(acase); + if (keys$1.length !== 1) { + throw new Error('one and only one name per case'); + } + var key = keys$1[0]; + var value = acase[key]; + if (adt[key] !== undefined) { + throw new Error('duplicate key detected:' + key); + } else if (key === 'cata') { + throw new Error('cannot have a case named cata (sorry)'); + } else if (!isArray(value)) { + throw new Error('case arguments must be an array'); + } + constructors.push(key); + adt[key] = function () { + var argLength = arguments.length; + if (argLength !== value.length) { + throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength); + } + var args = new Array(argLength); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i]; + } + var match = function (branches) { + var branchKeys = keys(branches); + if (constructors.length !== branchKeys.length) { + throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(',')); + } + var allReqd = forall(constructors, function (reqKey) { + return contains(branchKeys, reqKey); + }); + if (!allReqd) { + throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', ')); + } + return branches[key].apply(null, args); + }; + return { + fold: function () { + if (arguments.length !== cases.length) { + throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + arguments.length); + } + var target = arguments[count]; + return target.apply(null, args); + }, + match: match, + log: function (label) { + domGlobals.console.log(label, { + constructors: constructors, + constructor: key, + params: args + }); + } + }; + }; + }); + return adt; + }; + var Adt = { generate: generate }; + + var comparison = Adt.generate([ + { + bothErrors: [ + 'error1', + 'error2' + ] + }, + { + firstError: [ + 'error1', + 'value2' + ] + }, + { + secondError: [ + 'value1', + 'error2' + ] + }, + { + bothValues: [ + 'value1', + 'value2' + ] + } + ]); + var partition = function (results) { + var errors = []; + var values = []; + each(results, function (result) { + result.fold(function (err) { + errors.push(err); + }, function (value) { + values.push(value); + }); + }); + return { + errors: errors, + values: values + }; + }; + + var value = function (o) { + var is = function (v) { + return o === v; + }; + var or = function (opt) { + return value(o); + }; + var orThunk = function (f) { + return value(o); + }; + var map = function (f) { + return value(f(o)); + }; + var mapError = function (f) { + return value(o); + }; + var each = function (f) { + f(o); + }; + var bind = function (f) { + return f(o); + }; + var fold = function (_, onValue) { + return onValue(o); + }; + var exists = function (f) { + return f(o); + }; + var forall = function (f) { + return f(o); + }; + var toOption = function () { + return Option.some(o); + }; + return { + is: is, + isValue: always, + isError: never, + getOr: constant(o), + getOrThunk: constant(o), + getOrDie: constant(o), + or: or, + orThunk: orThunk, + fold: fold, + map: map, + mapError: mapError, + each: each, + bind: bind, + exists: exists, + forall: forall, + toOption: toOption + }; + }; + var error = function (message) { + var getOrThunk = function (f) { + return f(); + }; + var getOrDie = function () { + return die(String(message))(); + }; + var or = function (opt) { + return opt; + }; + var orThunk = function (f) { + return f(); + }; + var map = function (f) { + return error(message); + }; + var mapError = function (f) { + return error(f(message)); + }; + var bind = function (f) { + return error(message); + }; + var fold = function (onError, _) { + return onError(message); + }; + return { + is: never, + isValue: never, + isError: always, + getOr: identity, + getOrThunk: getOrThunk, + getOrDie: getOrDie, + or: or, + orThunk: orThunk, + fold: fold, + map: map, + mapError: mapError, + each: noop, + bind: bind, + exists: never, + forall: always, + toOption: Option.none + }; + }; + var fromOption = function (opt, err) { + return opt.fold(function () { + return error(err); + }, value); + }; + var Result = { + value: value, + error: error, + fromOption: fromOption + }; + + var isInlinePattern = function (pattern) { + return pattern.type === 'inline-command' || pattern.type === 'inline-format'; + }; + var isBlockPattern = function (pattern) { + return pattern.type === 'block-command' || pattern.type === 'block-format'; + }; + var sortPatterns = function (patterns) { + return sort(patterns, function (a, b) { + if (a.start.length === b.start.length) { + return 0; + } + return a.start.length > b.start.length ? -1 : 1; + }); + }; + var normalizePattern = function (pattern) { + var err = function (message) { + return Result.error({ + message: message, + pattern: pattern + }); + }; + var formatOrCmd = function (name, onFormat, onCommand) { + if (pattern.format !== undefined) { + var formats = void 0; + if (isArray(pattern.format)) { + if (!forall(pattern.format, isString)) { + return err(name + ' pattern has non-string items in the `format` array'); + } + formats = pattern.format; + } else if (isString(pattern.format)) { + formats = [pattern.format]; + } else { + return err(name + ' pattern has non-string `format` parameter'); + } + return Result.value(onFormat(formats)); + } else if (pattern.cmd !== undefined) { + if (!isString(pattern.cmd)) { + return err(name + ' pattern has non-string `cmd` parameter'); + } + return Result.value(onCommand(pattern.cmd, pattern.value)); + } else { + return err(name + ' pattern is missing both `format` and `cmd` parameters'); + } + }; + if (!isObject(pattern)) { + return err('Raw pattern is not an object'); + } + if (!isString(pattern.start)) { + return err('Raw pattern is missing `start` parameter'); + } + if (pattern.end !== undefined) { + if (!isString(pattern.end)) { + return err('Inline pattern has non-string `end` parameter'); + } + if (pattern.start.length === 0 && pattern.end.length === 0) { + return err('Inline pattern has empty `start` and `end` parameters'); + } + var start_1 = pattern.start; + var end_1 = pattern.end; + if (end_1.length === 0) { + end_1 = start_1; + start_1 = ''; + } + return formatOrCmd('Inline', function (format) { + return { + type: 'inline-format', + start: start_1, + end: end_1, + format: format + }; + }, function (cmd, value) { + return { + type: 'inline-command', + start: start_1, + end: end_1, + cmd: cmd, + value: value + }; + }); + } else if (pattern.replacement !== undefined) { + if (!isString(pattern.replacement)) { + return err('Replacement pattern has non-string `replacement` parameter'); + } + if (pattern.start.length === 0) { + return err('Replacement pattern has empty `start` parameter'); + } + return Result.value({ + type: 'inline-command', + start: '', + end: pattern.start, + cmd: 'mceInsertContent', + value: pattern.replacement + }); + } else { + if (pattern.start.length === 0) { + return err('Block pattern has empty `start` parameter'); + } + return formatOrCmd('Block', function (formats) { + return { + type: 'block-format', + start: pattern.start, + format: formats[0] + }; + }, function (command, commandValue) { + return { + type: 'block-command', + start: pattern.start, + cmd: command, + value: commandValue + }; + }); + } + }; + var denormalizePattern = function (pattern) { + if (pattern.type === 'block-command') { + return { + start: pattern.start, + cmd: pattern.cmd, + value: pattern.value + }; + } else if (pattern.type === 'block-format') { + return { + start: pattern.start, + format: pattern.format + }; + } else if (pattern.type === 'inline-command') { + if (pattern.cmd === 'mceInsertContent' && pattern.start === '') { + return { + start: pattern.end, + replacement: pattern.value + }; + } else { + return { + start: pattern.start, + end: pattern.end, + cmd: pattern.cmd, + value: pattern.value + }; + } + } else if (pattern.type === 'inline-format') { + return { + start: pattern.start, + end: pattern.end, + format: pattern.format.length === 1 ? pattern.format[0] : pattern.format + }; + } + }; + var createPatternSet = function (patterns) { + return { + inlinePatterns: filter(patterns, isInlinePattern), + blockPatterns: sortPatterns(filter(patterns, isBlockPattern)) + }; + }; + + var get$1 = function (patternsState) { + var setPatterns = function (newPatterns) { + var normalized = partition(map(newPatterns, normalizePattern)); + if (normalized.errors.length > 0) { + var firstError = normalized.errors[0]; + throw new Error(firstError.message + ':\n' + JSON.stringify(firstError.pattern, null, 2)); + } + patternsState.set(createPatternSet(normalized.values)); + }; + var getPatterns = function () { + return __spreadArrays(map(patternsState.get().inlinePatterns, denormalizePattern), map(patternsState.get().blockPatterns, denormalizePattern)); + }; + return { + setPatterns: setPatterns, + getPatterns: getPatterns + }; + }; + var Api = { get: get$1 }; + + var Global = typeof domGlobals.window !== 'undefined' ? domGlobals.window : Function('return this;')(); + + var error$1 = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var console = Global.console; + if (console) { + if (console.error) { + console.error.apply(console, args); + } else { + console.log.apply(console, args); + } + } + }; + var defaultPatterns = [ + { + start: '*', + end: '*', + format: 'italic' + }, + { + start: '**', + end: '**', + format: 'bold' + }, + { + start: '#', + format: 'h1' + }, + { + start: '##', + format: 'h2' + }, + { + start: '###', + format: 'h3' + }, + { + start: '####', + format: 'h4' + }, + { + start: '#####', + format: 'h5' + }, + { + start: '######', + format: 'h6' + }, + { + start: '1. ', + cmd: 'InsertOrderedList' + }, + { + start: '* ', + cmd: 'InsertUnorderedList' + }, + { + start: '- ', + cmd: 'InsertUnorderedList' + } + ]; + var getPatternSet = function (editorSettings) { + var patterns = get(editorSettings, 'textpattern_patterns').getOr(defaultPatterns); + if (!isArray(patterns)) { + error$1('The setting textpattern_patterns should be an array'); + return { + inlinePatterns: [], + blockPatterns: [] + }; + } + var normalized = partition(map(patterns, normalizePattern)); + each(normalized.errors, function (err) { + return error$1(err.message, err.pattern); + }); + return createPatternSet(normalized.values); + }; + var getForcedRootBlock = function (editor) { + var block = editor.getParam('forced_root_block', 'p'); + if (block === false) { + return ''; + } else if (block === true) { + return 'p'; + } else { + return block; + } + }; + + var global$1 = tinymce.util.Tools.resolve('tinymce.util.Delay'); + + var global$2 = tinymce.util.Tools.resolve('tinymce.util.VK'); + + var zeroWidth = function () { + return '\uFEFF'; + }; + + var global$3 = tinymce.util.Tools.resolve('tinymce.util.Tools'); + + var global$4 = tinymce.util.Tools.resolve('tinymce.dom.TreeWalker'); + + var isText = function (node) { + return node.nodeType === domGlobals.Node.TEXT_NODE; + }; + var cleanEmptyNodes = function (dom, node, isRoot) { + if (node && dom.isEmpty(node) && !isRoot(node)) { + var parent = node.parentNode; + dom.remove(node); + cleanEmptyNodes(dom, parent, isRoot); + } + }; + var deleteRng = function (dom, rng, isRoot, clean) { + if (clean === void 0) { + clean = true; + } + var startParent = rng.startContainer.parentNode; + var endParent = rng.endContainer.parentNode; + rng.deleteContents(); + if (clean && !isRoot(rng.startContainer)) { + if (isText(rng.startContainer) && rng.startContainer.data.length === 0) { + dom.remove(rng.startContainer); + } + if (isText(rng.endContainer) && rng.endContainer.data.length === 0) { + dom.remove(rng.endContainer); + } + cleanEmptyNodes(dom, startParent, isRoot); + if (startParent !== endParent) { + cleanEmptyNodes(dom, endParent, isRoot); + } + } + }; + var isBlockFormatName = function (name, formatter) { + var formatSet = formatter.get(name); + return isArray(formatSet) && head(formatSet).exists(function (format) { + return has(format, 'block'); + }); + }; + var isReplacementPattern = function (pattern) { + return pattern.start.length === 0; + }; + var getParentBlock = function (editor, rng) { + var parentBlockOpt = Option.from(editor.dom.getParent(rng.startContainer, editor.dom.isBlock)); + if (getForcedRootBlock(editor) === '') { + return parentBlockOpt.orThunk(function () { + return Option.some(editor.getBody()); + }); + } else { + return parentBlockOpt; + } + }; + + var point = function (element, offset) { + return { + element: element, + offset: offset + }; + }; + + var TextWalker = function (startNode, rootNode) { + var walker = new global$4(startNode, rootNode); + var walk = function (direction) { + var next = walker[direction](); + while (next && next.nodeType !== domGlobals.Node.TEXT_NODE) { + next = walker[direction](); + } + return next && next.nodeType === domGlobals.Node.TEXT_NODE ? Option.some(next) : Option.none(); + }; + return { + next: function () { + return walk('next'); + }, + prev: function () { + return walk('prev'); + }, + prev2: function () { + return walk('prev2'); + } + }; + }; + + var textBefore = function (node, offset, rootNode) { + if (isText(node) && offset >= 0) { + return Option.some(point(node, offset)); + } else { + var textWalker = TextWalker(node, rootNode); + return textWalker.prev().map(function (prev) { + return point(prev, prev.data.length); + }); + } + }; + var scanLeft = function (node, offset, rootNode) { + if (!isText(node)) { + return Option.none(); + } + var text = node.textContent; + if (offset >= 0 && offset <= text.length) { + return Option.some(point(node, offset)); + } else { + var textWalker = TextWalker(node, rootNode); + return textWalker.prev().bind(function (prev) { + var prevText = prev.textContent; + return scanLeft(prev, offset + prevText.length, rootNode); + }); + } + }; + var scanRight = function (node, offset, rootNode) { + if (!isText(node)) { + return Option.none(); + } + var text = node.textContent; + if (offset <= text.length) { + return Option.some(point(node, offset)); + } else { + var textWalker = TextWalker(node, rootNode); + return textWalker.next().bind(function (next) { + return scanRight(next, offset - text.length, rootNode); + }); + } + }; + var isBoundary = function (dom, node) { + return dom.isBlock(node) || contains([ + 'BR', + 'IMG', + 'HR', + 'INPUT' + ], node.nodeName) || dom.getContentEditable(node) === 'false'; + }; + var outcome = Adt.generate([ + { aborted: [] }, + { edge: ['element'] }, + { success: ['info'] } + ]); + var phase = Adt.generate([ + { abort: [] }, + { kontinue: [] }, + { finish: ['info'] } + ]); + var repeat = function (dom, node, offset, process, walker, recent) { + var terminate = function () { + return recent.fold(outcome.aborted, outcome.edge); + }; + var recurse = function () { + var next = walker(); + if (next) { + return repeat(dom, next, Option.none(), process, walker, Option.some(node)); + } else { + return terminate(); + } + }; + if (isBoundary(dom, node)) { + return terminate(); + } else if (!isText(node)) { + return recurse(); + } else { + var text = node.textContent; + return process(phase, node, text, offset).fold(outcome.aborted, function () { + return recurse(); + }, outcome.success); + } + }; + var repeatLeft = function (dom, node, offset, process, rootNode) { + var walker = new global$4(node, rootNode); + return repeat(dom, node, Option.some(offset), process, walker.prev, Option.none()); + }; + + var generatePath = function (root, node, offset) { + if (isText(node) && (offset < 0 || offset > node.data.length)) { + return []; + } + var p = [offset]; + var current = node; + while (current !== root && current.parentNode) { + var parent = current.parentNode; + for (var i = 0; i < parent.childNodes.length; i++) { + if (parent.childNodes[i] === current) { + p.push(i); + break; + } + } + current = parent; + } + return current === root ? p.reverse() : []; + }; + var generatePathRange = function (root, startNode, startOffset, endNode, endOffset) { + var start = generatePath(root, startNode, startOffset); + var end = generatePath(root, endNode, endOffset); + return { + start: start, + end: end + }; + }; + var resolvePath = function (root, path) { + var nodePath = path.slice(); + var offset = nodePath.pop(); + return foldl(nodePath, function (optNode, index) { + return optNode.bind(function (node) { + return Option.from(node.childNodes[index]); + }); + }, Option.some(root)).bind(function (node) { + if (isText(node) && offset >= 0 && offset <= node.data.length) { + return Option.some({ + node: node, + offset: offset + }); + } else { + return Option.some({ + node: node, + offset: offset + }); + } + }); + }; + var resolvePathRange = function (root, range) { + return resolvePath(root, range.start).bind(function (_a) { + var startNode = _a.node, startOffset = _a.offset; + return resolvePath(root, range.end).map(function (_a) { + var endNode = _a.node, endOffset = _a.offset; + var rng = domGlobals.document.createRange(); + rng.setStart(startNode, startOffset); + rng.setEnd(endNode, endOffset); + return rng; + }); + }); + }; + var generatePathRangeFromRange = function (root, range) { + return generatePathRange(root, range.startContainer, range.startOffset, range.endContainer, range.endOffset); + }; + + var stripPattern = function (dom, block, pattern) { + var firstTextNode = TextWalker(block, block).next(); + firstTextNode.each(function (node) { + scanRight(node, pattern.start.length, block).each(function (end) { + var rng = dom.createRng(); + rng.setStart(node, 0); + rng.setEnd(end.element, end.offset); + deleteRng(dom, rng, function (e) { + return e === block; + }); + }); + }); + }; + var applyPattern = function (editor, match) { + var dom = editor.dom; + var pattern = match.pattern; + var rng = resolvePathRange(dom.getRoot(), match.range).getOrDie('Unable to resolve path range'); + getParentBlock(editor, rng).each(function (block) { + if (pattern.type === 'block-format') { + if (isBlockFormatName(pattern.format, editor.formatter)) { + editor.undoManager.transact(function () { + stripPattern(editor.dom, block, pattern); + editor.formatter.apply(pattern.format); + }); + } + } else if (pattern.type === 'block-command') { + editor.undoManager.transact(function () { + stripPattern(editor.dom, block, pattern); + editor.execCommand(pattern.cmd, false, pattern.value); + }); + } + }); + return true; + }; + var findPattern = function (patterns, text) { + var nuText = text.replace('\xA0', ' '); + return find(patterns, function (pattern) { + if (text.indexOf(pattern.start) !== 0 && nuText.indexOf(pattern.start) !== 0) { + return false; + } + return true; + }); + }; + var findPatterns = function (editor, patterns) { + var dom = editor.dom; + var rng = editor.selection.getRng(); + return getParentBlock(editor, rng).filter(function (block) { + var forcedRootBlock = getForcedRootBlock(editor); + var matchesForcedRootBlock = forcedRootBlock === '' && dom.is(block, 'body') || dom.is(block, forcedRootBlock); + return block !== null && matchesForcedRootBlock; + }).bind(function (block) { + var blockText = block.textContent; + var matchedPattern = findPattern(patterns, blockText); + return matchedPattern.map(function (pattern) { + if (global$3.trim(blockText).length === pattern.start.length) { + return []; + } + return [{ + pattern: pattern, + range: generatePathRange(dom.getRoot(), block, 0, block, 0) + }]; + }); + }).getOr([]); + }; + var applyMatches = function (editor, matches) { + if (matches.length === 0) { + return; + } + var bookmark = editor.selection.getBookmark(); + each(matches, function (match) { + return applyPattern(editor, match); + }); + editor.selection.moveToBookmark(bookmark); + }; + + var unique = 0; + var generate$1 = function (prefix) { + var date = new Date(); + var time = date.getTime(); + var random = Math.floor(Math.random() * 1000000000); + unique++; + return prefix + '_' + random + unique + String(time); + }; + + var checkRange = function (str, substr, start) { + if (substr === '') { + return true; + } + if (str.length < substr.length) { + return false; + } + var x = str.substr(start, start + substr.length); + return x === substr; + }; + var endsWith = function (str, suffix) { + return checkRange(str, suffix, str.length - suffix.length); + }; + + var newMarker = function (dom, id) { + return dom.create('span', { + 'data-mce-type': 'bookmark', + 'id': id + }); + }; + var rangeFromMarker = function (dom, marker) { + var rng = dom.createRng(); + rng.setStartAfter(marker.start); + rng.setEndBefore(marker.end); + return rng; + }; + var createMarker = function (dom, markerPrefix, pathRange) { + var rng = resolvePathRange(dom.getRoot(), pathRange).getOrDie('Unable to resolve path range'); + var startNode = rng.startContainer; + var endNode = rng.endContainer; + var textEnd = rng.endOffset === 0 ? endNode : endNode.splitText(rng.endOffset); + var textStart = rng.startOffset === 0 ? startNode : startNode.splitText(rng.startOffset); + return { + prefix: markerPrefix, + end: textEnd.parentNode.insertBefore(newMarker(dom, markerPrefix + '-end'), textEnd), + start: textStart.parentNode.insertBefore(newMarker(dom, markerPrefix + '-start'), textStart) + }; + }; + var removeMarker = function (dom, marker, isRoot) { + cleanEmptyNodes(dom, dom.get(marker.prefix + '-end'), isRoot); + cleanEmptyNodes(dom, dom.get(marker.prefix + '-start'), isRoot); + }; + + var nodeMatchesPattern = function (dom, block, content) { + return function (phase, element, text, optOffset) { + if (element === block) { + return phase.abort(); + } + var searchText = text.substring(0, optOffset.getOr(text.length)); + var startEndIndex = searchText.lastIndexOf(content.charAt(content.length - 1)); + var startIndex = searchText.lastIndexOf(content); + if (startIndex !== -1) { + var rng = dom.createRng(); + rng.setStart(element, startIndex); + rng.setEnd(element, startIndex + content.length); + return phase.finish(rng); + } else if (startEndIndex !== -1) { + return scanLeft(element, startEndIndex + 1 - content.length, block).fold(function () { + return phase.kontinue(); + }, function (spot) { + var rng = dom.createRng(); + rng.setStart(spot.element, spot.offset); + rng.setEnd(element, startEndIndex + 1); + if (rng.toString() === content) { + return phase.finish(rng); + } else { + return phase.kontinue(); + } + }); + } else { + return phase.kontinue(); + } + }; + }; + var findPatternStart = function (dom, pattern, node, offset, block, requireGap) { + if (requireGap === void 0) { + requireGap = false; + } + if (pattern.start.length === 0 && !requireGap) { + var rng = dom.createRng(); + rng.setStart(node, offset); + rng.setEnd(node, offset); + return Option.some(rng); + } + return textBefore(node, offset, block).bind(function (spot) { + var outcome = repeatLeft(dom, spot.element, spot.offset, nodeMatchesPattern(dom, block, pattern.start), block); + var start = outcome.fold(Option.none, Option.none, Option.some); + return start.bind(function (startRange) { + if (requireGap) { + if (startRange.endContainer === spot.element && startRange.endOffset === spot.offset) { + return Option.none(); + } else if (spot.offset === 0 && startRange.endContainer.textContent.length === startRange.endOffset) { + return Option.none(); + } + } + return Option.some(startRange); + }); + }); + }; + var findPattern$1 = function (editor, block, details) { + var dom = editor.dom; + var root = dom.getRoot(); + var pattern = details.pattern; + var endNode = details.position.element; + var endOffset = details.position.offset; + return scanLeft(endNode, endOffset - details.pattern.end.length, block).bind(function (spot) { + var endPathRng = generatePathRange(root, spot.element, spot.offset, endNode, endOffset); + if (isReplacementPattern(pattern)) { + return Option.some({ + matches: [{ + pattern: pattern, + startRng: endPathRng, + endRng: endPathRng + }], + position: spot + }); + } else { + var resultsOpt = findPatternsRec(editor, details.remainingPatterns, spot.element, spot.offset, block); + var results_1 = resultsOpt.getOr({ + matches: [], + position: spot + }); + var pos = results_1.position; + var start = findPatternStart(dom, pattern, pos.element, pos.offset, block, resultsOpt.isNone()); + return start.map(function (startRng) { + var startPathRng = generatePathRangeFromRange(root, startRng); + return { + matches: results_1.matches.concat([{ + pattern: pattern, + startRng: startPathRng, + endRng: endPathRng + }]), + position: point(startRng.startContainer, startRng.startOffset) + }; + }); + } + }); + }; + var findPatternsRec = function (editor, patterns, node, offset, block) { + var dom = editor.dom; + return textBefore(node, offset, dom.getRoot()).bind(function (endSpot) { + var rng = dom.createRng(); + rng.setStart(block, 0); + rng.setEnd(node, offset); + var text = rng.toString(); + for (var i = 0; i < patterns.length; i++) { + var pattern = patterns[i]; + if (!endsWith(text, pattern.end)) { + continue; + } + var patternsWithoutCurrent = patterns.slice(); + patternsWithoutCurrent.splice(i, 1); + var result = findPattern$1(editor, block, { + pattern: pattern, + remainingPatterns: patternsWithoutCurrent, + position: endSpot + }); + if (result.isSome()) { + return result; + } + } + return Option.none(); + }); + }; + var applyPattern$1 = function (editor, pattern, patternRange) { + editor.selection.setRng(patternRange); + if (pattern.type === 'inline-format') { + each(pattern.format, function (format) { + editor.formatter.apply(format); + }); + } else { + editor.execCommand(pattern.cmd, false, pattern.value); + } + }; + var applyReplacementPattern = function (editor, pattern, marker, isRoot) { + var markerRange = rangeFromMarker(editor.dom, marker); + deleteRng(editor.dom, markerRange, isRoot); + applyPattern$1(editor, pattern, markerRange); + }; + var applyPatternWithContent = function (editor, pattern, startMarker, endMarker, isRoot) { + var dom = editor.dom; + var markerEndRange = rangeFromMarker(dom, endMarker); + var markerStartRange = rangeFromMarker(dom, startMarker); + deleteRng(dom, markerStartRange, isRoot); + deleteRng(dom, markerEndRange, isRoot); + var patternMarker = { + prefix: startMarker.prefix, + start: startMarker.end, + end: endMarker.start + }; + var patternRange = rangeFromMarker(dom, patternMarker); + applyPattern$1(editor, pattern, patternRange); + }; + var addMarkers = function (dom, matches) { + var markerPrefix = generate$1('mce_textpattern'); + var matchesWithEnds = foldr(matches, function (acc, match) { + var endMarker = createMarker(dom, markerPrefix + ('_end' + acc.length), match.endRng); + return acc.concat([__assign(__assign({}, match), { endMarker: endMarker })]); + }, []); + return foldr(matchesWithEnds, function (acc, match) { + var idx = matchesWithEnds.length - acc.length - 1; + var startMarker = isReplacementPattern(match.pattern) ? match.endMarker : createMarker(dom, markerPrefix + ('_start' + idx), match.startRng); + return acc.concat([__assign(__assign({}, match), { startMarker: startMarker })]); + }, []); + }; + var findPatterns$1 = function (editor, patterns, space) { + var rng = editor.selection.getRng(); + if (rng.collapsed === false) { + return []; + } + return getParentBlock(editor, rng).bind(function (block) { + var offset = rng.startOffset - (space ? 1 : 0); + return findPatternsRec(editor, patterns, rng.startContainer, offset, block); + }).fold(function () { + return []; + }, function (result) { + return result.matches; + }); + }; + var applyMatches$1 = function (editor, matches) { + if (matches.length === 0) { + return; + } + var dom = editor.dom; + var bookmark = editor.selection.getBookmark(); + var matchesWithMarkers = addMarkers(dom, matches); + each(matchesWithMarkers, function (match) { + var block = dom.getParent(match.startMarker.start, dom.isBlock); + var isRoot = function (node) { + return node === block; + }; + if (isReplacementPattern(match.pattern)) { + applyReplacementPattern(editor, match.pattern, match.endMarker, isRoot); + } else { + applyPatternWithContent(editor, match.pattern, match.startMarker, match.endMarker, isRoot); + } + removeMarker(dom, match.endMarker, isRoot); + removeMarker(dom, match.startMarker, isRoot); + }); + editor.selection.moveToBookmark(bookmark); + }; + + var handleEnter = function (editor, patternSet) { + if (!editor.selection.isCollapsed()) { + return false; + } + var inlineMatches = findPatterns$1(editor, patternSet.inlinePatterns, false); + var blockMatches = findPatterns(editor, patternSet.blockPatterns); + if (blockMatches.length > 0 || inlineMatches.length > 0) { + editor.undoManager.add(); + editor.undoManager.extra(function () { + editor.execCommand('mceInsertNewLine'); + }, function () { + editor.insertContent(zeroWidth()); + applyMatches$1(editor, inlineMatches); + applyMatches(editor, blockMatches); + var range = editor.selection.getRng(); + var spot = textBefore(range.startContainer, range.startOffset, editor.dom.getRoot()); + editor.execCommand('mceInsertNewLine'); + spot.each(function (s) { + if (s.element.data.charAt(s.offset - 1) === zeroWidth()) { + s.element.deleteData(s.offset - 1, 1); + cleanEmptyNodes(editor.dom, s.element.parentNode, function (e) { + return e === editor.dom.getRoot(); + }); + } + }); + }); + return true; + } + return false; + }; + var handleInlineKey = function (editor, patternSet) { + var inlineMatches = findPatterns$1(editor, patternSet.inlinePatterns, true); + if (inlineMatches.length > 0) { + editor.undoManager.transact(function () { + applyMatches$1(editor, inlineMatches); + }); + } + }; + var checkKeyEvent = function (codes, event, predicate) { + for (var i = 0; i < codes.length; i++) { + if (predicate(codes[i], event)) { + return true; + } + } + }; + var checkKeyCode = function (codes, event) { + return checkKeyEvent(codes, event, function (code, event) { + return code === event.keyCode && global$2.modifierPressed(event) === false; + }); + }; + var checkCharCode = function (chars, event) { + return checkKeyEvent(chars, event, function (chr, event) { + return chr.charCodeAt(0) === event.charCode; + }); + }; + var KeyHandler = { + handleEnter: handleEnter, + handleInlineKey: handleInlineKey, + checkCharCode: checkCharCode, + checkKeyCode: checkKeyCode + }; + + var setup = function (editor, patternsState) { + var charCodes = [ + ',', + '.', + ';', + ':', + '!', + '?' + ]; + var keyCodes = [32]; + editor.on('keydown', function (e) { + if (e.keyCode === 13 && !global$2.modifierPressed(e)) { + if (KeyHandler.handleEnter(editor, patternsState.get())) { + e.preventDefault(); + } + } + }, true); + editor.on('keyup', function (e) { + if (KeyHandler.checkKeyCode(keyCodes, e)) { + KeyHandler.handleInlineKey(editor, patternsState.get()); + } + }); + editor.on('keypress', function (e) { + if (KeyHandler.checkCharCode(charCodes, e)) { + global$1.setEditorTimeout(editor, function () { + KeyHandler.handleInlineKey(editor, patternsState.get()); + }); + } + }); + }; + var Keyboard = { setup: setup }; + + function Plugin () { + global.add('textpattern', function (editor) { + var patternsState = Cell(getPatternSet(editor.settings)); + Keyboard.setup(editor, patternsState); + return Api.get(patternsState); + }); + } + + Plugin(); + +}(window)); diff --git a/lib/tinymce/js/tinymce/plugins/textpattern/plugin.min.js b/lib/tinymce/js/tinymce/plugins/textpattern/plugin.min.js new file mode 100644 index 00000000..256cb544 --- /dev/null +++ b/lib/tinymce/js/tinymce/plugins/textpattern/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.1.6 (2020-01-28) + */ +!function(f){"use strict";var r=function(t){function n(){return e}var e=t;return{get:n,set:function(t){e=t},clone:function(){return r(n())}}},t=tinymce.util.Tools.resolve("tinymce.PluginManager"),u=function(){return(u=Object.assign||function(t){for(var n,e=1,r=arguments.length;en.start.length?-1:1})}function T(o){function a(t){return yt.error({message:t,pattern:o})}function t(t,n,e){if(o.format===undefined)return o.cmd!==undefined?it(o.cmd)?yt.value(e(o.cmd,o.value)):a(t+" pattern has non-string `cmd` parameter"):a(t+" pattern is missing both `format` and `cmd` parameters");var r=void 0;if(ft(o.format)){if(!O(o.format,it))return a(t+" pattern has non-string items in the `format` array");r=o.format}else{if(!it(o.format))return a(t+" pattern has non-string `format` parameter");r=[o.format]}return yt.value(n(r))}if(!ut(o))return a("Raw pattern is not an object");if(!it(o.start))return a("Raw pattern is missing `start` parameter");if(o.end===undefined)return o.replacement!==undefined?it(o.replacement)?0===o.start.length?a("Replacement pattern has empty `start` parameter"):yt.value({type:"inline-command",start:"",end:o.start,cmd:"mceInsertContent",value:o.replacement}):a("Replacement pattern has non-string `replacement` parameter"):0===o.start.length?a("Block pattern has empty `start` parameter"):t("Block",function(t){return{type:"block-format",start:o.start,format:t[0]}},function(t,n){return{type:"block-command",start:o.start,cmd:t,value:n}});if(!it(o.end))return a("Inline pattern has non-string `end` parameter");if(0===o.start.length&&0===o.end.length)return a("Inline pattern has empty `start` and `end` parameters");var e=o.start,r=o.end;return 0===r.length&&(r=e,e=""),t("Inline",function(t){return{type:"inline-format",start:e,end:r,format:t}},function(t,n){return{type:"inline-command",start:e,end:r,cmd:t,value:n}})}function R(t){return"block-command"===t.type?{start:t.start,cmd:t.cmd,value:t.value}:"block-format"===t.type?{start:t.start,format:t.format}:"inline-command"===t.type?"mceInsertContent"===t.cmd&&""===t.start?{start:t.end,replacement:t.value}:{start:t.start,end:t.end,cmd:t.cmd,value:t.value}:"inline-format"===t.type?{start:t.start,end:t.end,format:1===t.format.length?t.format[0]:t.format}:void 0}function N(t){return{inlinePatterns:b(t,x),blockPatterns:E(b(t,C))}}function P(){for(var t=[],n=0;n n.data.length))return[];for(var r=[e],o=n;o!==t&&o.parentNode;){for(var a=o.parentNode,i=0;i = 1 && depth <= 9 ? depth : 3; + }; + var Settings = { + getTocClass: getTocClass, + getTocHeader: getTocHeader, + getTocDepth: getTocDepth + }; + + var create = function (prefix) { + var counter = 0; + return function () { + var guid = new Date().getTime().toString(32); + return prefix + guid + (counter++).toString(32); + }; + }; + var Guid = { create: create }; + + var tocId = Guid.create('mcetoc_'); + var generateSelector = function generateSelector(depth) { + var i; + var selector = []; + for (i = 1; i <= depth; i++) { + selector.push('h' + i); + } + return selector.join(','); + }; + var hasHeaders = function (editor) { + return readHeaders(editor).length > 0; + }; + var readHeaders = function (editor) { + var tocClass = Settings.getTocClass(editor); + var headerTag = Settings.getTocHeader(editor); + var selector = generateSelector(Settings.getTocDepth(editor)); + var headers = editor.$(selector); + if (headers.length && /^h[1-9]$/i.test(headerTag)) { + headers = headers.filter(function (i, el) { + return !editor.dom.hasClass(el.parentNode, tocClass); + }); + } + return global$3.map(headers, function (h) { + return { + id: h.id ? h.id : tocId(), + level: parseInt(h.nodeName.replace(/^H/i, ''), 10), + title: editor.$.text(h), + element: h + }; + }); + }; + var getMinLevel = function (headers) { + var i, minLevel = 9; + for (i = 0; i < headers.length; i++) { + if (headers[i].level < minLevel) { + minLevel = headers[i].level; + } + if (minLevel === 1) { + return minLevel; + } + } + return minLevel; + }; + var generateTitle = function (tag, title) { + var openTag = '<' + tag + ' contenteditable="true">'; + var closeTag = '' + tag + '>'; + return openTag + global$1.DOM.encode(title) + closeTag; + }; + var generateTocHtml = function (editor) { + var html = generateTocContentHtml(editor); + return ' ' + html + ''; + }; + var generateTocContentHtml = function (editor) { + var html = ''; + var headers = readHeaders(editor); + var prevLevel = getMinLevel(headers) - 1; + var i, ii, h, nextLevel; + if (!headers.length) { + return ''; + } + html += generateTitle(Settings.getTocHeader(editor), global$2.translate('Table of Contents')); + for (i = 0; i < headers.length; i++) { + h = headers[i]; + h.element.id = h.id; + nextLevel = headers[i + 1] && headers[i + 1].level; + if (prevLevel === h.level) { + html += ''; + } else { + for (ii = prevLevel; ii < h.level; ii++) { + html += ' '; + } + } else { + for (ii = h.level; ii > nextLevel; ii--) { + html += '
- '; + } + } + html += '' + h.title + ''; + if (nextLevel === h.level || !nextLevel) { + html += '
'; + if (!nextLevel) { + html += ''; + } + } + prevLevel = h.level; + } + return html; + }; + var isEmptyOrOffscren = function (editor, nodes) { + return !nodes.length || editor.dom.getParents(nodes[0], '.mce-offscreen-selection').length > 0; + }; + var insertToc = function (editor) { + var tocClass = Settings.getTocClass(editor); + var $tocElm = editor.$('.' + tocClass); + if (isEmptyOrOffscren(editor, $tocElm)) { + editor.insertContent(generateTocHtml(editor)); + } else { + updateToc(editor); + } + }; + var updateToc = function (editor) { + var tocClass = Settings.getTocClass(editor); + var $tocElm = editor.$('.' + tocClass); + if ($tocElm.length) { + editor.undoManager.transact(function () { + $tocElm.html(generateTocContentHtml(editor)); + }); + } + }; + var Toc = { + hasHeaders: hasHeaders, + insertToc: insertToc, + updateToc: updateToc + }; + + var register = function (editor) { + editor.addCommand('mceInsertToc', function () { + Toc.insertToc(editor); + }); + editor.addCommand('mceUpdateToc', function () { + Toc.updateToc(editor); + }); + }; + var Commands = { register: register }; + + var setup = function (editor) { + var $ = editor.$, tocClass = Settings.getTocClass(editor); + editor.on('PreProcess', function (e) { + var $tocElm = $('.' + tocClass, e.node); + if ($tocElm.length) { + $tocElm.removeAttr('contentEditable'); + $tocElm.find('[contenteditable]').removeAttr('contentEditable'); + } + }); + editor.on('SetContent', function () { + var $tocElm = $('.' + tocClass); + if ($tocElm.length) { + $tocElm.attr('contentEditable', false); + $tocElm.children(':first-child').attr('contentEditable', true); + } + }); + }; + var FilterContent = { setup: setup }; + + var toggleState = function (editor) { + return function (api) { + var toggleDisabledState = function () { + return api.setDisabled(editor.readonly || !Toc.hasHeaders(editor)); + }; + toggleDisabledState(); + editor.on('LoadContent SetContent change', toggleDisabledState); + return function () { + return editor.on('LoadContent SetContent change', toggleDisabledState); + }; + }; + }; + var isToc = function (editor) { + return function (elm) { + return elm && editor.dom.is(elm, '.' + Settings.getTocClass(editor)) && editor.getBody().contains(elm); + }; + }; + var register$1 = function (editor) { + editor.ui.registry.addButton('toc', { + icon: 'toc', + tooltip: 'Table of contents', + onAction: function () { + return editor.execCommand('mceInsertToc'); + }, + onSetup: toggleState(editor) + }); + editor.ui.registry.addButton('tocupdate', { + icon: 'reload', + tooltip: 'Update', + onAction: function () { + return editor.execCommand('mceUpdateToc'); + } + }); + editor.ui.registry.addMenuItem('toc', { + icon: 'toc', + text: 'Table of contents', + onAction: function () { + return editor.execCommand('mceInsertToc'); + }, + onSetup: toggleState(editor) + }); + editor.ui.registry.addContextToolbar('toc', { + items: 'tocupdate', + predicate: isToc(editor), + scope: 'node', + position: 'node' + }); + }; + var Buttons = { register: register$1 }; + + function Plugin () { + global.add('toc', function (editor) { + Commands.register(editor); + Buttons.register(editor); + FilterContent.setup(editor); + }); + } + + Plugin(); + +}()); diff --git a/lib/tinymce/js/tinymce/plugins/toc/plugin.min.js b/lib/tinymce/js/tinymce/plugins/toc/plugin.min.js new file mode 100644 index 00000000..02548c4b --- /dev/null +++ b/lib/tinymce/js/tinymce/plugins/toc/plugin.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.1.6 (2020-01-28) + */ +!function(){"use strict";function e(n){return function(t){function e(){return t.setDisabled(n.readonly||!v.hasHeaders(n))}return e(),n.on("LoadContent SetContent change",e),function(){return n.on("LoadContent SetContent change",e)}}}var t=tinymce.util.Tools.resolve("tinymce.PluginManager"),u=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),l=tinymce.util.Tools.resolve("tinymce.util.I18n"),i=tinymce.util.Tools.resolve("tinymce.util.Tools"),c=function(t){return t.getParam("toc_class","mce-toc")},d=function(t){var e=t.getParam("toc_header","h2");return/^h[1-6]$/.test(e)?e:"h2"},a=function(t){var e=parseInt(t.getParam("toc_depth","3"),10);return 1<=e&&e<=9?e:3},s=function(e){var n=0;return function(){var t=(new Date).getTime().toString(32);return e+t+(n++).toString(32)}}("mcetoc_"),f=function f(t){var e,n=[];for(e=1;e<=t;e++)n.push("h"+e);return n.join(",")},m=function(n){var o=c(n),t=d(n),e=f(a(n)),r=n.$(e);return r.length&&/^h[1-9]$/i.test(t)&&(r=r.filter(function(t,e){return!n.dom.hasClass(e.parentNode,o)})),i.map(r,function(t){return{id:t.id?t.id:s(),level:parseInt(t.nodeName.replace(/^H/i,""),10),title:n.$.text(t),element:t}})},o=function(t){var e,n,o,r,i="",c=m(t),a=function(t){var e,n=9;for(e=0;e ";return"<"+t+' contenteditable="true">'+u.DOM.encode(e)+n}(d(t),l.translate("Table of Contents")),e=0;e ";else for(n=a;n ";if(i+=''+o.title+"",r!==o.level&&r)for(n=o.level;r ";else i+=" ",r||(i+="");a=o.level}return i},r=function(t){var e=c(t),n=t.$("."+e);n.length&&t.undoManager.transact(function(){n.html(o(t))})},v={hasHeaders:function(t){return 0'+e+"
+
+
+
+