assets/vendor/tinymce/tiny_mce_jquery.js in tinymce-rails-3.4.7.0.2 vs assets/vendor/tinymce/tiny_mce_jquery.js in tinymce-rails-3.4.8

- old
+ new

@@ -3,13 +3,13 @@ undefined, isRegExpBroken = 'B'.replace(/A(.)|B/, '$1') === '$1'; var tinymce = { majorVersion : '3', - minorVersion : '4.7', + minorVersion : '4.8', - releaseDate : '2011-11-03', + releaseDate : '2012-02-02', _init : function() { var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v; t.isOpera = win.opera && opera.buildNumber; @@ -808,11 +808,11 @@ // Needs to be a real loop since the listener count might change while looping // And this is also more efficient for (i = 0; i<li.length; i++) { c = li[i]; - s = c.cb.apply(c.scope, a); + s = c.cb.apply(c.scope, a.length > 0 ? a : [c.scope]); if (s === false) break; } @@ -851,11 +851,11 @@ u = ((s.base_uri && s.base_uri.protocol) || 'http') + '://mce_host' + t.toAbsPath(base_url, u); } // Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri) u = u.replace(/@@/g, '(mce_at)'); // Zope 3 workaround, they use @@something - u = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u); + u = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u); each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], function(v, i) { var s = u[i]; // Zope 3 workaround, they use @@something if (s) @@ -1321,11 +1321,14 @@ BACKSPACE: 8, ENTER: 13, TAB: 9, SPACEBAR: 32, UP: 38, - DOWN: 40 + DOWN: 40, + modifierPressed: function (e) { + return e.shiftKey || e.ctrlKey || e.altKey; + } } })(tinymce); (function(tinymce) { var VK = tinymce.VK, BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE; @@ -1335,11 +1338,11 @@ ed.onKeyDown.add(function(ed, e) { var rng, blockElm, node, clonedSpan, isDelete; isDelete = e.keyCode == DELETE; - if (isDelete || e.keyCode == BACKSPACE) { + if ((isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) { e.preventDefault(); rng = selection.getRng(); // Find root block blockElm = dom.getParent(rng.startContainer, dom.isBlock); @@ -1452,10 +1455,30 @@ ed.nodeChanged(); }); }; + function removeStylesOnPTagsInheritedFromHeadingTag(ed) { + ed.onKeyDown.add(function(ed, event) { + function checkInHeadingTag(ed) { + var currentNode = ed.selection.getNode(); + var headingTags = 'h1,h2,h3,h4,h5,h6'; + return ed.dom.is(currentNode, headingTags) || ed.dom.getParent(currentNode, headingTags) !== null; + } + + if (event.keyCode === VK.ENTER && !VK.modifierPressed(event) && checkInHeadingTag(ed)) { + setTimeout(function() { + var currentNode = ed.selection.getNode(); + if (ed.dom.is(currentNode, 'p')) { + ed.dom.setAttrib(currentNode, 'style', null); + // While tiny's content is correct after this method call, the content shown is not representative of it and needs to be 'repainted' + ed.execCommand('mceCleanup'); + } + }, 0); + } + }); + } function selectionChangeNodeChanged(ed) { var lastRng, selectionTimer; ed.dom.bind(ed.getDoc(), 'selectionchange', function() { if (selectionTimer) { @@ -1476,11 +1499,11 @@ } function ensureBodyHasRoleApplication(ed) { document.body.setAttribute("role", "application"); } - + tinymce.create('tinymce.util.Quirks', { Quirks: function(ed) { // WebKit if (tinymce.isWebKit) { cleanupStylesWhenDeleting(ed); @@ -1497,10 +1520,11 @@ // IE if (tinymce.isIE) { removeHrOnBackspace(ed); emptyEditorWhenDeleting(ed); ensureBodyHasRoleApplication(ed); + removeStylesOnPTagsInheritedFromHeadingTag(ed) } // Gecko if (tinymce.isGecko) { removeHrOnBackspace(ed); @@ -4169,10 +4193,11 @@ if (t.settings.strict) n = n.toLowerCase(); return this.run(e, function(e) { var s = t.settings; + var originalValue = e.getAttribute(n); if (v !== null) { switch (n) { case "style": if (!is(v, 'string')) { each(v, function(v, n) { @@ -4215,10 +4240,16 @@ } if (is(v) && v !== null && v.length !== 0) e.setAttribute(n, '' + v, 2); else e.removeAttribute(n, 2); + + // fire onChangeAttrib event for attributes that have changed + if (tinyMCE.activeEditor && originalValue != v) { + var ed = tinyMCE.activeEditor; + ed.onSetAttrib.dispatch(ed, e, n, v); + } }); }, setAttribs : function(e, o) { var t = this; @@ -4920,21 +4951,30 @@ // this function will then trim of empty edges and produce: // <p>text 1</p><b>CHOP</b><p>text 2</p> function trim(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--) trim(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 "<p> </p>" - if (!t.isBlock(node.parentNode) || tinymce.trim(node.nodeValue).length > 0) + // Also keep text nodes with only spaces if surrounded by spans. + // eg. "<p><span>a</span> <span>b</span></p>" should keep space between a and b + var trimmedLength = tinymce.trim(node.nodeValue).length; + if (!t.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; if (children.length == 1 && children[0] && children[0].nodeType == 1 && children[0].getAttribute('data-mce-type') == 'bookmark') @@ -4967,13 +5007,13 @@ pa = pe.parentNode; pa.insertBefore(trim(bef), pe); // Insert middle chunk if (re) - pa.replaceChild(re, e); - else - pa.insertBefore(e, pe); + pa.replaceChild(re, e); + else + pa.insertBefore(e, pe); // Insert after chunk pa.insertBefore(trim(aft), pe); t.remove(pe); @@ -7199,11 +7239,12 @@ } catch (ex) { // IE9 might throw errors here don't know why } s.addRange(r); - t.selectedRange = s.getRangeAt(0); + // adding range isn't always successful so we need to check range count otherwise an exception can occur + t.selectedRange = s.rangeCount > 0 ? s.getRangeAt(0) : null; } } else { // Is W3C Range if (r.cloneRange) { t.tridentSel.addRange(r); @@ -7311,10 +7352,15 @@ }, normalize : function() { var self = this, rng, normalized; + // TODO: + // Retain selection direction. + // Lean left/right on Gecko for inline elements. + // Run this on mouse up/key up when the user manually moves the selection + // Normalize only on non IE browsers for now if (tinymce.isIE) return; function normalizeEndPoint(start) { @@ -7345,22 +7391,28 @@ do { // Found a text node use that position if (node.nodeType === 3) { offset = start ? 0 : node.nodeValue.length - 1; container = node; + normalized = true; break; } - // Found a BR element that we can place the caret before - if (node.nodeName === 'BR') { + // Found a BR/IMG element that we can place the caret before + if (/^(BR|IMG)$/.test(node.nodeName)) { offset = dom.nodeIndex(node); container = node.parentNode; + + // Put caret after image when moving the end point + if (node.nodeName == "IMG" && !start) { + offset++; + } + + normalized = true; break; } } while (node = (start ? walker.next() : walker.prev())); - - normalized = true; } } } // Set endpoint if it was normalized @@ -7371,11 +7423,11 @@ rng = self.getRng(); // Normalize the end points normalizeEndPoint(true); - if (rng.collapsed) + if (!rng.collapsed) normalizeEndPoint(); // Set the selection if it was normalized if (normalized) { //console.log(self.dom.dumpRng(rng)); @@ -7483,16 +7535,15 @@ // Support the old apply_source_formatting option if (!settings.apply_source_formatting) settings.indent = false; - settings.remove_trailing_brs = true; - // Default DOM and Schema if they are undefined dom = dom || tinymce.DOM; schema = schema || new tinymce.html.Schema(settings); settings.entity_encoding = settings.entity_encoding || 'named'; + settings.remove_trailing_brs = "remove_trailing_brs" in settings ? settings.remove_trailing_brs : true; onPreProcess = new tinymce.util.Dispatcher(self); onPostProcess = new tinymce.util.Dispatcher(self); @@ -7552,12 +7603,12 @@ var i = nodes.length, node, value; function trim(value) { return value.replace(/(<!--\[CDATA\[|\]\]-->)/g, '\n') .replace(/^[\r\n]*|[\r\n]*$/g, '') - .replace(/^\s*(\/\/\s*<!--|\/\/\s*<!\[CDATA\[|<!--|<!\[CDATA\[)[\r\n]*/g, '') - .replace(/\s*(\/\/\s*\]\]>|\/\/\s*-->|\]\]>|-->|\]\]-->)\s*$/g, ''); + .replace(/^\s*((<!--)?(\s*\/\/)?\s*<!\[CDATA\[|(<!--\s*)?\/\*\s*<!\[CDATA\[\s*\*\/|(\/\/)?\s*<!--|\/\*\s*<!--\s*\*\/)\s*[\r\n]*/gi, '') + .replace(/\s*(\/\*\s*\]\]>\s*\*\/(-->)?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g, ''); }; while (i--) { node = nodes[i]; value = node.firstChild ? node.firstChild.value : ''; @@ -8854,11 +8905,11 @@ }, // Internal functions _setupKeyboardNav : function(){ var contextMenu, menuItems, t=this; - contextMenu = DOM.select('#menu_' + t.id)[0]; + contextMenu = DOM.get('menu_' + t.id); menuItems = DOM.select('a[role=option]', 'menu_' + t.id); menuItems.splice(0,0,contextMenu); t.keyboardNav = new tinymce.ui.KeyboardNavigation({ root: 'menu_' + t.id, items: menuItems, @@ -8961,16 +9012,32 @@ h += '</a>'; return h; }, postRender : function() { - var t = this, s = t.settings; + var t = this, s = t.settings, bookmark; + // In IE a large image that occupies the entire editor area will be deselected when a button is clicked, so + // need to keep the selection in case the selection is lost + if (tinymce.isIE && t.editor) { + tinymce.dom.Event.add(t.id, 'mousedown', function(e) { + bookmark = t.editor.selection.getBookmark(); + }); + } tinymce.dom.Event.add(t.id, 'click', function(e) { - if (!t.isDisabled()) + if (!t.isDisabled()) { + // restore the selection in case the selection is lost in IE + if (tinymce.isIE && t.editor && bookmark) { + tinymce.activeEditor.selection.moveToBookmark(bookmark); + } return s.onclick.call(s.scope, e); + } }); + tinymce.dom.Event.add(t.id, 'keyup', function(e) { + if (!t.isDisabled() && e.keyCode==tinymce.VK.SPACEBAR) + return s.onclick.call(s.scope, e); + }); } }); })(tinymce); (function(tinymce) { @@ -9671,20 +9738,26 @@ tr = DOM.add(tb, 'tr'); i = s.grid_width - 1; } n = DOM.add(tr, 'td'); - n = DOM.add(n, 'a', { - role : 'option', + var settings = { href : 'javascript:;', style : { backgroundColor : '#' + c }, 'title': t.editor.getLang('colors.' + c, c), 'data-mce-color' : '#' + c - }); + }; + // adding a proper ARIA role = button causes JAWS to read things incorrectly on IE. + if (!tinymce.isIE ) { + settings['role']= 'option'; + } + + n = DOM.add(n, 'a', settings); + if (t.editor.forcedHighContrastMode) { n = DOM.add(n, 'canvas', { width: 16, height: 16, 'aria-hidden': 'true' }); if (n.getContext && (context = n.getContext("2d"))) { context.fillStyle = '#' + c; context.fillRect(0, 0, 16, 16); @@ -10320,11 +10393,11 @@ // Shorten these names var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, Dispatcher = tinymce.util.Dispatcher, each = tinymce.each, isGecko = tinymce.isGecko, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit, is = tinymce.is, ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, - inArray = tinymce.inArray, grep = tinymce.grep, explode = tinymce.explode; + inArray = tinymce.inArray, grep = tinymce.grep, explode = tinymce.explode, VK = tinymce.VK; tinymce.create('tinymce.Editor', { Editor : function(id, s) { var t = this; @@ -10344,10 +10417,12 @@ 'onBeforeRenderUI', 'onPostRender', + 'onLoad', + 'onInit', 'onRemove', 'onActivate', @@ -10406,11 +10481,13 @@ 'onRedo', 'onVisualAid', - 'onSetProgressState' + 'onSetProgressState', + + 'onSetAttrib' ], function(e) { t[e] = new Dispatcher(t); }); t.settings = s = extend({ @@ -10758,11 +10835,11 @@ if (bc.indexOf('=') != -1) { bc = t.getParam('body_class', '', 'hash'); bc = bc[t.id] || ''; } - t.iframeHTML += '</head><body id="' + bi + '" class="mceContentBody ' + bc + '"><br></body></html>'; + t.iframeHTML += '</head><body id="' + bi + '" class="mceContentBody ' + bc + '" onload="window.parent.tinyMCE.get(\'' + t.id + '\').onLoad.dispatch();"><br></body></html>'; // Domain relaxing enabled, then set document domain if (tinymce.relaxedDomain && (isIE || (tinymce.isOpera && parseFloat(opera.version()) < 11))) { // We need to write the contents here in IE since multiple writes messes up refresh button and back button u = 'javascript:(function(){document.open();document.domain="' + document.domain + '";var ed = window.parent.tinyMCE.get("' + t.id + '");document.write(ed.iframeHTML);document.close();ed.setupIframe();})()'; @@ -11226,11 +11303,10 @@ if (ieRng.item) { controlElm = ieRng.item(0); } t._refreshContentEditable(); - selection.normalize(); // Is not content editable if (!ce) t.getWin().focus(); @@ -11998,36 +12074,38 @@ }); // Add block quote deletion handler t.onKeyDown.add(function(ed, e) { - // Was the BACKSPACE key pressed? - if (e.keyCode != 8) + if (e.keyCode != VK.BACKSPACE) return; - var n = ed.selection.getRng().startContainer; - var offset = ed.selection.getRng().startOffset; + var rng = ed.selection.getRng(); + if (!rng.collapsed) + return; + var n = rng.startContainer; + var offset = rng.startOffset; + while (n && n.nodeType && n.nodeType != 1 && n.parentNode) n = n.parentNode; - + // Is the cursor at the beginning of a blockquote? if (n && n.parentNode && n.parentNode.tagName === 'BLOCKQUOTE' && n.parentNode.firstChild == n && offset == 0) { // Remove the blockquote ed.formatter.toggle('blockquote', null, n.parentNode); // Move the caret to the beginning of n - var rng = ed.selection.getRng(); rng.setStart(n, 0); rng.setEnd(n, 0); ed.selection.setRng(rng); ed.selection.collapse(false); } }); - + // Add reset handler t.onReset.add(function() { t.setContent(t.startContent, {format : 'raw'}); }); @@ -12229,13 +12307,13 @@ var target = t.selection.getStart(); if (target !== t.getBody()) { t.dom.setAttrib(target, "style", null); - each(template, function(attr) { - target.setAttributeNode(attr.cloneNode(true)); - }); + each(template, function(attr) { + target.setAttributeNode(attr.cloneNode(true)); + }); } }; } function isSelectionAcrossElements() { @@ -12543,10 +12621,12 @@ mceInsertContent : function(command, ui, value) { var parser, serializer, parentNode, rootNode, fragment, args, marker, nodeRect, viewPortRect, rng, node, node2, bookmarkHtml, viewportBodyElement; + //selection.normalize(); + // Setup parser and serializer parser = editor.parser; serializer = new tinymce.html.Serializer({}, editor.schema); bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">\uFEFF</span>'; @@ -12769,11 +12849,18 @@ // Add queryCommandState overrides addCommands({ // Override justify commands 'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull' : function(command) { - return isFormatMatch('align' + command.substring(7)); + var name = 'align' + command.substring(7); + // Use Formatter.matchNode instead of Formatter.match so that we don't match on parent node. This fixes bug where for both left + // and right align buttons can be active. This could occur when selected nodes have align right and the parent has align left. + var nodes = selection.isCollapsed() ? [selection.getNode()] : selection.getSelectedBlocks(); + var matches = tinymce.map(nodes, function(node) { + return !!formatter.matchNode(node, name); + }); + return tinymce.inArray(matches, TRUE) !== -1; }, 'Bold,Italic,Underline,Strikethrough,Superscript,Subscript' : function(command) { return isFormatMatch(command); }, @@ -14166,34 +14253,10 @@ }; function apply(name, vars, node) { var formatList = get(name), format = formatList[0], bookmark, rng, i, isCollapsed = selection.isCollapsed(); - function moveStart(rng) { - var container = rng.startContainer, - offset = rng.startOffset, - walker, node; - - // Move startContainer/startOffset in to a suitable node - if (container.nodeType == 1 || container.nodeValue === "") { - container = container.nodeType == 1 ? container.childNodes[offset] : container; - - // Might fail if the offset is behind the last element in it's container - if (container) { - walker = new TreeWalker(container, container.parentNode); - for (node = walker.current(); node; node = walker.next()) { - if (node.nodeType == 3 && !isWhiteSpaceNode(node)) { - rng.setStart(node, 0); - break; - } - } - } - } - - return rng; - }; - function setElementFormat(elm, fmt) { fmt = fmt || format; if (elm) { if (fmt.onformat) { @@ -14540,59 +14603,21 @@ tinymce.walk(curSelNode, processUnderlineAndColor, 'childNodes'); processUnderlineAndColor(curSelNode); } selection.moveToBookmark(bookmark); - selection.setRng(moveStart(selection.getRng(TRUE))); + moveStart(selection.getRng(TRUE)); ed.nodeChanged(); } else performCaretAction('apply', name, vars); } } }; function remove(name, vars, node) { var formatList = get(name), format = formatList[0], bookmark, i, rng; - function moveStart(rng) { - var container = rng.startContainer, - offset = rng.startOffset, - walker, node, nodes, tmpNode; - // Convert text node into index if possible - if (container.nodeType == 3 && offset >= container.nodeValue.length - 1) { - container = container.parentNode; - offset = nodeIndex(container) + 1; - } - - // Move startContainer/startOffset in to a suitable node - if (container.nodeType == 1) { - nodes = container.childNodes; - container = nodes[Math.min(offset, nodes.length - 1)]; - walker = new TreeWalker(container); - - // If offset is at end of the parent node walk to the next one - if (offset > nodes.length - 1) - walker.next(); - - for (node = walker.current(); node; node = walker.next()) { - if (node.nodeType == 3 && !isWhiteSpaceNode(node)) { - // IE has a "neat" feature where it moves the start node into the closest element - // we can avoid this by inserting an element before it and then remove it after we set the selection - tmpNode = dom.create('a', null, INVISIBLE_CHAR); - node.parentNode.insertBefore(tmpNode, node); - - // Set selection and remove tmpNode - rng.setStart(node, 0); - selection.setRng(rng); - dom.remove(tmpNode); - - return; - } - } - } - }; - // Merges the styles for each node function process(node) { var children, i, l; // Grab the children first since the nodelist might be changed @@ -15675,11 +15700,15 @@ } dom.remove(node); } else { child = findFirstTextNode(node); - child = child.deleteData(0, 1); + + if (child.nodeValue.charAt(0) === INVISIBLE_CHAR) { + child = child.deleteData(0, 1); + } + dom.remove(node, 1); } selection.setRng(rng); } @@ -15805,45 +15834,90 @@ // Move selection to text node selection.setCursorLocation(node, 1); } }; - // Mark current caret container elements as bogus when getting the contents so we don't end up with empty elements - ed.onBeforeGetContent.addToTop(function() { - var nodes = [], i; + // Only bind the caret events once + if (!self._hasCaretEvents) { + // Mark current caret container elements as bogus when getting the contents so we don't end up with empty elements + ed.onBeforeGetContent.addToTop(function() { + var nodes = [], i; - if (isCaretContainerEmpty(getParentCaretContainer(selection.getStart()), nodes)) { - // Mark children - i = nodes.length; - while (i--) { - dom.setAttrib(nodes[i], 'data-mce-bogus', '1'); + if (isCaretContainerEmpty(getParentCaretContainer(selection.getStart()), nodes)) { + // Mark children + i = nodes.length; + while (i--) { + dom.setAttrib(nodes[i], 'data-mce-bogus', '1'); + } } - } - }); + }); - // Remove caret container on mouse up and on key up - tinymce.each('onMouseUp onKeyUp'.split(' '), function(name) { - ed[name].addToTop(function() { - removeCaretContainer(); + // Remove caret container on mouse up and on key up + tinymce.each('onMouseUp onKeyUp'.split(' '), function(name) { + ed[name].addToTop(function() { + removeCaretContainer(); + }); }); - }); - // Remove caret container on keydown and it's a backspace, enter or left/right arrow keys - ed.onKeyDown.addToTop(function(ed, e) { - var keyCode = e.keyCode; + // Remove caret container on keydown and it's a backspace, enter or left/right arrow keys + ed.onKeyDown.addToTop(function(ed, e) { + var keyCode = e.keyCode; - if (keyCode == 8 || keyCode == 37 || keyCode == 39) { - removeCaretContainer(getParentCaretContainer(selection.getStart())); - } - }); + if (keyCode == 8 || keyCode == 37 || keyCode == 39) { + removeCaretContainer(getParentCaretContainer(selection.getStart())); + } + }); + self._hasCaretEvents = true; + } + // Do apply or remove caret format if (type == "apply") { applyCaretFormat(); } else { removeCaretFormat(); } }; + + function moveStart(rng) { + var container = rng.startContainer, + offset = rng.startOffset, + walker, node, nodes, tmpNode; + + // Convert text node into index if possible + if (container.nodeType == 3 && offset >= container.nodeValue.length - 1) { + container = container.parentNode; + offset = nodeIndex(container) + 1; + } + + // Move startContainer/startOffset in to a suitable node + if (container.nodeType == 1) { + nodes = container.childNodes; + container = nodes[Math.min(offset, nodes.length - 1)]; + walker = new TreeWalker(container); + + // If offset is at end of the parent node walk to the next one + if (offset > nodes.length - 1) + walker.next(); + + for (node = walker.current(); node; node = walker.next()) { + if (node.nodeType == 3 && !isWhiteSpaceNode(node)) { + // IE has a "neat" feature where it moves the start node into the closest element + // we can avoid this by inserting an element before it and then remove it after we set the selection + tmpNode = dom.create('a', null, INVISIBLE_CHAR); + node.parentNode.insertBefore(tmpNode, node); + + // Set selection and remove tmpNode + rng.setStart(node, 0); + selection.setRng(rng); + dom.remove(tmpNode); + + return; + } + } + } + }; + }; })(tinymce); tinymce.onAddEditor.add(function(tinymce, ed) { var filters, fontSizes, dom, settings = ed.settings;