From 61517ce39da8d64b37328ee98d2d53a408351dd4 Mon Sep 17 00:00:00 2001 From: thomascube Date: Wed, 20 Apr 2011 09:57:35 +0000 Subject: Updated to TinyMCE 3.4.2 which is now compatible with IE9 --- program/js/tiny_mce/tiny_mce_src.js | 230 +++++++++++++++++++++++------------- 1 file changed, 145 insertions(+), 85 deletions(-) (limited to 'program/js/tiny_mce/tiny_mce_src.js') diff --git a/program/js/tiny_mce/tiny_mce_src.js b/program/js/tiny_mce/tiny_mce_src.js index b28a65a07..c1d47fcb7 100644 --- a/program/js/tiny_mce/tiny_mce_src.js +++ b/program/js/tiny_mce/tiny_mce_src.js @@ -5,9 +5,9 @@ var tinymce = { majorVersion : '3', - minorVersion : '4.1', + minorVersion : '4.2', - releaseDate : '2011-03-24', + releaseDate : '2011-04-07', _init : function() { var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v; @@ -1407,7 +1407,7 @@ tinymce.html.Styles = function(settings, schema) { name = styleList[i]; value = styles[name]; - if (value !== undef) + if (value !== undef && value.length > 0) css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';'; } } @@ -1423,7 +1423,7 @@ tinymce.html.Styles = function(settings, schema) { for (name in styles) { value = styles[name]; - if (value !== undef) + if (value !== undef && value.length > 0) css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';'; } } @@ -2483,11 +2483,12 @@ tinymce.html.Styles = function(settings, schema) { }, isEmpty : function(elements) { - var self = this, node = self.firstChild, i; + 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; @@ -2495,10 +2496,11 @@ tinymce.html.Styles = function(settings, schema) { if (elements[node.name]) return false; - // Keep elements with data attributes + // Keep elements with data attributes or name attribute like i = node.attributes.length; while (i--) { - if (node.attributes[i].name.indexOf('data-') === 0) + name = node.attributes[i].name; + if (name === "name" || name.indexOf('data-') === 0) return false; } } @@ -2540,6 +2542,7 @@ tinymce.html.Styles = function(settings, schema) { var self = this, nodeFilters = {}, attributeFilters = [], matchedNodes = {}, matchedAttributes = {}; settings = settings || {}; + settings.validate = "validate" in settings ? settings.validate : true; settings.root_name = settings.root_name || 'body'; self.schema = schema = schema || new tinymce.html.Schema(); @@ -2690,16 +2693,17 @@ tinymce.html.Styles = function(settings, schema) { }; self.parse = function(html, args) { - var parser, rootNode, node, nodes, i, l, fi, fl, list, name, + var parser, rootNode, node, nodes, i, l, fi, fl, list, name, validate, blockElements, startWhiteSpaceRegExp, invalidChildren = [], endWhiteSpaceRegExp, allWhiteSpaceRegExp, whiteSpaceElements, children, nonEmptyElements; args = args || {}; matchedNodes = {}; matchedAttributes = {}; - blockElements = tinymce.extend(tinymce.makeMap('script,style,head,title,meta,param'), schema.getBlockElements()); + blockElements = tinymce.extend(tinymce.makeMap('script,style,head,html,body,title,meta,param'), schema.getBlockElements()); nonEmptyElements = schema.getNonEmptyElements(); children = schema.children; + validate = settings.validate; whiteSpaceElements = schema.getWhiteSpaceElements(); startWhiteSpaceRegExp = /^[ \t\r\n]+/; @@ -2721,9 +2725,26 @@ tinymce.html.Styles = function(settings, schema) { 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; + } + } + }; + parser = new tinymce.html.SaxParser({ - validate : settings.validate, - fix_self_closing : false, // Let the DOM parser handle
  • in
  • or

    in

    for better results + validate : validate, + fix_self_closing : !validate, // Let the DOM parser handle

  • in
  • or

    in

    for better results cdata: function(text) { node.append(createNode('#cdata', 4)).value = text; @@ -2754,16 +2775,21 @@ tinymce.html.Styles = function(settings, schema) { pi: function(name, text) { node.append(createNode(name, 7)).value = text; + removeWhitespaceBefore(node); }, doctype: function(text) { - node.append(createNode('#doctype', 10)).value = text; + var newNode; + + newNode = node.append(createNode('#doctype', 10)); + newNode.value = text; + removeWhitespaceBefore(node); }, start: function(name, attrs, empty) { var newNode, attrFiltersLen, elementRule, textNode, attrName, text, sibling, parent; - elementRule = schema.getElementRule(name); + elementRule = validate ? schema.getElementRule(name) : {}; if (elementRule) { newNode = createNode(elementRule.outputName || name, 1); newNode.attributes = attrs; @@ -2792,20 +2818,8 @@ tinymce.html.Styles = function(settings, schema) { } // Trim whitespace before block - if (blockElements[name]) { - for (textNode = newNode.prev; textNode && textNode.type === 3; ) { - text = textNode.value.replace(endWhiteSpaceRegExp, ''); - - if (text.length > 0) { - textNode.value = text; - textNode = textNode.prev; - } else { - sibling = textNode.prev; - textNode.remove(); - textNode = sibling; - } - } - } + if (blockElements[name]) + removeWhitespaceBefore(newNode); // Change current node if the element wasn't empty i.e not
    or if (!empty) @@ -2816,7 +2830,7 @@ tinymce.html.Styles = function(settings, schema) { end: function(name) { var textNode, elementRule, text, sibling, tempNode; - elementRule = schema.getElementRule(name); + elementRule = validate ? schema.getElementRule(name) : {}; if (elementRule) { if (blockElements[name]) { if (!whiteSpaceElements[node.name]) { @@ -2887,7 +2901,8 @@ tinymce.html.Styles = function(settings, schema) { parser.parse(html); - fixInvalidChildren(invalidChildren); + if (validate) + fixInvalidChildren(invalidChildren); // Run node filters for (name in matchedNodes) { @@ -3019,8 +3034,12 @@ tinymce.html.Writer = function(settings) { else html[html.length] = ' />'; - /*if (indent && indentAfter[name]) - html.push('\n');*/ + if (empty && indent && indentAfter[name] && html.length > 0) { + value = html[html.length - 1]; + + if (value.length > 0 && value !== '\n') + html.push('\n'); + } }, end: function(name) { @@ -3061,10 +3080,13 @@ tinymce.html.Writer = function(settings) { html.push(''); else html.push(''); + + if (indent) + html.push('\n'); }, doctype: function(text) { - html.push(''); + html.push('', indent ? '\n' : ''); }, reset: function() { @@ -3201,7 +3223,8 @@ tinymce.html.Writer = function(settings) { isIE = tinymce.isIE, Entities = tinymce.html.Entities, simpleSelectorRe = /^([a-z0-9],?)+$/i, - blockElementsMap = tinymce.html.Schema.blockElementsMap; + blockElementsMap = tinymce.html.Schema.blockElementsMap, + whiteSpaceRegExp = /^[ \t\r\n]*$/; tinymce.create('tinymce.dom.DOMUtils', { doc : null, @@ -3239,7 +3262,8 @@ tinymce.html.Writer = function(settings) { keep_values : false, hex_colors : 1 }, s); - + + t.schema = s.schema; t.styles = new tinymce.html.Styles({ url_converter : s.url_converter, url_converter_scope : s.url_converter_scope @@ -3469,9 +3493,7 @@ tinymce.html.Writer = function(settings) { remove : function(node, keep_children) { return this.run(node, function(node) { - var parent, child; - - parent = node.parentNode; + var child, parent = node.parentNode; if (!parent) return null; @@ -3539,7 +3561,7 @@ tinymce.html.Writer = function(settings) { n = this.get(n); if (!n) - return false; + return; // Gecko if (this.doc.defaultView && c) { @@ -3568,7 +3590,7 @@ tinymce.html.Writer = function(settings) { if (n.currentStyle && c) return n.currentStyle[na]; - return n.style[na]; + return n.style ? n.style[na] : undefined; }, setStyles : function(e, o) { @@ -3589,8 +3611,8 @@ tinymce.html.Writer = function(settings) { removeAllAttribs: function(e) { return this.run(e, function(e) { - var attrs = e.attributes; - for (var i = attrs.length - 1; i >= 0; i--) { + var i, attrs = e.attributes; + for (i = attrs.length - 1; i >= 0; i--) { e.removeAttributeNode(attrs.item(i)); } }); @@ -3645,7 +3667,7 @@ tinymce.html.Writer = function(settings) { } break; - + case "shape": e.setAttribute('data-mce-style', v); break; @@ -4257,6 +4279,45 @@ tinymce.html.Writer = function(settings) { return n.attributes; }, + isEmpty : function(node, elements) { + var self = this, i, attributes, type, walker, name; + + node = node.firstChild; + if (node) { + walker = new tinymce.dom.TreeWalker(node); + elements = elements || self.schema ? self.schema.getNonEmptyElements() : null; + + do { + type = node.nodeType; + + if (type === 1) { + // Ignore bogus elements + if (node.getAttribute('data-mce-bogus')) + continue; + + // Keep empty elements like + if (elements && elements[node.nodeName.toLowerCase()]) + return false; + + // Keep elements with data attributes or name attribute like + attributes = self.getAttribs(node); + i = node.attributes.length; + while (i--) { + name = node.attributes[i].nodeName; + if (name === "name" || name.indexOf('data-') === 0) + return false; + } + } + + // Keep non whitespace text nodes + if ((type === 3 && !whiteSpaceRegExp.test(node.nodeValue))) + return false; + } while (node = walker.next()); + } + + return true; + }, + destroy : function(s) { var t = this; @@ -4312,23 +4373,21 @@ tinymce.html.Writer = function(settings) { // this function will then trim of empty edges and produce: //

    text 1

    CHOP

    text 2

    function trim(node) { - var i, children = node.childNodes; + var i, children = node.childNodes, type = node.nodeType; - if (node.nodeType == 1 && node.getAttribute('data-mce-type') == 'bookmark') + if (type == 1 && node.getAttribute('data-mce-type') == 'bookmark') return; for (i = children.length - 1; i >= 0; i--) trim(children[i]); - if (node.nodeType != 9) { + if (type != 9) { // Keep non whitespace text nodes - if (node.nodeType == 3 && node.nodeValue.length > 0) { + if (type == 3 && node.nodeValue.length > 0) { // If parent element isn't a block or there isn't any useful contents for example "

    " if (!t.isBlock(node.parentNode) || tinymce.trim(node.nodeValue).length > 0) return; - } - - if (node.nodeType == 1) { + } else if (type == 1) { // If the only child is a bookmark then move it up children = node.childNodes; if (children.length == 1 && children[0] && children[0].nodeType == 1 && children[0].getAttribute('data-mce-type') == 'bookmark') @@ -7428,7 +7487,13 @@ window.tinymce.dom.Sizzle = Sizzle; if (s) { t.explicitRange = r; - s.removeAllRanges(); + + try { + s.removeAllRanges(); + } catch (ex) { + // IE9 might throw errors here don't know why + } + s.addRange(r); t.selectedRange = s.getRangeAt(0); } @@ -7860,6 +7925,10 @@ window.tinymce.dom.Sizzle = Sizzle; htmlParser.parse(args.getInner ? node.innerHTML : tinymce.trim(dom.getOuterHTML(node), args), args) ); + // Replace all BOM characters for now until we can find a better solution + if (!args.cleanup) + args.content = args.content.replace(/\uFEFF/g, ''); + // Post process if (!args.no_events) onPostProcess.dispatch(self, args); @@ -9762,21 +9831,20 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', { hideMenu : function(e) { var t = this; - // Prevent double toogles by canceling the mouse click event to the button - if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';})) - return; - - if (!e || !DOM.getParent(e.target, '.mceSplitButtonMenu')) { - DOM.removeClass(t.id, 'mceSplitButtonSelected'); - Event.remove(DOM.doc, 'mousedown', t.hideMenu, t); - Event.remove(t.id + '_menu', 'keydown', t._keyHandler); - DOM.hide(t.id + '_menu'); - } + if (t.isMenuVisible) { + // Prevent double toogles by canceling the mouse click event to the button + if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';})) + return; - t.onHideMenu.dispatch(t); + if (!e || !DOM.getParent(e.target, '.mceSplitButtonMenu')) { + DOM.removeClass(t.id, 'mceSplitButtonSelected'); + Event.remove(DOM.doc, 'mousedown', t.hideMenu, t); + Event.remove(t.id + '_menu', 'keydown', t._keyHandler); + DOM.hide(t.id + '_menu'); + } - t.isMenuVisible = 0; - t.editor.focus(); + t.isMenuVisible = 0; + } }, renderMenu : function() { @@ -9950,7 +10018,7 @@ tinymce.create('tinymce.ui.ToolbarGroup:tinymce.ui.Container', { (function(tinymce) { // Shorten class names -var dom = tinymce.DOM, each = tinymce.each +var dom = tinymce.DOM, each = tinymce.each; tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { renderHTML : function() { var t = this, h = '', c, co, s = t.settings, i, pr, nx, cl; @@ -12622,14 +12690,17 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { mceInsertContent : function(command, ui, value) { var caretNode, rng, rootNode, parent, node, rng, nodeRect, viewPortRect, args; - function findSuitableCaretNode(start_node, root_node) { - var node, walker = new tinymce.dom.TreeWalker(start_node, root_node); + function findSuitableCaretNode(node, root_node, next) { + var walker = new tinymce.dom.TreeWalker(next ? node.nextSibling : node.previousSibling, root_node); while ((node = walker.current())) { if ((node.nodeType == 3 && tinymce.trim(node.nodeValue).length) || node.nodeName == 'BR' || node.nodeName == 'IMG') return node; - walker.prev(); + if (next) + walker.next(); + else + walker.prev(); } }; @@ -12650,7 +12721,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { // Move the caret into the last suitable location within the previous sibling if it's a block since the block might be split if (caretNode.previousSibling && dom.isBlock(caretNode.previousSibling) || caretNode.parentNode == rootNode) { - node = findSuitableCaretNode(caretNode.previousSibling, rootNode); + node = findSuitableCaretNode(caretNode, rootNode); if (node) { if (node.nodeName == 'BR') node.parentNode.insertBefore(caretNode, node); @@ -12666,9 +12737,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { // This will remove invalid elements/attributes and fix nesting issues dom.setOuterHTML(parent, new tinymce.html.Serializer({}, editor.schema).serialize( - new tinymce.html.DomParser({ - remove_trailing_brs : true - }, editor.schema).parse(dom.getOuterHTML(parent)) + editor.parser.parse(dom.getOuterHTML(parent)) ) ); @@ -12682,7 +12751,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { // Find caret after cleanup and move selection to that location caretNode = dom.select('#__mce')[0]; if (caretNode) { - node = findSuitableCaretNode(caretNode.previousSibling, rootNode); + node = findSuitableCaretNode(caretNode, rootNode) || findSuitableCaretNode(caretNode, rootNode, true); dom.remove(caretNode); if (node) { @@ -12791,7 +12860,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { }, mceReplaceContent : function(command, ui, value) { - editor.execCommand('mceInsertContent', false, selection.setContent(value.replace(/\{\$selection\}/g, selection.getContent({format : 'text'})))); + editor.execCommand('mceInsertContent', false, value.replace(/\{\$selection\}/g, selection.getContent({format : 'text'}))); }, mceInsertLink : function(command, ui, value) { @@ -13064,19 +13133,10 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { return rng2.cloneContents().textContent.length == 0; }; - function isEmpty(n) { - n = n.innerHTML; - - n = n.replace(/<(img|hr|table|input|select|textarea)[ \>]/gi, '-'); // Keep these convert them to - chars - n = n.replace(/<[^>]+>/g, ''); // Remove all tags - - return n.replace(/[ \u00a0\t\r\n]+/g, '') == ''; - }; - function splitList(selection, dom, li) { var listBlock, block; - if (isEmpty(li)) { + if (dom.isEmpty(li)) { listBlock = dom.getParent(li, 'ul,ol'); if (!dom.getParent(listBlock.parentNode, 'ul,ol')) { @@ -13607,7 +13667,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { aft.innerHTML = aft.firstChild.innerHTML; // Padd empty blocks - if (isEmpty(bef)) + if (dom.isEmpty(bef)) bef.innerHTML = '
    '; function appendStyles(e, en) { @@ -13641,7 +13701,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { }; // Fill empty afterblook with current style - if (isEmpty(aft)) + if (dom.isEmpty(aft)) car = appendStyles(aft, en); // Opera needs this one backwards for older versions -- cgit v1.2.3