X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Ftiny_mce%2Ftiny_mce_src.js;h=64feb6663762f61f030fb01d3f7abf8f816900ac;hb=a8ce0eff2e9c97d6c0c878451f83a3759ec0d07f;hp=8c665b09535c46d2bdac3012c7b881f0948b6e2c;hpb=2797e21fbf023037fc706d85ab314e609a0d3a07;p=citadel.git diff --git a/webcit/tiny_mce/tiny_mce_src.js b/webcit/tiny_mce/tiny_mce_src.js index 8c665b095..64feb6663 100644 --- a/webcit/tiny_mce/tiny_mce_src.js +++ b/webcit/tiny_mce/tiny_mce_src.js @@ -5,9 +5,9 @@ var tinymce = { majorVersion : '3', - minorVersion : '4.5', + minorVersion : '4.9', - releaseDate : '2011-09-06', + releaseDate : '2012-02-23', _init : function() { var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v; @@ -535,7 +535,7 @@ tinymce.create('tinymce.util.Dispatcher', { // And this is also more efficient for (i = 0; i
" - if (!t.isBlock(node.parentNode) || tinymce.trim(node.nodeValue).length > 0) + // Also keep text nodes with only spaces if surrounded by spans. + // eg. "
a b
" 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 @@ -4621,9 +4794,9 @@ tinymce.html.Writer = function(settings) { // 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); @@ -5640,7 +5813,7 @@ tinymce.html.Writer = function(settings) { parent = node.parentNode; root = dom.getRoot().parentNode; - while (parent != root) { + while (parent != root && parent.nodeType !== 9) { children = parent.children; i = children.length; @@ -7123,6 +7296,12 @@ window.tinymce.dom.Sizzle = Sizzle; return; } + // When loaded asynchronously, the DOM Content may already be loaded + if (doc.readyState === 'complete') { + t._pageInit(win); + return; + } + // Use IE method if (doc.attachEvent) { doc.attachEvent("onreadystatechange", function() { @@ -7923,7 +8102,8 @@ window.tinymce.dom.Sizzle = Sizzle; } 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 @@ -8019,7 +8199,8 @@ window.tinymce.dom.Sizzle = Sizzle; if (sb && eb && sb != eb) { n = sb; - while ((n = n.nextSibling) && n != eb) { + var walker = new tinymce.dom.TreeWalker(sb, dom.getRoot()); + while ((n = walker.next()) && n != eb) { if (dom.isBlock(n)) bl.push(n); } @@ -8034,6 +8215,11 @@ window.tinymce.dom.Sizzle = Sizzle; 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; @@ -8068,18 +8254,24 @@ window.tinymce.dom.Sizzle = Sizzle; 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; } } } @@ -8094,7 +8286,7 @@ window.tinymce.dom.Sizzle = Sizzle; // Normalize the end points normalizeEndPoint(true); - if (rng.collapsed) + if (!rng.collapsed) normalizeEndPoint(); // Set the selection if it was normalized @@ -8206,12 +8398,11 @@ window.tinymce.dom.Sizzle = Sizzle; 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); @@ -8275,8 +8466,8 @@ window.tinymce.dom.Sizzle = Sizzle; function trim(value) { return value.replace(/()/g, '\n') .replace(/^[\r\n]*|[\r\n]*$/g, '') - .replace(/^\s*(\/\/\s*|\]\]>|-->|\]\]-->)\s*$/g, ''); + .replace(/^\s*(()?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g, ''); }; while (i--) { @@ -8425,7 +8616,7 @@ window.tinymce.dom.Sizzle = Sizzle; // Replace all BOM characters for now until we can find a better solution if (!args.cleanup) - args.content = args.content.replace(/\uFEFF/g, ''); + args.content = args.content.replace(/\uFEFF|\u200B/g, ''); // Post process if (!args.no_events) @@ -8719,6 +8910,24 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { return; } + 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; + }; + function collectSiblings(node, name, end_node) { var siblings = []; @@ -8748,7 +8957,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { if (!next) siblings.reverse(); - callback(siblings); + callback(exclude(siblings)); } } }; @@ -8761,28 +8970,28 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { if (endContainer.nodeType == 1 && endContainer.hasChildNodes()) endContainer = endContainer.childNodes[Math.min(endOffset - 1, endContainer.childNodes.length - 1)]; - // Find common ancestor and end points - ancestor = dom.findCommonAncestor(startContainer, endContainer); - // Same container if (startContainer == endContainer) - return callback([startContainer]); + 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) + if (node === endContainer) return walkBoundary(startContainer, ancestor, true); - if (node == ancestor) + if (node === ancestor) break; } // Process right side for (node = endContainer; node; node = node.parentNode) { - if (node == startContainer) + if (node === startContainer) return walkBoundary(endContainer, ancestor); - if (node == ancestor) + if (node === ancestor) break; } @@ -8801,48 +9010,46 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { ); if (siblings.length) - callback(siblings); + callback(exclude(siblings)); // Walk right leaf walkBoundary(endContainer, endPoint); }; - /* this.split = function(rng) { + this.split = function(rng) { var startContainer = rng.startContainer, startOffset = rng.startOffset, endContainer = rng.endContainer, endOffset = rng.endOffset; function splitText(node, offset) { - if (offset == node.nodeValue.length) - node.appendData(INVISIBLE_CHAR); - - node = node.splitText(offset); - - if (node.nodeValue === INVISIBLE_CHAR) - node.nodeValue = ''; - - return node; + return node.splitText(offset); }; // Handle single text node - if (startContainer == endContainer) { - if (startContainer.nodeType == 3) { - if (startOffset != 0) - startContainer = endContainer = splitText(startContainer, startOffset); - - if (endOffset - startOffset != startContainer.nodeValue.length) - splitText(startContainer, endOffset - startOffset); + 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) { + 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 != endContainer.nodeValue.length) { + if (endContainer.nodeType == 3 && endOffset > 0 && endOffset < endContainer.nodeValue.length) { endContainer = splitText(endContainer, endOffset).previousSibling; endOffset = endContainer.nodeValue.length; } @@ -8855,7 +9062,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { endOffset : endOffset }; }; -*/ + }; tinymce.dom.RangeUtils.compareRanges = function(rng1, rng2) { @@ -9025,6 +9232,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { } }); })(tinymce); + (function(tinymce) { // Shorten class names var DOM = tinymce.DOM, is = tinymce.is; @@ -9560,7 +9768,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', { // 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({ @@ -9667,10 +9875,27 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', { }, postRender : function() { - var t = this, s = t.settings; - + var t = this, s = t.settings, imgBookmark; + + // 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) { + var nodeName = t.editor.selection.getNode().nodeName; + imgBookmark = nodeName === 'IMG' ? t.editor.selection.getBookmark() : null; + }); + } 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 && imgBookmark !== null) { + t.editor.selection.moveToBookmark(imgBookmark); + } + 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); }); } @@ -9706,7 +9931,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', { return t.selectByIndex(-1); // Is string or number make function selector - if (va && va.call) + if (va && typeof(va)=="function") f = va; else { f = function(v) { @@ -9731,20 +9956,23 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', { }, selectByIndex : function(idx) { - var t = this, e, o; + var t = this, e, o, label; if (idx != t.selectedIndex) { e = DOM.get(t.id + '_text'); + label = DOM.get(t.id + '_voiceDesc'); o = t.items[idx]; if (o) { t.selectedValue = o.value; t.selectedIndex = idx; DOM.setHTML(e, DOM.encode(o.title)); + DOM.setHTML(label, t.settings.title + " - " + o.title); DOM.removeClass(e, 'mceTitle'); DOM.setAttrib(t.id, 'aria-valuenow', o.title); } else { DOM.setHTML(e, DOM.encode(t.settings.title)); + DOM.setHTML(label, DOM.encode(t.settings.title)); DOM.addClass(e, 'mceTitle'); t.selectedValue = t.selectedIndex = null; DOM.setAttrib(t.id, 'aria-valuenow', t.settings.title); @@ -9773,7 +10001,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', { renderHTML : function() { var h = '', t = this, s = t.settings, cp = t.classPrefix; - h = '' + DOM.createHTML('span', {id: t.id + '_voiceDesc', 'class': 'voiceLabel', style:'display:none;'}, t.settings.title); h += DOM.createHTML('a', {id : t.id + '_text', tabindex : -1, href : 'javascript:;', 'class' : 'mceText', onclick : "return false;", onmousedown : 'return false;'}, DOM.encode(t.settings.title)) + ' | '; h += '' + DOM.createHTML('a', {id : t.id + '_open', tabindex : -1, href : 'javascript:;', 'class' : 'mceOpen', onclick : "return false;", onmousedown : 'return false;'}, '') + ' | '; @@ -9869,6 +10097,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', { if (o.value === undefined) { m.add({ title : o.title, + role : "option", 'class' : 'mceMenuItemTitle', onclick : function() { if (t.settings.onselect('') !== false) @@ -9877,6 +10106,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', { }); } else { o.id = DOM.uniqueId(); + o.role= "option"; o.onclick = function() { if (t.settings.onselect(o.value) !== false) t.select(o.value); // Must be runned after @@ -9952,6 +10182,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', { } }); })(tinymce); + (function(tinymce) { var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher; @@ -9977,7 +10208,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', { return t.selectByIndex(-1); // Is string or number make function selector - if (va && va.call) + if (va && typeof(va)=="function") f = va; else { f = function(v) { @@ -10210,8 +10441,8 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', { h += '' + DOM.createHTML('a', {role: 'button', id : t.id + '_open', tabindex: '-1', href : 'javascript:;', 'class' : 'mceOpen ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + ' | '; h += '