Changeset 7729


Ignore:
Timestamp:
06/12/10 07:17:45 (2 years ago)
Author:
PaulHarvey
Message:

Item8476: Upgrade to TinyMCE 3.3.7 - mostly IE fixes

Also fix for toolbar buttons not accurately reflecting selection state

Location:
trunk/TinyMCEPlugin
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/TinyMCEPlugin/lib/Foswiki/Plugins/TinyMCEPlugin.pm

    r7692 r7729  
    99 
    1010our $VERSION           = '$Rev$'; 
    11 our $RELEASE           = '21 May 2010'; 
     11our $RELEASE           = '12 Jun 2010'; 
    1212our $SHORTDESCRIPTION  = 'Integration of the Tiny MCE WYSIWYG Editor'; 
    1313our $NO_PREFS_IN_TOPIC = 1; 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/changelog.txt

    r7493 r7729  
     1Version 3.3.7 (2010-06-10) 
     2        Fixed bug where context menu would produce an error on IE if you right clicked twice and left clicked once. 
     3        Fixed bug where resizing of the window on WebKit browsers in fullscreen mode wouldn't position the statusbar correctly. 
     4        Fixed bug where IE would produce an error if the editor was empty and you where undoing to that initial level. 
     5        Fixed bug where setting the table background on gecko would produce \" entities inside the url style property. 
     6        Fixed bug where the button states wouldn't be updated correctly on IE if you placed the caret inside the new element. 
     7        Fixed bug where undo levels wasn't properly added after applying styles or font sizes. 
     8        Fixed bug where IE would throw an error if you used "select all" on empty elements and applied formatting to that. 
     9        Fixed bug where IE could select one extra character when you did a bookmark call on a caret location. 
     10        Fixed bug where IE could produce a script error on delete since it would sometimes produce an invalid DOM. 
     11        Fixed bug where IE would return the wrong start element if the whole element was selected. 
     12        Fixed bug where formatting states wasn't updated on IE if you pressed enter at the end of a block with formatting. 
     13        Fixed bug where submenus for the context menu wasn't removed correctly when the editor was destroyed. 
     14        Fixed bug where Gecko could select the wrong element after applying format to multiple elements. 
     15        Fixed bug where Gecko would delete parts of the previous element if the selection range was a element selection. 
     16        Fixed bug where Gecko would not merge paragraph elements correctly if they contained br elements. 
     17        Fixed bug where the cleanup button could produce span artifacts if you pressed it twice in a row. 
     18        Fixed bug where the fullpage plugin header/footer would be have it's header reseted to it's initial state on undo. 
     19        Fixed bug where an empty paragraph would be collapsed if you performed a cleanup while having the caret inside it. 
     20        Fixed a few memory leaks on IE especially with drop menus in listboxes and the spellchecker. 
     21        Fixed so formats applied to the current caret gets merged to reduce the number of output elements. 
     22        Added the latest version of Sizzle for the CSS selector logic to fix a compatibility issue with prototype. 
    123Version 3.3.6 (2010-05-20) 
    224        Fixed bug where a editor.focus call could produce errors on IE in very specific scenarios. 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/Editor.js

    r7493 r7729  
    23912391                        // Add node change handlers 
    23922392                        t.onMouseUp.add(t.nodeChanged); 
    2393                         t.onClick.add(t.nodeChanged); 
     2393                        //t.onClick.add(t.nodeChanged); 
    23942394                        t.onKeyUp.add(function(ed, e) { 
    23952395                                var c = e.keyCode; 
     
    25652565 
    25662566                                t.onKeyDown.add(function(ed, e) { 
     2567                                        var rng, tmpRng, parent, offset; 
     2568 
     2569                                        // IE has a really odd bug where the DOM might include an node that doesn't have 
     2570                                        // a proper structure. If you try to access nodeValue it would throw an illegal value exception. 
     2571                                        // This seems to only happen when you delete contents and it seems to be avoidable if you refresh the element 
     2572                                        // after you delete contents from it. See: #3008923 
     2573                                        if (isIE && e.keyCode == 46) { 
     2574                                                rng = t.selection.getRng(); 
     2575 
     2576                                                if (rng.parentElement) { 
     2577                                                        parent = rng.parentElement(); 
     2578 
     2579                                                        // Get the current caret position within the element 
     2580                                                        tmpRng = rng.duplicate(); 
     2581                                                        tmpRng.moveToElementText(parent); 
     2582                                                        tmpRng.setEndPoint('EndToEnd', rng); 
     2583                                                        offset = tmpRng.text.length; 
     2584 
     2585                                                        // Select next word when ctrl key is used in combo with delete 
     2586                                                        if (e.ctrlKey) { 
     2587                                                                rng.moveEnd('word', 1); 
     2588                                                                rng.select(); 
     2589                                                        } 
     2590 
     2591                                                        // Delete contents 
     2592                                                        t.selection.getSel().clear(); 
     2593 
     2594                                                        // Check if we are within the same parent 
     2595                                                        if (rng.parentElement() == parent) { 
     2596                                                                try { 
     2597                                                                        // Update the HTML and hopefully it will remove the artifacts 
     2598                                                                        parent.innerHTML = parent.innerHTML; 
     2599                                                                } catch (ex) { 
     2600                                                                        // And since it's IE it can sometimes produce an unknown runtime error 
     2601                                                                } 
     2602 
     2603                                                                // Restore the caret position 
     2604                                                                tmpRng.moveToElementText(parent); 
     2605                                                                tmpRng.collapse(); 
     2606                                                                tmpRng.move('character', offset); 
     2607                                                                tmpRng.select(); 
     2608                                                        } 
     2609 
     2610                                                        // Block the default delete behavior since it might be broken 
     2611                                                        e.preventDefault(); 
     2612                                                        return; 
     2613                                                } 
     2614                                        } 
     2615 
    25672616                                        // Is caracter positon keys 
    25682617                                        if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) { 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/EditorCommands.js

    r7493 r7729  
    251251 
    252252                        mceCleanup : function() { 
    253                                 storeSelection(); 
     253                                var bookmark = selection.getBookmark(); 
     254 
    254255                                editor.setContent(editor.getContent({cleanup : TRUE}), {cleanup : TRUE}); 
    255                                 restoreSelection(); 
     256 
     257                                selection.moveToBookmark(bookmark); 
    256258                        }, 
    257259 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/ForceBlocks.js

    r7493 r7729  
    2020                FALSE = false; 
    2121 
     22        function cloneFormats(node) { 
     23                var clone, temp, inner; 
     24 
     25                do { 
     26                        if (/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(node.nodeName)) { 
     27                                if (clone) { 
     28                                        temp = node.cloneNode(false); 
     29                                        temp.appendChild(clone); 
     30                                        clone = temp; 
     31                                } else { 
     32                                        clone = inner = node.cloneNode(false); 
     33                                } 
     34 
     35                                clone.removeAttribute('id'); 
     36                        } 
     37                } while (node = node.parentNode); 
     38 
     39                if (clone) 
     40                        return {wrapper : clone, inner : inner}; 
     41        }; 
     42 
    2243        // Checks if the selection/caret is at the end of the specified block element 
    2344        function isAtEnd(rng, par) { 
     
    131152                        } 
    132153 
    133                         if (!isIE && s.force_p_newlines) { 
    134                                 ed.onKeyPress.add(function(ed, e) { 
    135                                         if (e.keyCode == 13 && !e.shiftKey && !t.insertPara(e)) 
    136                                                 Event.cancel(e); 
    137                                 }); 
     154                        if (s.force_p_newlines) { 
     155                                if (!isIE) { 
     156                                        ed.onKeyPress.add(function(ed, e) { 
     157                                                if (e.keyCode == 13 && !e.shiftKey && !t.insertPara(e)) 
     158                                                        Event.cancel(e); 
     159                                        }); 
     160                                } else { 
     161                                        // Ungly hack to for IE to preserve the formatting when you press 
     162                                        // enter at the end of a block element with formatted contents 
     163                                        // This logic overrides the browsers default logic with 
     164                                        // custom logic that enables us to control the output 
     165                                        tinymce.addUnload(function() { 
     166                                                t._previousFormats = 0; // Fix IE leak 
     167                                        }); 
     168 
     169                                        ed.onKeyPress.add(function(ed, e) { 
     170                                                t._previousFormats = 0; 
     171 
     172                                                // Clone the current formats, this will later be applied to the new block contents 
     173                                                if (e.keyCode == 13 && !e.shiftKey && ed.selection.isCollapsed() && s.keep_styles) 
     174                                                        t._previousFormats = cloneFormats(ed.selection.getStart()); 
     175                                        }); 
     176 
     177                                        ed.onKeyUp.add(function(ed, e) { 
     178                                                // Let IE break the element and the wrap the new caret location in the previous formats 
     179                                                if (e.keyCode == 13 && !e.shiftKey) { 
     180                                                        var parent = ed.selection.getStart(), fmt = t._previousFormats; 
     181 
     182                                                        // Parent is an empty block 
     183                                                        if (!parent.hasChildNodes()) { 
     184                                                                parent = dom.getParent(parent, dom.isBlock); 
     185 
     186                                                                if (parent) { 
     187                                                                        parent.innerHTML = ''; 
     188         
     189                                                                        if (t._previousFormats) { 
     190                                                                                parent.appendChild(fmt.wrapper); 
     191                                                                                fmt.inner.innerHTML = '\uFEFF'; 
     192                                                                        } else 
     193                                                                                parent.innerHTML = '\uFEFF'; 
     194 
     195                                                                        selection.select(parent, 1); 
     196                                                                        ed.getDoc().execCommand('Delete', false, null); 
     197                                                                } 
     198                                                        } 
     199                                                } 
     200                                        }); 
     201                                } 
    138202 
    139203                                if (isGecko) { 
     
    637701 
    638702                backspaceDelete : function(e, bs) { 
    639                         var t = this, ed = t.editor, b = ed.getBody(), dom = ed.dom, n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n, w, tn; 
     703                        var t = this, ed = t.editor, b = ed.getBody(), dom = ed.dom, n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n, w, tn, walker; 
     704 
     705                        // Delete when caret is behind a element doesn't work correctly on Gecko see #3011651 
     706                        if (!bs && r.collapsed && sc.nodeType == 1 && r.startOffset == sc.childNodes.length) { 
     707                                walker = new tinymce.dom.TreeWalker(sc.lastChild, sc); 
     708 
     709                                // Walk the dom backwards until we find a text node 
     710                                for (n = sc.lastChild; n; n = walker.prev()) { 
     711                                        if (n.nodeType == 3) { 
     712                                                r.setStart(n, n.nodeValue.length); 
     713                                                r.collapse(true); 
     714                                                se.setRng(r); 
     715                                                return; 
     716                                        } 
     717                                } 
     718                        } 
    640719 
    641720                        // The caret sometimes gets stuck in Gecko if you delete empty paragraphs 
     
    668747                                } 
    669748                        } 
    670  
    671                         // Gecko generates BR elements here and there, we don't like those so lets remove them 
    672                         function handler(e) { 
    673                                 var pr; 
    674  
    675                                 e = e.target; 
    676  
    677                                 // A new BR was created in a block element, remove it 
    678                                 if (e && e.parentNode && e.nodeName == 'BR' && (n = t.getParentBlock(e))) { 
    679                                         pr = e.previousSibling; 
    680  
    681                                         Event.remove(b, 'DOMNodeInserted', handler); 
    682  
    683                                         // Is there whitespace at the end of the node before then we might need the pesky BR 
    684                                         // to place the caret at a correct location see bug: #2013943 
    685                                         if (pr && pr.nodeType == 3 && /\s+$/.test(pr.nodeValue)) 
    686                                                 return; 
    687  
    688                                         // Only remove BR elements that got inserted in the middle of the text 
    689                                         if (e.previousSibling || e.nextSibling) 
    690                                                 ed.dom.remove(e); 
    691                                 } 
    692                         }; 
    693  
    694                         // Listen for new nodes 
    695                         Event._add(b, 'DOMNodeInserted', handler); 
    696  
    697                         // Remove listener 
    698                         window.setTimeout(function() { 
    699                                 Event._remove(b, 'DOMNodeInserted', handler); 
    700                         }, 1); 
    701749                } 
    702750        }); 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/Formatter.js

    r7493 r7729  
    143143                                if (container.nodeType == 1 || container.nodeValue === "") { 
    144144                                        container = container.nodeType == 1 ? container.childNodes[offset] : container; 
    145                                         walker = new TreeWalker(container, container.parentNode); 
    146                                         for (node = walker.current(); node; node = walker.next()) { 
    147                                                 if (node.nodeType == 3 && !isBlock(node.parentNode) && !isWhiteSpaceNode(node)) { 
    148                                                         rng.setStart(node, 0); 
    149                                                         break; 
     145 
     146                                        // Might fail if the offset is behind the last element in it's container 
     147                                        if (container) { 
     148                                                walker = new TreeWalker(container, container.parentNode); 
     149                                                for (node = walker.current(); node; node = walker.next()) { 
     150                                                        if (node.nodeType == 3 && !isWhiteSpaceNode(node)) { 
     151                                                                rng.setStart(node, 0); 
     152                                                                break; 
     153                                                        } 
    150154                                                } 
    151155                                        } 
     
    356360                                        rng.setEndAfter(node); 
    357361 
    358                                         applyRngStyle(rng); 
     362                                        applyRngStyle(expandRng(rng, formatList)); 
    359363                                } else { 
    360364                                        if (!selection.isCollapsed() || !format.inline) { 
     
    865869 
    866870                function isWhiteSpaceNode(node) { 
    867                         return node && node.nodeType === 3 && /^\s*$/.test(node.nodeValue); 
     871                        return node && node.nodeType === 3 && /^([\s\r\n]+|)$/.test(node.nodeValue); 
    868872                }; 
    869873 
     
    14971501                                                                                textNode = node.firstChild; 
    14981502 
    1499                                                                                 perform(node); 
    1500  
    1501                                                                                 rng = dom.createRng(); 
    1502                                                                                 rng.setStart(textNode, textNode.nodeValue.length); 
    1503                                                                                 rng.setEnd(textNode, textNode.nodeValue.length); 
    1504                                                                                 selection.setRng(rng); 
    1505                                                                                 ed.nodeChanged(); 
     1503                                                                                if (textNode) { 
     1504                                                                                        perform(node); 
     1505 
     1506                                                                                        rng = dom.createRng(); 
     1507                                                                                        rng.setStart(textNode, textNode.nodeValue.length); 
     1508                                                                                        rng.setEnd(textNode, textNode.nodeValue.length); 
     1509                                                                                        selection.setRng(rng); 
     1510                                                                                        ed.nodeChanged(); 
     1511                                                                                } else 
     1512                                                                                        dom.remove(node); 
    15061513                                                                        } 
    15071514                                                                }); 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/dom/Selection.js

    r7493 r7729  
    171171                 */ 
    172172                getStart : function() { 
    173                         var t = this, r = t.getRng(), e; 
    174  
    175                         if (r.duplicate || r.item) { 
    176                                 if (r.item) 
    177                                         return r.item(0); 
    178  
    179                                 r = r.duplicate(); 
    180                                 r.collapse(1); 
    181                                 e = r.parentElement(); 
    182  
    183                                 if (e && e.nodeName == 'BODY') 
    184                                         return e.firstChild || e; 
    185  
    186                                 return e; 
     173                        var rng = this.getRng(), startElement, parentElement, checkRng, node; 
     174 
     175                        if (rng.duplicate || rng.item) { 
     176                                // Control selection, return first item 
     177                                if (rng.item) 
     178                                        return rng.item(0); 
     179 
     180                                // Get start element 
     181                                checkRng = rng.duplicate(); 
     182                                checkRng.collapse(1); 
     183                                startElement = checkRng.parentElement(); 
     184 
     185                                // Check if range parent is inside the start element, then return the inner parent element 
     186                                // This will fix issues when a single element is selected, IE would otherwise return the wrong start element 
     187                                parentElement = node = rng.parentElement(); 
     188                                while (node = node.parentNode) { 
     189                                        if (node == startElement) { 
     190                                                startElement = parentElement; 
     191                                                break; 
     192                                        } 
     193                                } 
     194 
     195                                // If start element is body element try to move to the first child if it exists 
     196                                if (startElement && startElement.nodeName == 'BODY') 
     197                                        return startElement.firstChild || startElement; 
     198 
     199                                return startElement; 
    187200                        } else { 
    188                                 e = r.startContainer; 
    189  
    190                                 if (e.nodeType == 1 && e.hasChildNodes()) 
    191                                         e = e.childNodes[Math.min(e.childNodes.length - 1, r.startOffset)]; 
    192  
    193                                 if (e && e.nodeType == 3) 
    194                                         return e.parentNode; 
    195  
    196                                 return e; 
     201                                startElement = rng.startContainer; 
     202 
     203                                if (startElement.nodeType == 1 && startElement.hasChildNodes()) 
     204                                        startElement = startElement.childNodes[Math.min(startElement.childNodes.length - 1, rng.startOffset)]; 
     205 
     206                                if (startElement && startElement.nodeType == 3) 
     207                                        return startElement.parentNode; 
     208 
     209                                return startElement; 
    197210                        } 
    198211                }, 
     
    375388 
    376389                                        function setEndPoint(start) { 
    377                                                 var point = bookmark[start ? 'start' : 'end'], i, node, offset; 
     390                                                var point = bookmark[start ? 'start' : 'end'], i, node, offset, children; 
    378391 
    379392                                                if (point) { 
    380393                                                        // Find container node 
    381                                                         for (node = root, i = point.length - 1; i >= 1; i--) 
    382                                                                 node = node.childNodes[point[i]]; 
     394                                                        for (node = root, i = point.length - 1; i >= 1; i--) { 
     395                                                                children = node.childNodes; 
     396 
     397                                                                if (children.length) 
     398                                                                        node = children[point[i]]; 
     399                                                        } 
    383400 
    384401                                                        // Set offset within container node 
     
    405422                                                                        idx = dom.nodeIndex(marker); 
    406423                                                                } else { 
    407                                                                         node = marker; 
     424                                                                        node = marker.firstChild; 
    408425                                                                        idx = 1; 
    409426                                                                } 
     
    415432                                                                        idx = dom.nodeIndex(marker); 
    416433                                                                } else { 
    417                                                                         node = marker; 
     434                                                                        node = marker.firstChild; 
    418435                                                                        idx = 1; 
    419436                                                                } 
     
    456473                                        }; 
    457474 
     475                                        function addBogus(node) { 
     476                                                // Adds a bogus BR element for empty block elements 
     477                                                // on non IE browsers just to have a place to put the caret 
     478                                                if (!isIE && dom.isBlock(node) && !node.innerHTML) 
     479                                                        node.innerHTML = '<br _mce_bogus="1" />'; 
     480 
     481                                                return node; 
     482                                        }; 
     483 
    458484                                        // Restore start/end points 
    459485                                        restoreEndPoint('start'); 
     
    461487 
    462488                                        rng = dom.createRng(); 
    463                                         rng.setStart(startContainer, startOffset); 
    464                                         rng.setEnd(endContainer, endOffset); 
     489                                        rng.setStart(addBogus(startContainer), startOffset); 
     490                                        rng.setEnd(addBogus(endContainer), endOffset); 
    465491                                        t.setRng(rng); 
    466492                                } else if (bookmark.name) { 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/dom/Sizzle.js

    r5654 r7729  
    99(function(){ 
    1010 
    11 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g, 
     11var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, 
    1212        done = 0, 
    1313        toString = Object.prototype.toString, 
    14         hasDuplicate = false; 
     14        hasDuplicate = false, 
     15        baseHasDuplicate = true; 
     16 
     17// Here we check if the JavaScript engine is using some sort of 
     18// optimization where it does not always call our comparision 
     19// function. If that is the case, discard the hasDuplicate value. 
     20//   Thus far that includes Google Chrome. 
     21[0, 0].sort(function(){ 
     22        baseHasDuplicate = false; 
     23        return 0; 
     24}); 
    1525 
    1626var Sizzle = function(selector, context, results, seed) { 
    1727        results = results || []; 
    18         var origContext = context = context || document; 
     28        context = context || document; 
     29 
     30        var origContext = context; 
    1931 
    2032        if ( context.nodeType !== 1 && context.nodeType !== 9 ) { 
     
    2638        } 
    2739 
    28         var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context); 
     40        var parts = [], m, set, checkSet, extra, prune = true, contextXML = Sizzle.isXML(context), 
     41                soFar = selector, ret, cur, pop, i; 
    2942         
    3043        // Reset the position of the chunker regexp (start from head) 
    31         chunker.lastIndex = 0; 
    32          
    33         while ( (m = chunker.exec(selector)) !== null ) { 
    34                 parts.push( m[1] ); 
     44        do { 
     45                chunker.exec(""); 
     46                m = chunker.exec(soFar); 
     47 
     48                if ( m ) { 
     49                        soFar = m[3]; 
    3550                 
    36                 if ( m[2] ) { 
    37                         extra = RegExp.rightContext; 
    38                         break; 
    39                 } 
    40         } 
     51                        parts.push( m[1] ); 
     52                 
     53                        if ( m[2] ) { 
     54                                extra = m[3]; 
     55                                break; 
     56                        } 
     57                } 
     58        } while ( m ); 
    4159 
    4260        if ( parts.length > 1 && origPOS.exec( selector ) ) { 
     
    5169                                selector = parts.shift(); 
    5270 
    53                                 if ( Expr.relative[ selector ] ) 
     71                                if ( Expr.relative[ selector ] ) { 
    5472                                        selector += parts.shift(); 
    55  
     73                                } 
     74                                 
    5675                                set = posProcess( selector, set ); 
    5776                        } 
     
    6281                if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && 
    6382                                Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { 
    64                         var ret = Sizzle.find( parts.shift(), context, contextXML ); 
     83                        ret = Sizzle.find( parts.shift(), context, contextXML ); 
    6584                        context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; 
    6685                } 
    6786 
    6887                if ( context ) { 
    69                         var ret = seed ? 
     88                        ret = seed ? 
    7089                                { expr: parts.pop(), set: makeArray(seed) } : 
    7190                                Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); 
     
    7998 
    8099                        while ( parts.length ) { 
    81                                 var cur = parts.pop(), pop = cur; 
     100                                cur = parts.pop(); 
     101                                pop = cur; 
    82102 
    83103                                if ( !Expr.relative[ cur ] ) { 
     
    103123 
    104124        if ( !checkSet ) { 
    105                 throw "Syntax error, unrecognized expression: " + (cur || selector); 
     125                Sizzle.error( cur || selector ); 
    106126        } 
    107127 
     
    110130                        results.push.apply( results, checkSet ); 
    111131                } else if ( context && context.nodeType === 1 ) { 
    112                         for ( var i = 0; checkSet[i] != null; i++ ) { 
    113                                 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { 
     132                        for ( i = 0; checkSet[i] != null; i++ ) { 
     133                                if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { 
    114134                                        results.push( set[i] ); 
    115135                                } 
    116136                        } 
    117137                } else { 
    118                         for ( var i = 0; checkSet[i] != null; i++ ) { 
     138                        for ( i = 0; checkSet[i] != null; i++ ) { 
    119139                                if ( checkSet[i] && checkSet[i].nodeType === 1 ) { 
    120140                                        results.push( set[i] ); 
     
    136156Sizzle.uniqueSort = function(results){ 
    137157        if ( sortOrder ) { 
    138                 hasDuplicate = false; 
     158                hasDuplicate = baseHasDuplicate; 
    139159                results.sort(sortOrder); 
    140160 
     
    147167                } 
    148168        } 
     169 
     170        return results; 
    149171}; 
    150172 
     
    154176 
    155177Sizzle.find = function(expr, context, isXML){ 
    156         var set, match; 
     178        var set; 
    157179 
    158180        if ( !expr ) { 
     
    163185                var type = Expr.order[i], match; 
    164186                 
    165                 if ( (match = Expr.match[ type ].exec( expr )) ) { 
    166                         var left = RegExp.leftContext; 
     187                if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { 
     188                        var left = match[1]; 
     189                        match.splice(1,1); 
    167190 
    168191                        if ( left.substr( left.length - 1 ) !== "\\" ) { 
     
    186209Sizzle.filter = function(expr, set, inplace, not){ 
    187210        var old = expr, result = [], curLoop = set, match, anyFound, 
    188                 isXMLFilter = set && set[0] && isXML(set[0]); 
     211                isXMLFilter = set && set[0] && Sizzle.isXML(set[0]); 
    189212 
    190213        while ( expr && set.length ) { 
    191214                for ( var type in Expr.filter ) { 
    192                         if ( (match = Expr.match[ type ].exec( expr )) != null ) { 
    193                                 var filter = Expr.filter[ type ], found, item; 
     215                        if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { 
     216                                var filter = Expr.filter[ type ], found, item, left = match[1]; 
    194217                                anyFound = false; 
    195218 
    196                                 if ( curLoop == result ) { 
     219                                match.splice(1,1); 
     220 
     221                                if ( left.substr( left.length - 1 ) === "\\" ) { 
     222                                        continue; 
     223                                } 
     224 
     225                                if ( curLoop === result ) { 
    197226                                        result = []; 
    198227                                } 
     
    245274 
    246275                // Improper expression 
    247                 if ( expr == old ) { 
     276                if ( expr === old ) { 
    248277                        if ( anyFound == null ) { 
    249                                 throw "Syntax error, unrecognized expression: " + expr; 
     278                                Sizzle.error( expr ); 
    250279                        } else { 
    251280                                break; 
     
    257286 
    258287        return curLoop; 
     288}; 
     289 
     290Sizzle.error = function( msg ) { 
     291        throw "Syntax error, unrecognized expression: " + msg; 
    259292}; 
    260293 
     
    262295        order: [ "ID", "NAME", "TAG" ], 
    263296        match: { 
    264                 ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, 
    265                 CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, 
    266                 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/, 
    267                 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, 
    268                 TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/, 
    269                 CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, 
    270                 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, 
    271                 PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/ 
     297                ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, 
     298                CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, 
     299                NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, 
     300                ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, 
     301                TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, 
     302                CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/, 
     303                POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, 
     304                PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ 
    272305        }, 
     306        leftMatch: {}, 
    273307        attrMap: { 
    274308                "class": "className", 
     
    281315        }, 
    282316        relative: { 
    283                 "+": function(checkSet, part, isXML){ 
     317                "+": function(checkSet, part){ 
    284318                        var isPartStr = typeof part === "string", 
    285319                                isTag = isPartStr && !/\W/.test(part), 
    286320                                isPartStrNotTag = isPartStr && !isTag; 
    287321 
    288                         if ( isTag && !isXML ) { 
    289                                 part = part.toUpperCase(); 
     322                        if ( isTag ) { 
     323                                part = part.toLowerCase(); 
    290324                        } 
    291325 
     
    294328                                        while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} 
    295329 
    296                                         checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ? 
     330                                        checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? 
    297331                                                elem || false : 
    298332                                                elem === part; 
     
    304338                        } 
    305339                }, 
    306                 ">": function(checkSet, part, isXML){ 
    307                         var isPartStr = typeof part === "string"; 
     340                ">": function(checkSet, part){ 
     341                        var isPartStr = typeof part === "string", 
     342                                elem, i = 0, l = checkSet.length; 
    308343 
    309344                        if ( isPartStr && !/\W/.test(part) ) { 
    310                                 part = isXML ? part : part.toUpperCase(); 
    311  
    312                                 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 
    313                                         var elem = checkSet[i]; 
     345                                part = part.toLowerCase(); 
     346 
     347                                for ( ; i < l; i++ ) { 
     348                                        elem = checkSet[i]; 
    314349                                        if ( elem ) { 
    315350                                                var parent = elem.parentNode; 
    316                                                 checkSet[i] = parent.nodeName === part ? parent : false; 
     351                                                checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; 
    317352                                        } 
    318353                                } 
    319354                        } else { 
    320                                 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 
    321                                         var elem = checkSet[i]; 
     355                                for ( ; i < l; i++ ) { 
     356                                        elem = checkSet[i]; 
    322357                                        if ( elem ) { 
    323358                                                checkSet[i] = isPartStr ? 
     
    333368                }, 
    334369                "": function(checkSet, part, isXML){ 
    335                         var doneName = done++, checkFn = dirCheck; 
    336  
    337                         if ( !part.match(/\W/) ) { 
    338                                 var nodeCheck = part = isXML ? part : part.toUpperCase(); 
     370                        var doneName = done++, checkFn = dirCheck, nodeCheck; 
     371 
     372                        if ( typeof part === "string" && !/\W/.test(part) ) { 
     373                                part = part.toLowerCase(); 
     374                                nodeCheck = part; 
    339375                                checkFn = dirNodeCheck; 
    340376                        } 
     
    343379                }, 
    344380                "~": function(checkSet, part, isXML){ 
    345                         var doneName = done++, checkFn = dirCheck; 
    346  
    347                         if ( typeof part === "string" && !part.match(/\W/) ) { 
    348                                 var nodeCheck = part = isXML ? part : part.toUpperCase(); 
     381                        var doneName = done++, checkFn = dirCheck, nodeCheck; 
     382 
     383                        if ( typeof part === "string" && !/\W/.test(part) ) { 
     384                                part = part.toLowerCase(); 
     385                                nodeCheck = part; 
    349386                                checkFn = dirNodeCheck; 
    350387                        } 
     
    360397                        } 
    361398                }, 
    362                 NAME: function(match, context, isXML){ 
     399                NAME: function(match, context){ 
    363400                        if ( typeof context.getElementsByName !== "undefined" ) { 
    364401                                var ret = [], results = context.getElementsByName(match[1]); 
     
    387424                        for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { 
    388425                                if ( elem ) { 
    389                                         if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) { 
    390                                                 if ( !inplace ) 
     426                                        if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) { 
     427                                                if ( !inplace ) { 
    391428                                                        result.push( elem ); 
     429                                                } 
    392430                                        } else if ( inplace ) { 
    393431                                                curLoop[i] = false; 
     
    402440                }, 
    403441                TAG: function(match, curLoop){ 
    404                         for ( var i = 0; curLoop[i] === false; i++ ){} 
    405                         return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase(); 
     442                        return match[1].toLowerCase(); 
    406443                }, 
    407444                CHILD: function(match){ 
    408                         if ( match[1] == "nth" ) { 
     445                        if ( match[1] === "nth" ) { 
    409446                                // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' 
    410447                                var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( 
    411                                         match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" || 
     448                                        match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || 
    412449                                        !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); 
    413450 
     
    438475                        if ( match[1] === "not" ) { 
    439476                                // If we're dealing with a complex expression, or a simple one 
    440                                 if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) { 
     477                                if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { 
    441478                                        match[3] = Sizzle(match[3], null, null, curLoop); 
    442479                                } else { 
     
    484521                }, 
    485522                header: function(elem){ 
    486                         return /h\d/i.test( elem.nodeName ); 
     523                        return (/h\d/i).test( elem.nodeName ); 
    487524                }, 
    488525                text: function(elem){ 
     
    511548                }, 
    512549                button: function(elem){ 
    513                         return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON"; 
     550                        return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; 
    514551                }, 
    515552                input: function(elem){ 
    516                         return /input|select|textarea|button/i.test(elem.nodeName); 
     553                        return (/input|select|textarea|button/i).test(elem.nodeName); 
    517554                } 
    518555        }, 
     
    537574                }, 
    538575                nth: function(elem, i, match){ 
    539                         return match[3] - 0 == i; 
     576                        return match[3] - 0 === i; 
    540577                }, 
    541578                eq: function(elem, i, match){ 
    542                         return match[3] - 0 == i; 
     579                        return match[3] - 0 === i; 
    543580                } 
    544581        }, 
     
    550587                                return filter( elem, i, match, array ); 
    551588                        } else if ( name === "contains" ) { 
    552                                 return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0; 
     589                                return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; 
    553590                        } else if ( name === "not" ) { 
    554591                                var not = match[3]; 
    555592 
    556                                 for ( var i = 0, l = not.length; i < l; i++ ) { 
    557                                         if ( not[i] === elem ) { 
     593                                for ( var j = 0, l = not.length; j < l; j++ ) { 
     594                                        if ( not[j] === elem ) { 
    558595                                                return false; 
    559596                                        } 
     
    561598 
    562599                                return true; 
     600                        } else { 
     601                                Sizzle.error( "Syntax error, unrecognized expression: " + name ); 
    563602                        } 
    564603                }, 
     
    568607                                case 'only': 
    569608                                case 'first': 
    570                                         while (node = node.previousSibling)  { 
    571                                                 if ( node.nodeType === 1 ) return false; 
    572                                         } 
    573                                         if ( type == 'first') return true; 
     609                                        while ( (node = node.previousSibling) )  { 
     610                                                if ( node.nodeType === 1 ) {  
     611                                                        return false;  
     612                                                } 
     613                                        } 
     614                                        if ( type === "first" ) {  
     615                                                return true;  
     616                                        } 
    574617                                        node = elem; 
    575618                                case 'last': 
    576                                         while (node = node.nextSibling)  { 
    577                                                 if ( node.nodeType === 1 ) return false; 
     619                                        while ( (node = node.nextSibling) )      { 
     620                                                if ( node.nodeType === 1 ) {  
     621                                                        return false;  
     622                                                } 
    578623                                        } 
    579624                                        return true; 
     
    581626                                        var first = match[2], last = match[3]; 
    582627 
    583                                         if ( first == 1 && last == 0 ) { 
     628                                        if ( first === 1 && last === 0 ) { 
    584629                                                return true; 
    585630                                        } 
     
    599644                                         
    600645                                        var diff = elem.nodeIndex - last; 
    601                                         if ( first == 0 ) { 
    602                                                 return diff == 0; 
     646                                        if ( first === 0 ) { 
     647                                                return diff === 0; 
    603648                                        } else { 
    604                                                 return ( diff % first == 0 && diff / first >= 0 ); 
     649                                                return ( diff % first === 0 && diff / first >= 0 ); 
    605650                                        } 
    606651                        } 
     
    610655                }, 
    611656                TAG: function(elem, match){ 
    612                         return (match === "*" && elem.nodeType === 1) || elem.nodeName === match; 
     657                        return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; 
    613658                }, 
    614659                CLASS: function(elem, match){ 
     
    638683                                value && result !== false : 
    639684                                type === "!=" ? 
    640                                 value != check : 
     685                                value !== check : 
    641686                                type === "^=" ? 
    642687                                value.indexOf(check) === 0 : 
     
    657702}; 
    658703 
    659 var origPOS = Expr.match.POS; 
     704var origPOS = Expr.match.POS, 
     705        fescape = function(all, num){ 
     706                return "\\" + (num - 0 + 1); 
     707        }; 
    660708 
    661709for ( var type in Expr.match ) { 
    662         Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); 
     710        Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); 
     711        Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); 
    663712} 
    664713 
    665714var makeArray = function(array, results) { 
    666         array = Array.prototype.slice.call( array ); 
     715        array = Array.prototype.slice.call( array, 0 ); 
    667716 
    668717        if ( results ) { 
     
    676725// Perform a simple check to determine if the browser is capable of 
    677726// converting a NodeList to an array using builtin methods. 
     727// Also verifies that the returned array holds DOM nodes 
     728// (which is not the case in the Blackberry browser) 
    678729try { 
    679         Array.prototype.slice.call( document.documentElement.childNodes ); 
     730        Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; 
    680731 
    681732// Provide a fallback method if it does not work 
    682733} catch(e){ 
    683734        makeArray = function(array, results) { 
    684                 var ret = results || []; 
     735                var ret = results || [], i = 0; 
    685736 
    686737                if ( toString.call(array) === "[object Array]" ) { 
     
    688739                } else { 
    689740                        if ( typeof array.length === "number" ) { 
    690                                 for ( var i = 0, l = array.length; i < l; i++ ) { 
     741                                for ( var l = array.length; i < l; i++ ) { 
    691742                                        ret.push( array[i] ); 
    692743                                } 
    693744                        } else { 
    694                                 for ( var i = 0; array[i]; i++ ) { 
     745                                for ( ; array[i]; i++ ) { 
    695746                                        ret.push( array[i] ); 
    696747                                } 
     
    706757if ( document.documentElement.compareDocumentPosition ) { 
    707758        sortOrder = function( a, b ) { 
     759                if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { 
     760                        if ( a == b ) { 
     761                                hasDuplicate = true; 
     762                        } 
     763                        return a.compareDocumentPosition ? -1 : 1; 
     764                } 
     765 
    708766                var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; 
    709767                if ( ret === 0 ) { 
     
    714772} else if ( "sourceIndex" in document.documentElement ) { 
    715773        sortOrder = function( a, b ) { 
     774                if ( !a.sourceIndex || !b.sourceIndex ) { 
     775                        if ( a == b ) { 
     776                                hasDuplicate = true; 
     777                        } 
     778                        return a.sourceIndex ? -1 : 1; 
     779                } 
     780 
    716781                var ret = a.sourceIndex - b.sourceIndex; 
    717782                if ( ret === 0 ) { 
     
    722787} else if ( document.createRange ) { 
    723788        sortOrder = function( a, b ) { 
     789                if ( !a.ownerDocument || !b.ownerDocument ) { 
     790                        if ( a == b ) { 
     791                                hasDuplicate = true; 
     792                        } 
     793                        return a.ownerDocument ? -1 : 1; 
     794                } 
     795 
    724796                var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); 
    725797                aRange.setStart(a, 0); 
     
    735807} 
    736808 
     809// Utility function for retreiving the text value of an array of DOM nodes 
     810Sizzle.getText = function( elems ) { 
     811        var ret = "", elem; 
     812 
     813        for ( var i = 0; elems[i]; i++ ) { 
     814                elem = elems[i]; 
     815 
     816                // Get the text from text nodes and CDATA nodes 
     817                if ( elem.nodeType === 3 || elem.nodeType === 4 ) { 
     818                        ret += elem.nodeValue; 
     819 
     820                // Traverse everything else, except comment nodes 
     821                } else if ( elem.nodeType !== 8 ) { 
     822                        ret += Sizzle.getText( elem.childNodes ); 
     823                } 
     824        } 
     825 
     826        return ret; 
     827}; 
     828 
    737829// Check to see if the browser returns elements by name when 
    738830// querying by getElementById (and provide a workaround) 
     
    740832        // We're going to inject a fake input element with a specified name 
    741833        var form = document.createElement("div"), 
    742                 id = "script" + (new Date).getTime(); 
     834                id = "script" + (new Date()).getTime(); 
    743835        form.innerHTML = "<a name='" + id + "'/>"; 
    744836 
     
    749841        // The workaround has to do additional checks after a getElementById 
    750842        // Which slows things down for other browsers (hence the branching) 
    751         if ( !!document.getElementById( id ) ) { 
     843        if ( document.getElementById( id ) ) { 
    752844                Expr.find.ID = function(match, context, isXML){ 
    753845                        if ( typeof context.getElementById !== "undefined" && !isXML ) { 
     
    764856 
    765857        root.removeChild( form ); 
     858        root = form = null; // release memory in IE 
    766859})(); 
    767860 
     
    804897                }; 
    805898        } 
     899 
     900        div = null; // release memory in IE 
    806901})(); 
    807902 
    808 if ( document.querySelectorAll ) (function(){ 
    809         var oldSizzle = Sizzle, div = document.createElement("div"); 
    810         div.innerHTML = "<p class='TEST'></p>"; 
    811  
    812         // Safari can't handle uppercase or unicode characters when 
    813         // in quirks mode. 
    814         if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { 
     903if ( document.querySelectorAll ) { 
     904        (function(){ 
     905                var oldSizzle = Sizzle, div = document.createElement("div"); 
     906                div.innerHTML = "<p class='TEST'></p>"; 
     907 
     908                // Safari can't handle uppercase or unicode characters when 
     909                // in quirks mode. 
     910                if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { 
     911                        return; 
     912                } 
     913         
     914                Sizzle = function(query, context, extra, seed){ 
     915                        context = context || document; 
     916 
     917                        // Only use querySelectorAll on non-XML documents 
     918                        // (ID selectors don't work in non-HTML documents) 
     919                        if ( !seed && context.nodeType === 9 && !Sizzle.isXML(context) ) { 
     920                                try { 
     921                                        return makeArray( context.querySelectorAll(query), extra ); 
     922                                } catch(e){} 
     923                        } 
     924                 
     925                        return oldSizzle(query, context, extra, seed); 
     926                }; 
     927 
     928                for ( var prop in oldSizzle ) { 
     929                        Sizzle[ prop ] = oldSizzle[ prop ]; 
     930                } 
     931 
     932                div = null; // release memory in IE 
     933        })(); 
     934} 
     935 
     936(function(){ 
     937        var div = document.createElement("div"); 
     938 
     939        div.innerHTML = "<div class='test e'></div><div class='test'></div>"; 
     940 
     941        // Opera can't find a second classname (in 9.6) 
     942        // Also, make sure that getElementsByClassName actually exists 
     943        if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { 
    815944                return; 
    816945        } 
    817          
    818         Sizzle = function(query, context, extra, seed){ 
    819                 context = context || document; 
    820  
    821                 // Only use querySelectorAll on non-XML documents 
    822                 // (ID selectors don't work in non-HTML documents) 
    823                 if ( !seed && context.nodeType === 9 && !isXML(context) ) { 
    824                         try { 
    825                                 return makeArray( context.querySelectorAll(query), extra ); 
    826                         } catch(e){} 
    827                 } 
    828                  
    829                 return oldSizzle(query, context, extra, seed); 
    830         }; 
    831  
    832         for ( var prop in oldSizzle ) { 
    833                 Sizzle[ prop ] = oldSizzle[ prop ]; 
    834         } 
    835 })(); 
    836  
    837 if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){ 
    838         var div = document.createElement("div"); 
    839         div.innerHTML = "<div class='test e'></div><div class='test'></div>"; 
    840  
    841         // Opera can't find a second classname (in 9.6) 
    842         if ( div.getElementsByClassName("e").length === 0 ) 
    843                 return; 
    844946 
    845947        // Safari caches class attributes, doesn't catch changes (in 3.2) 
    846948        div.lastChild.className = "e"; 
    847949 
    848         if ( div.getElementsByClassName("e").length === 1 ) 
     950        if ( div.getElementsByClassName("e").length === 1 ) { 
    849951                return; 
    850  
     952        } 
     953         
    851954        Expr.order.splice(1, 0, "CLASS"); 
    852955        Expr.find.CLASS = function(match, context, isXML) { 
     
    855958                } 
    856959        }; 
     960 
     961        div = null; // release memory in IE 
    857962})(); 
    858963 
    859964function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 
    860         var sibDir = dir == "previousSibling" && !isXML; 
    861965        for ( var i = 0, l = checkSet.length; i < l; i++ ) { 
    862966                var elem = checkSet[i]; 
    863967                if ( elem ) { 
    864                         if ( sibDir && elem.nodeType === 1 ){ 
    865                                 elem.sizcache = doneName; 
    866                                 elem.sizset = i; 
    867                         } 
    868968                        elem = elem[dir]; 
    869969                        var match = false; 
     
    880980                                } 
    881981 
    882                                 if ( elem.nodeName === cur ) { 
     982                                if ( elem.nodeName.toLowerCase() === cur ) { 
    883983                                        match = elem; 
    884984                                        break; 
     
    894994 
    895995function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 
    896         var sibDir = dir == "previousSibling" && !isXML; 
    897996        for ( var i = 0, l = checkSet.length; i < l; i++ ) { 
    898997                var elem = checkSet[i]; 
    899998                if ( elem ) { 
    900                         if ( sibDir && elem.nodeType === 1 ) { 
    901                                 elem.sizcache = doneName; 
    902                                 elem.sizset = i; 
    903                         } 
    904999                        elem = elem[dir]; 
    9051000                        var match = false; 
     
    9361031} 
    9371032 
    938 var contains = document.compareDocumentPosition ? function(a, b){ 
    939         return a.compareDocumentPosition(b) & 16; 
     1033Sizzle.contains = document.compareDocumentPosition ? function(a, b){ 
     1034        return !!(a.compareDocumentPosition(b) & 16); 
    9401035} : function(a, b){ 
    9411036        return a !== b && (a.contains ? a.contains(b) : true); 
    9421037}; 
    9431038 
    944 var isXML = function(elem){ 
    945         return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || 
    946                 !!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML"; 
     1039Sizzle.isXML = function(elem){ 
     1040        // documentElement is verified for cases where it doesn't yet exist 
     1041        // (such as loading iframes in IE - #4833)  
     1042        var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; 
     1043        return documentElement ? documentElement.nodeName !== "HTML" : false; 
    9471044}; 
    9481045 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/dom/TridentSelection.js

    r7493 r7729  
    4242                                marker = dom.create('a'); 
    4343                                parent = checkRng.parentElement(); 
     44 
     45                                // If parent doesn't have any children then set the container to that parent and the index to 0 
     46                                if (!parent.hasChildNodes()) { 
     47                                        domRange[start ? 'setStart' : 'setEnd'](parent, 0); 
     48                                        return; 
     49                                } 
     50 
    4451                                parent.appendChild(marker); 
    4552                                checkRng.moveToElementText(marker); 
     
    216223                                ieRng.moveToElementText(marker); 
    217224                                marker.parentNode.removeChild(marker); 
    218                                 ieRng.move('character', so); 
     225 
     226                                // Move if we need to, moving it 0 characters actually moves it! 
     227                                if (so > 0) 
     228                                        ieRng.move('character', so); 
    219229                        } else { 
    220230                                ieRng.moveToElementText(sc); 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/ui/ListBox.js

    r6655 r7729  
    317317 
    318318                        Event.add(t.id, 'click', t.showMenu, t); 
    319                         Event.add(t.id + '_text', 'focus', function(e) { 
     319                        Event.add(t.id + '_text', 'focus', function() { 
    320320                                if (!t._focused) { 
    321321                                        t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) { 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/plugins/contextmenu/editor_plugin_src.js

    r7398 r7729  
    4848 
    4949                                        t._getMenu(ed).showMenu(e.clientX, e.clientY); 
    50                                         Event.add(ed.getDoc(), 'click', hide); 
     50                                        Event.add(ed.getDoc(), 'click', function(e) { 
     51                                                hide(ed, e); 
     52                                        }); 
    5153                                        Event.cancel(e); 
    5254                                } 
     55                        }); 
     56 
     57                        ed.onRemove.add(function() { 
     58                                if (t._menu) 
     59                                        t._menu.removeAll(); 
    5360                        }); 
    5461 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/plugins/fullpage/editor_plugin_src.js

    r7229 r7729  
    8686                        var t = this, sp, ep, c = o.content, v, st = ''; 
    8787 
     88                        // Ignore raw updated if we already have a head, this will fix issues with undo/redo keeping the head/foot separate 
     89                        if (o.format == 'raw' && t.head) 
     90                                return; 
     91 
    8892                        if (o.source_view && ed.getParam('fullpage_hide_in_source_view')) 
    8993                                return; 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/plugins/fullscreen/editor_plugin_src.js

    r7493 r7729  
    120120 
    121121                                                // Get outer/inner size to get a delta size that can be used to calc the new iframe size 
    122                                                 outerSize = fed.dom.getSize(fed.getContainer()); 
     122                                                outerSize = fed.dom.getSize(fed.getContainer().firstChild); 
    123123                                                innerSize = fed.dom.getSize(fed.getContainer().getElementsByTagName('iframe')[0]); 
    124124 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/plugins/spellchecker/editor_plugin_src.js

    r7398 r7729  
    262262 
    263263                _showMenu : function(ed, e) { 
    264                         var t = this, ed = t.editor, m = t._menu, p1, dom = ed.dom, vp = dom.getViewPort(ed.getWin()); 
     264                        var t = this, ed = t.editor, m = t._menu, p1, dom = ed.dom, vp = dom.getViewPort(ed.getWin()), wordSpan = e.target; 
     265 
     266                        e = 0; // Fixes IE memory leak 
    265267 
    266268                        if (!m) { 
     
    277279                        } 
    278280 
    279                         if (dom.hasClass(e.target, 'mceItemHiddenSpellWord')) { 
     281                        if (dom.hasClass(wordSpan, 'mceItemHiddenSpellWord')) { 
    280282                                m.removeAll(); 
    281283                                m.add({title : 'spellchecker.wait', 'class' : 'mceMenuItemTitle'}).setDisabled(1); 
    282284 
    283                                 t._sendRPC('getSuggestions', [t.selectedLang, dom.decode(e.target.innerHTML)], function(r) { 
     285                                t._sendRPC('getSuggestions', [t.selectedLang, dom.decode(wordSpan.innerHTML)], function(r) { 
    284286                                        var ignoreRpc; 
    285287 
     
    290292                                                each(r, function(v) { 
    291293                                                        m.add({title : v, onclick : function() { 
    292                                                                 dom.replace(ed.getDoc().createTextNode(v), e.target); 
     294                                                                dom.replace(ed.getDoc().createTextNode(v), wordSpan); 
    293295                                                                t._checkDone(); 
    294296                                                        }}); 
     
    303305                                                title : 'spellchecker.ignore_word', 
    304306                                                onclick : function() { 
    305                                                         var word = e.target.innerHTML; 
    306  
    307                                                         dom.remove(e.target, 1); 
     307                                                        var word = wordSpan.innerHTML; 
     308 
     309                                                        dom.remove(wordSpan, 1); 
    308310                                                        t._checkDone(); 
    309311 
     
    321323                                                title : 'spellchecker.ignore_words', 
    322324                                                onclick : function() { 
    323                                                         var word = e.target.innerHTML; 
     325                                                        var word = wordSpan.innerHTML; 
    324326 
    325327                                                        t._removeWords(dom.decode(word)); 
     
    341343                                                        title : 'spellchecker.learn_word', 
    342344                                                        onclick : function() { 
    343                                                                 var word = e.target.innerHTML; 
    344  
    345                                                                 dom.remove(e.target, 1); 
     345                                                                var word = wordSpan.innerHTML; 
     346 
     347                                                                dom.remove(wordSpan, 1); 
    346348                                                                t._checkDone(); 
    347349 
     
    357359                                }); 
    358360 
    359                                 ed.selection.select(e.target); 
    360                                 p1 = dom.getPos(e.target); 
    361                                 m.showMenu(p1.x, p1.y + e.target.offsetHeight - vp.y); 
     361                                ed.selection.select(wordSpan); 
     362                                p1 = dom.getPos(wordSpan); 
     363                                m.showMenu(p1.x, p1.y + wordSpan.offsetHeight - vp.y); 
    362364 
    363365                                return tinymce.dom.Event.cancel(e); 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/plugins/table/js/table.js

    r7230 r7729  
    317317                dir = dom.getAttrib(elm, 'dir'); 
    318318                lang = dom.getAttrib(elm, 'lang'); 
    319                 background = getStyle(elm, 'background', 'backgroundImage').replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1"); 
     319                background = getStyle(elm, 'background', 'backgroundImage').replace(new RegExp("url\\(['\"]?([^'\"]*)['\"]?\\)", 'gi'), "$1"); 
    320320                formObj.caption.checked = elm.getElementsByTagName('caption').length > 0; 
    321321 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/themes/advanced/editor_template_src.js

    r7493 r7729  
    227227 
    228228                                        ed.focus(); 
     229                                        ed.undoManager.add(); 
    229230 
    230231                                        // Toggle off the current format 
     
    234235                                        else 
    235236                                                ed.formatter.apply(name); 
     237 
     238                                        ed.undoManager.add(); 
     239                                        ed.nodeChanged(); 
    236240 
    237241                                        return false; // No auto select 
     
    298302                                onselect : function(v) { 
    299303                                        ed.execCommand('FontName', false, v); 
     304 
     305                                        // Fake selection, execCommand will fire a nodeChange and update the selection 
     306                                        c.select(function(sv) { 
     307                                                return v == sv; 
     308                                        }); 
     309 
    300310                                        return false; // No auto select 
    301311                                } 
     
    317327                                if (v['class']) { 
    318328                                        ed.focus(); 
     329                                        ed.undoManager.add(); 
    319330                                        ed.formatter.toggle('fontsize_class', {value : v['class']}); 
     331                                        ed.undoManager.add(); 
     332                                        ed.nodeChanged(); 
    320333                                } else 
    321334                                        ed.execCommand('FontSize', false, v.fontSize); 
     335 
     336                                // Fake selection, execCommand will fire a nodeChange and update the selection 
     337                                c.select(function(sv) { 
     338                                        return v == sv; 
     339                                }); 
    322340 
    323341                                return false; // No auto select 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/tiny_mce_jquery_src.js

    r7493 r7729  
    66                majorVersion : '3', 
    77 
    8                 minorVersion : '3.6', 
    9  
    10                 releaseDate : '2010-05-20', 
     8                minorVersion : '3.7', 
     9 
     10                releaseDate : '2010-06-10', 
    1111 
    1212                _init : function() { 
     
    35313531                                marker = dom.create('a'); 
    35323532                                parent = checkRng.parentElement(); 
     3533 
     3534                                // If parent doesn't have any children then set the container to that parent and the index to 0 
     3535                                if (!parent.hasChildNodes()) { 
     3536                                        domRange[start ? 'setStart' : 'setEnd'](parent, 0); 
     3537                                        return; 
     3538                                } 
     3539 
    35333540                                parent.appendChild(marker); 
    35343541                                checkRng.moveToElementText(marker); 
     
    37053712                                ieRng.moveToElementText(marker); 
    37063713                                marker.parentNode.removeChild(marker); 
    3707                                 ieRng.move('character', so); 
     3714 
     3715                                // Move if we need to, moving it 0 characters actually moves it! 
     3716                                if (so > 0) 
     3717                                        ieRng.move('character', so); 
    37083718                        } else { 
    37093719                                ieRng.moveToElementText(sc); 
     
    43754385 
    43764386                getStart : function() { 
    4377                         var t = this, r = t.getRng(), e; 
    4378  
    4379                         if (r.duplicate || r.item) { 
    4380                                 if (r.item) 
    4381                                         return r.item(0); 
    4382  
    4383                                 r = r.duplicate(); 
    4384                                 r.collapse(1); 
    4385                                 e = r.parentElement(); 
    4386  
    4387                                 if (e && e.nodeName == 'BODY') 
    4388                                         return e.firstChild || e; 
    4389  
    4390                                 return e; 
     4387                        var rng = this.getRng(), startElement, parentElement, checkRng, node; 
     4388 
     4389                        if (rng.duplicate || rng.item) { 
     4390                                // Control selection, return first item 
     4391                                if (rng.item) 
     4392                                        return rng.item(0); 
     4393 
     4394                                // Get start element 
     4395                                checkRng = rng.duplicate(); 
     4396                                checkRng.collapse(1); 
     4397                                startElement = checkRng.parentElement(); 
     4398 
     4399                                // Check if range parent is inside the start element, then return the inner parent element 
     4400                                // This will fix issues when a single element is selected, IE would otherwise return the wrong start element 
     4401                                parentElement = node = rng.parentElement(); 
     4402                                while (node = node.parentNode) { 
     4403                                        if (node == startElement) { 
     4404                                                startElement = parentElement; 
     4405                                                break; 
     4406                                        } 
     4407                                } 
     4408 
     4409                                // If start element is body element try to move to the first child if it exists 
     4410                                if (startElement && startElement.nodeName == 'BODY') 
     4411                                        return startElement.firstChild || startElement; 
     4412 
     4413                                return startElement; 
    43914414                        } else { 
    4392                                 e = r.startContainer; 
    4393  
    4394                                 if (e.nodeType == 1 && e.hasChildNodes()) 
    4395                                         e = e.childNodes[Math.min(e.childNodes.length - 1, r.startOffset)]; 
    4396  
    4397                                 if (e && e.nodeType == 3) 
    4398                                         return e.parentNode; 
    4399  
    4400                                 return e; 
     4415                                startElement = rng.startContainer; 
     4416 
     4417                                if (startElement.nodeType == 1 && startElement.hasChildNodes()) 
     4418                                        startElement = startElement.childNodes[Math.min(startElement.childNodes.length - 1, rng.startOffset)]; 
     4419 
     4420                                if (startElement && startElement.nodeType == 3) 
     4421                                        return startElement.parentNode; 
     4422 
     4423                                return startElement; 
    44014424                        } 
    44024425                }, 
     
    45564579 
    45574580                                        function setEndPoint(start) { 
    4558                                                 var point = bookmark[start ? 'start' : 'end'], i, node, offset; 
     4581                                                var point = bookmark[start ? 'start' : 'end'], i, node, offset, children; 
    45594582 
    45604583                                                if (point) { 
    45614584                                                        // Find container node 
    4562                                                         for (node = root, i = point.length - 1; i >= 1; i--) 
    4563                                                                 node = node.childNodes[point[i]]; 
     4585                                                        for (node = root, i = point.length - 1; i >= 1; i--) { 
     4586                                                                children = node.childNodes; 
     4587 
     4588                                                                if (children.length) 
     4589                                                                        node = children[point[i]]; 
     4590                                                        } 
    45644591 
    45654592                                                        // Set offset within container node 
     
    45864613                                                                        idx = dom.nodeIndex(marker); 
    45874614                                                                } else { 
    4588                                                                         node = marker; 
     4615                                                                        node = marker.firstChild; 
    45894616                                                                        idx = 1; 
    45904617                                                                } 
     
    45964623                                                                        idx = dom.nodeIndex(marker); 
    45974624                                                                } else { 
    4598                                                                         node = marker; 
     4625                                                                        node = marker.firstChild; 
    45994626                                                                        idx = 1; 
    46004627                                                                } 
     
    46374664                                        }; 
    46384665 
     4666                                        function addBogus(node) { 
     4667                                                // Adds a bogus BR element for empty block elements 
     4668                                                // on non IE browsers just to have a place to put the caret 
     4669                                                if (!isIE && dom.isBlock(node) && !node.innerHTML) 
     4670                                                        node.innerHTML = '<br _mce_bogus="1" />'; 
     4671 
     4672                                                return node; 
     4673                                        }; 
     4674 
    46394675                                        // Restore start/end points 
    46404676                                        restoreEndPoint('start'); 
     
    46424678 
    46434679                                        rng = dom.createRng(); 
    4644                                         rng.setStart(startContainer, startOffset); 
    4645                                         rng.setEnd(endContainer, endOffset); 
     4680                                        rng.setStart(addBogus(startContainer), startOffset); 
     4681                                        rng.setEnd(addBogus(endContainer), endOffset); 
    46464682                                        t.setRng(rng); 
    46474683                                } else if (bookmark.name) { 
     
    73587394 
    73597395                        Event.add(t.id, 'click', t.showMenu, t); 
    7360                         Event.add(t.id + '_text', 'focus', function(e) { 
     7396                        Event.add(t.id + '_text', 'focus', function() { 
    73617397                                if (!t._focused) { 
    73627398                                        t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) { 
     
    99109946                        // Add node change handlers 
    99119947                        t.onMouseUp.add(t.nodeChanged); 
    9912                         t.onClick.add(t.nodeChanged); 
     9948                        //t.onClick.add(t.nodeChanged); 
    99139949                        t.onKeyUp.add(function(ed, e) { 
    99149950                                var c = e.keyCode; 
     
    1008410120 
    1008510121                                t.onKeyDown.add(function(ed, e) { 
     10122                                        var rng, tmpRng, parent, offset; 
     10123 
     10124                                        // IE has a really odd bug where the DOM might include an node that doesn't have 
     10125                                        // a proper structure. If you try to access nodeValue it would throw an illegal value exception. 
     10126                                        // This seems to only happen when you delete contents and it seems to be avoidable if you refresh the element 
     10127                                        // after you delete contents from it. See: #3008923 
     10128                                        if (isIE && e.keyCode == 46) { 
     10129                                                rng = t.selection.getRng(); 
     10130 
     10131                                                if (rng.parentElement) { 
     10132                                                        parent = rng.parentElement(); 
     10133 
     10134                                                        // Get the current caret position within the element 
     10135                                                        tmpRng = rng.duplicate(); 
     10136                                                        tmpRng.moveToElementText(parent); 
     10137                                                        tmpRng.setEndPoint('EndToEnd', rng); 
     10138                                                        offset = tmpRng.text.length; 
     10139 
     10140                                                        // Select next word when ctrl key is used in combo with delete 
     10141                                                        if (e.ctrlKey) { 
     10142                                                                rng.moveEnd('word', 1); 
     10143                                                                rng.select(); 
     10144                                                        } 
     10145 
     10146                                                        // Delete contents 
     10147                                                        t.selection.getSel().clear(); 
     10148 
     10149                                                        // Check if we are within the same parent 
     10150                                                        if (rng.parentElement() == parent) { 
     10151                                                                try { 
     10152                                                                        // Update the HTML and hopefully it will remove the artifacts 
     10153                                                                        parent.innerHTML = parent.innerHTML; 
     10154                                                                } catch (ex) { 
     10155                                                                        // And since it's IE it can sometimes produce an unknown runtime error 
     10156                                                                } 
     10157 
     10158                                                                // Restore the caret position 
     10159                                                                tmpRng.moveToElementText(parent); 
     10160                                                                tmpRng.collapse(); 
     10161                                                                tmpRng.move('character', offset); 
     10162                                                                tmpRng.select(); 
     10163                                                        } 
     10164 
     10165                                                        // Block the default delete behavior since it might be broken 
     10166                                                        e.preventDefault(); 
     10167                                                        return; 
     10168                                                } 
     10169                                        } 
     10170 
    1008610171                                        // Is caracter positon keys 
    1008710172                                        if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) { 
     
    1037510460 
    1037610461                        mceCleanup : function() { 
    10377                                 storeSelection(); 
     10462                                var bookmark = selection.getBookmark(); 
     10463 
    1037810464                                editor.setContent(editor.getContent({cleanup : TRUE}), {cleanup : TRUE}); 
    10379                                 restoreSelection(); 
     10465 
     10466                                selection.moveToBookmark(bookmark); 
    1038010467                        }, 
    1038110468 
     
    1069010777                FALSE = false; 
    1069110778 
     10779        function cloneFormats(node) { 
     10780                var clone, temp, inner; 
     10781 
     10782                do { 
     10783                        if (/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(node.nodeName)) { 
     10784                                if (clone) { 
     10785                                        temp = node.cloneNode(false); 
     10786                                        temp.appendChild(clone); 
     10787                                        clone = temp; 
     10788                                } else { 
     10789                                        clone = inner = node.cloneNode(false); 
     10790                                } 
     10791 
     10792                                clone.removeAttribute('id'); 
     10793                        } 
     10794                } while (node = node.parentNode); 
     10795 
     10796                if (clone) 
     10797                        return {wrapper : clone, inner : inner}; 
     10798        }; 
     10799 
    1069210800        // Checks if the selection/caret is at the end of the specified block element 
    1069310801        function isAtEnd(rng, par) { 
     
    1079810906                        } 
    1079910907 
    10800                         if (!isIE && s.force_p_newlines) { 
    10801                                 ed.onKeyPress.add(function(ed, e) { 
    10802                                         if (e.keyCode == 13 && !e.shiftKey && !t.insertPara(e)) 
    10803                                                 Event.cancel(e); 
    10804                                 }); 
     10908                        if (s.force_p_newlines) { 
     10909                                if (!isIE) { 
     10910                                        ed.onKeyPress.add(function(ed, e) { 
     10911                                                if (e.keyCode == 13 && !e.shiftKey && !t.insertPara(e)) 
     10912                                                        Event.cancel(e); 
     10913                                        }); 
     10914                                } else { 
     10915                                        // Ungly hack to for IE to preserve the formatting when you press 
     10916                                        // enter at the end of a block element with formatted contents 
     10917                                        // This logic overrides the browsers default logic with 
     10918                                        // custom logic that enables us to control the output 
     10919                                        tinymce.addUnload(function() { 
     10920                                                t._previousFormats = 0; // Fix IE leak 
     10921                                        }); 
     10922 
     10923                                        ed.onKeyPress.add(function(ed, e) { 
     10924                                                t._previousFormats = 0; 
     10925 
     10926                                                // Clone the current formats, this will later be applied to the new block contents 
     10927                                                if (e.keyCode == 13 && !e.shiftKey && ed.selection.isCollapsed() && s.keep_styles) 
     10928                                                        t._previousFormats = cloneFormats(ed.selection.getStart()); 
     10929                                        }); 
     10930 
     10931                                        ed.onKeyUp.add(function(ed, e) { 
     10932                                                // Let IE break the element and the wrap the new caret location in the previous formats 
     10933                                                if (e.keyCode == 13 && !e.shiftKey) { 
     10934                                                        var parent = ed.selection.getStart(), fmt = t._previousFormats; 
     10935 
     10936                                                        // Parent is an empty block 
     10937                                                        if (!parent.hasChildNodes()) { 
     10938                                                                parent = dom.getParent(parent, dom.isBlock); 
     10939 
     10940                                                                if (parent) { 
     10941                                                                        parent.innerHTML = ''; 
     10942         
     10943                                                                        if (t._previousFormats) { 
     10944                                                                                parent.appendChild(fmt.wrapper); 
     10945                                                                                fmt.inner.innerHTML = '\uFEFF'; 
     10946                                                                        } else 
     10947                                                                                parent.innerHTML = '\uFEFF'; 
     10948 
     10949                                                                        selection.select(parent, 1); 
     10950                                                                        ed.getDoc().execCommand('Delete', false, null); 
     10951                                                                } 
     10952                                                        } 
     10953                                                } 
     10954                                        }); 
     10955                                } 
    1080510956 
    1080610957                                if (isGecko) { 
     
    1130411455 
    1130511456                backspaceDelete : function(e, bs) { 
    11306                         var t = this, ed = t.editor, b = ed.getBody(), dom = ed.dom, n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n, w, tn; 
     11457                        var t = this, ed = t.editor, b = ed.getBody(), dom = ed.dom, n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n, w, tn, walker; 
     11458 
     11459                        // Delete when caret is behind a element doesn't work correctly on Gecko see #3011651 
     11460                        if (!bs && r.collapsed && sc.nodeType == 1 && r.startOffset == sc.childNodes.length) { 
     11461                                walker = new tinymce.dom.TreeWalker(sc.lastChild, sc); 
     11462 
     11463                                // Walk the dom backwards until we find a text node 
     11464                                for (n = sc.lastChild; n; n = walker.prev()) { 
     11465                                        if (n.nodeType == 3) { 
     11466                                                r.setStart(n, n.nodeValue.length); 
     11467                                                r.collapse(true); 
     11468                                                se.setRng(r); 
     11469                                                return; 
     11470                                        } 
     11471                                } 
     11472                        } 
    1130711473 
    1130811474                        // The caret sometimes gets stuck in Gecko if you delete empty paragraphs 
     
    1133511501                                } 
    1133611502                        } 
    11337  
    11338                         // Gecko generates BR elements here and there, we don't like those so lets remove them 
    11339                         function handler(e) { 
    11340                                 var pr; 
    11341  
    11342                                 e = e.target; 
    11343  
    11344                                 // A new BR was created in a block element, remove it 
    11345                                 if (e && e.parentNode && e.nodeName == 'BR' && (n = t.getParentBlock(e))) { 
    11346                                         pr = e.previousSibling; 
    11347  
    11348                                         Event.remove(b, 'DOMNodeInserted', handler); 
    11349  
    11350                                         // Is there whitespace at the end of the node before then we might need the pesky BR 
    11351                                         // to place the caret at a correct location see bug: #2013943 
    11352                                         if (pr && pr.nodeType == 3 && /\s+$/.test(pr.nodeValue)) 
    11353                                                 return; 
    11354  
    11355                                         // Only remove BR elements that got inserted in the middle of the text 
    11356                                         if (e.previousSibling || e.nextSibling) 
    11357                                                 ed.dom.remove(e); 
    11358                                 } 
    11359                         }; 
    11360  
    11361                         // Listen for new nodes 
    11362                         Event._add(b, 'DOMNodeInserted', handler); 
    11363  
    11364                         // Remove listener 
    11365                         window.setTimeout(function() { 
    11366                                 Event._remove(b, 'DOMNodeInserted', handler); 
    11367                         }, 1); 
    1136811503                } 
    1136911504        }); 
     
    1198212117                                if (container.nodeType == 1 || container.nodeValue === "") { 
    1198312118                                        container = container.nodeType == 1 ? container.childNodes[offset] : container; 
    11984                                         walker = new TreeWalker(container, container.parentNode); 
    11985                                         for (node = walker.current(); node; node = walker.next()) { 
    11986                                                 if (node.nodeType == 3 && !isBlock(node.parentNode) && !isWhiteSpaceNode(node)) { 
    11987                                                         rng.setStart(node, 0); 
    11988                                                         break; 
     12119 
     12120                                        // Might fail if the offset is behind the last element in it's container 
     12121                                        if (container) { 
     12122                                                walker = new TreeWalker(container, container.parentNode); 
     12123                                                for (node = walker.current(); node; node = walker.next()) { 
     12124                                                        if (node.nodeType == 3 && !isWhiteSpaceNode(node)) { 
     12125                                                                rng.setStart(node, 0); 
     12126                                                                break; 
     12127                                                        } 
    1198912128                                                } 
    1199012129                                        } 
     
    1219212331                                        rng.setEndAfter(node); 
    1219312332 
    12194                                         applyRngStyle(rng); 
     12333                                        applyRngStyle(expandRng(rng, formatList)); 
    1219512334                                } else { 
    1219612335                                        if (!selection.isCollapsed() || !format.inline) { 
     
    1261812757 
    1261912758                function isWhiteSpaceNode(node) { 
    12620                         return node && node.nodeType === 3 && /^\s*$/.test(node.nodeValue); 
     12759                        return node && node.nodeType === 3 && /^([\s\r\n]+|)$/.test(node.nodeValue); 
    1262112760                }; 
    1262212761 
     
    1315613295                                                                                textNode = node.firstChild; 
    1315713296 
    13158                                                                                 perform(node); 
    13159  
    13160                                                                                 rng = dom.createRng(); 
    13161                                                                                 rng.setStart(textNode, textNode.nodeValue.length); 
    13162                                                                                 rng.setEnd(textNode, textNode.nodeValue.length); 
    13163                                                                                 selection.setRng(rng); 
    13164                                                                                 ed.nodeChanged(); 
     13297                                                                                if (textNode) { 
     13298                                                                                        perform(node); 
     13299 
     13300                                                                                        rng = dom.createRng(); 
     13301                                                                                        rng.setStart(textNode, textNode.nodeValue.length); 
     13302                                                                                        rng.setEnd(textNode, textNode.nodeValue.length); 
     13303                                                                                        selection.setRng(rng); 
     13304                                                                                        ed.nodeChanged(); 
     13305                                                                                } else 
     13306                                                                                        dom.remove(node); 
    1316513307                                                                        } 
    1316613308                                                                }); 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/tiny_mce_prototype_src.js

    r7493 r7729  
    66                majorVersion : '3', 
    77 
    8                 minorVersion : '3.6', 
    9  
    10                 releaseDate : '2010-05-20', 
     8                minorVersion : '3.7', 
     9 
     10                releaseDate : '2010-06-10', 
    1111 
    1212                _init : function() { 
     
    33173317                                marker = dom.create('a'); 
    33183318                                parent = checkRng.parentElement(); 
     3319 
     3320                                // If parent doesn't have any children then set the container to that parent and the index to 0 
     3321                                if (!parent.hasChildNodes()) { 
     3322                                        domRange[start ? 'setStart' : 'setEnd'](parent, 0); 
     3323                                        return; 
     3324                                } 
     3325 
    33193326                                parent.appendChild(marker); 
    33203327                                checkRng.moveToElementText(marker); 
     
    34913498                                ieRng.moveToElementText(marker); 
    34923499                                marker.parentNode.removeChild(marker); 
    3493                                 ieRng.move('character', so); 
     3500 
     3501                                // Move if we need to, moving it 0 characters actually moves it! 
     3502                                if (so > 0) 
     3503                                        ieRng.move('character', so); 
    34943504                        } else { 
    34953505                                ieRng.moveToElementText(sc); 
     
    36513661(function(){ 
    36523662 
    3653 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g, 
     3663var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, 
    36543664        done = 0, 
    36553665        toString = Object.prototype.toString, 
    3656         hasDuplicate = false; 
     3666        hasDuplicate = false, 
     3667        baseHasDuplicate = true; 
     3668 
     3669// Here we check if the JavaScript engine is using some sort of 
     3670// optimization where it does not always call our comparision 
     3671// function. If that is the case, discard the hasDuplicate value. 
     3672//   Thus far that includes Google Chrome. 
     3673[0, 0].sort(function(){ 
     3674        baseHasDuplicate = false; 
     3675        return 0; 
     3676}); 
    36573677 
    36583678var Sizzle = function(selector, context, results, seed) { 
    36593679        results = results || []; 
    3660         var origContext = context = context || document; 
     3680        context = context || document; 
     3681 
     3682        var origContext = context; 
    36613683 
    36623684        if ( context.nodeType !== 1 && context.nodeType !== 9 ) { 
     
    36683690        } 
    36693691 
    3670         var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context); 
     3692        var parts = [], m, set, checkSet, extra, prune = true, contextXML = Sizzle.isXML(context), 
     3693                soFar = selector, ret, cur, pop, i; 
    36713694         
    36723695        // Reset the position of the chunker regexp (start from head) 
    3673         chunker.lastIndex = 0; 
    3674          
    3675         while ( (m = chunker.exec(selector)) !== null ) { 
    3676                 parts.push( m[1] ); 
     3696        do { 
     3697                chunker.exec(""); 
     3698                m = chunker.exec(soFar); 
     3699 
     3700                if ( m ) { 
     3701                        soFar = m[3]; 
    36773702                 
    3678                 if ( m[2] ) { 
    3679                         extra = RegExp.rightContext; 
    3680                         break; 
     3703                        parts.push( m[1] ); 
     3704                 
     3705                        if ( m[2] ) { 
     3706                                extra = m[3]; 
     3707                                break; 
     3708                        } 
    36813709                } 
    3682         } 
     3710        } while ( m ); 
    36833711 
    36843712        if ( parts.length > 1 && origPOS.exec( selector ) ) { 
     
    36933721                                selector = parts.shift(); 
    36943722 
    3695                                 if ( Expr.relative[ selector ] ) 
     3723                                if ( Expr.relative[ selector ] ) { 
    36963724                                        selector += parts.shift(); 
    3697  
     3725                                } 
     3726                                 
    36983727                                set = posProcess( selector, set ); 
    36993728                        } 
     
    37043733                if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && 
    37053734                                Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { 
    3706                         var ret = Sizzle.find( parts.shift(), context, contextXML ); 
     3735                        ret = Sizzle.find( parts.shift(), context, contextXML ); 
    37073736                        context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; 
    37083737                } 
    37093738 
    37103739                if ( context ) { 
    3711                         var ret = seed ? 
     3740                        ret = seed ? 
    37123741                                { expr: parts.pop(), set: makeArray(seed) } : 
    37133742                                Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); 
     
    37213750 
    37223751                        while ( parts.length ) { 
    3723                                 var cur = parts.pop(), pop = cur; 
     3752                                cur = parts.pop(); 
     3753                                pop = cur; 
    37243754 
    37253755                                if ( !Expr.relative[ cur ] ) { 
     
    37453775 
    37463776        if ( !checkSet ) { 
    3747                 throw "Syntax error, unrecognized expression: " + (cur || selector); 
     3777                Sizzle.error( cur || selector ); 
    37483778        } 
    37493779 
     
    37523782                        results.push.apply( results, checkSet ); 
    37533783                } else if ( context && context.nodeType === 1 ) { 
    3754                         for ( var i = 0; checkSet[i] != null; i++ ) { 
    3755                                 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { 
     3784                        for ( i = 0; checkSet[i] != null; i++ ) { 
     3785                                if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { 
    37563786                                        results.push( set[i] ); 
    37573787                                } 
    37583788                        } 
    37593789                } else { 
    3760                         for ( var i = 0; checkSet[i] != null; i++ ) { 
     3790                        for ( i = 0; checkSet[i] != null; i++ ) { 
    37613791                                if ( checkSet[i] && checkSet[i].nodeType === 1 ) { 
    37623792                                        results.push( set[i] ); 
     
    37783808Sizzle.uniqueSort = function(results){ 
    37793809        if ( sortOrder ) { 
    3780                 hasDuplicate = false; 
     3810                hasDuplicate = baseHasDuplicate; 
    37813811                results.sort(sortOrder); 
    37823812 
     
    37893819                } 
    37903820        } 
     3821 
     3822        return results; 
    37913823}; 
    37923824 
     
    37963828 
    37973829Sizzle.find = function(expr, context, isXML){ 
    3798         var set, match; 
     3830        var set; 
    37993831 
    38003832        if ( !expr ) { 
     
    38053837                var type = Expr.order[i], match; 
    38063838                 
    3807                 if ( (match = Expr.match[ type ].exec( expr )) ) { 
    3808                         var left = RegExp.leftContext; 
     3839                if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { 
     3840                        var left = match[1]; 
     3841                        match.splice(1,1); 
    38093842 
    38103843                        if ( left.substr( left.length - 1 ) !== "\\" ) { 
     
    38283861Sizzle.filter = function(expr, set, inplace, not){ 
    38293862        var old = expr, result = [], curLoop = set, match, anyFound, 
    3830                 isXMLFilter = set && set[0] && isXML(set[0]); 
     3863                isXMLFilter = set && set[0] && Sizzle.isXML(set[0]); 
    38313864 
    38323865        while ( expr && set.length ) { 
    38333866                for ( var type in Expr.filter ) { 
    3834                         if ( (match = Expr.match[ type ].exec( expr )) != null ) { 
    3835                                 var filter = Expr.filter[ type ], found, item; 
     3867                        if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { 
     3868                                var filter = Expr.filter[ type ], found, item, left = match[1]; 
    38363869                                anyFound = false; 
    38373870 
    3838                                 if ( curLoop == result ) { 
     3871                                match.splice(1,1); 
     3872 
     3873                                if ( left.substr( left.length - 1 ) === "\\" ) { 
     3874                                        continue; 
     3875                                } 
     3876 
     3877                                if ( curLoop === result ) { 
    38393878                                        result = []; 
    38403879                                } 
     
    38873926 
    38883927                // Improper expression 
    3889                 if ( expr == old ) { 
     3928                if ( expr === old ) { 
    38903929                        if ( anyFound == null ) { 
    3891                                 throw "Syntax error, unrecognized expression: " + expr; 
     3930                                Sizzle.error( expr ); 
    38923931                        } else { 
    38933932                                break; 
     
    38993938 
    39003939        return curLoop; 
     3940}; 
     3941 
     3942Sizzle.error = function( msg ) { 
     3943        throw "Syntax error, unrecognized expression: " + msg; 
    39013944}; 
    39023945 
     
    39043947        order: [ "ID", "NAME", "TAG" ], 
    39053948        match: { 
    3906                 ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, 
    3907                 CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, 
    3908                 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/, 
    3909                 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, 
    3910                 TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/, 
    3911                 CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, 
    3912                 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, 
    3913                 PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/ 
     3949                ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, 
     3950                CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, 
     3951                NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, 
     3952                ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, 
     3953                TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, 
     3954                CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/, 
     3955                POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, 
     3956                PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ 
    39143957        }, 
     3958        leftMatch: {}, 
    39153959        attrMap: { 
    39163960                "class": "className", 
     
    39233967        }, 
    39243968        relative: { 
    3925                 "+": function(checkSet, part, isXML){ 
     3969                "+": function(checkSet, part){ 
    39263970                        var isPartStr = typeof part === "string", 
    39273971                                isTag = isPartStr && !/\W/.test(part), 
    39283972                                isPartStrNotTag = isPartStr && !isTag; 
    39293973 
    3930                         if ( isTag && !isXML ) { 
    3931                                 part = part.toUpperCase(); 
     3974                        if ( isTag ) { 
     3975                                part = part.toLowerCase(); 
    39323976                        } 
    39333977 
     
    39363980                                        while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} 
    39373981 
    3938                                         checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ? 
     3982                                        checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? 
    39393983                                                elem || false : 
    39403984                                                elem === part; 
     
    39463990                        } 
    39473991                }, 
    3948                 ">": function(checkSet, part, isXML){ 
    3949                         var isPartStr = typeof part === "string"; 
     3992                ">": function(checkSet, part){ 
     3993                        var isPartStr = typeof part === "string", 
     3994                                elem, i = 0, l = checkSet.length; 
    39503995 
    39513996                        if ( isPartStr && !/\W/.test(part) ) { 
    3952                                 part = isXML ? part : part.toUpperCase(); 
    3953  
    3954                                 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 
    3955                                         var elem = checkSet[i]; 
     3997                                part = part.toLowerCase(); 
     3998 
     3999                                for ( ; i < l; i++ ) { 
     4000                                        elem = checkSet[i]; 
    39564001                                        if ( elem ) { 
    39574002                                                var parent = elem.parentNode; 
    3958                                                 checkSet[i] = parent.nodeName === part ? parent : false; 
     4003                                                checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; 
    39594004                                        } 
    39604005                                } 
    39614006                        } else { 
    3962                                 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 
    3963                                         var elem = checkSet[i]; 
     4007                                for ( ; i < l; i++ ) { 
     4008                                        elem = checkSet[i]; 
    39644009                                        if ( elem ) { 
    39654010                                                checkSet[i] = isPartStr ? 
     
    39754020                }, 
    39764021                "": function(checkSet, part, isXML){ 
    3977                         var doneName = done++, checkFn = dirCheck; 
    3978  
    3979                         if ( !part.match(/\W/) ) { 
    3980                                 var nodeCheck = part = isXML ? part : part.toUpperCase(); 
     4022                        var doneName = done++, checkFn = dirCheck, nodeCheck; 
     4023 
     4024                        if ( typeof part === "string" && !/\W/.test(part) ) { 
     4025                                part = part.toLowerCase(); 
     4026                                nodeCheck = part; 
    39814027                                checkFn = dirNodeCheck; 
    39824028                        } 
     
    39854031                }, 
    39864032                "~": function(checkSet, part, isXML){ 
    3987                         var doneName = done++, checkFn = dirCheck; 
    3988  
    3989                         if ( typeof part === "string" && !part.match(/\W/) ) { 
    3990                                 var nodeCheck = part = isXML ? part : part.toUpperCase(); 
     4033                        var doneName = done++, checkFn = dirCheck, nodeCheck; 
     4034 
     4035                        if ( typeof part === "string" && !/\W/.test(part) ) { 
     4036                                part = part.toLowerCase(); 
     4037                                nodeCheck = part; 
    39914038                                checkFn = dirNodeCheck; 
    39924039                        } 
     
    40024049                        } 
    40034050                }, 
    4004                 NAME: function(match, context, isXML){ 
     4051                NAME: function(match, context){ 
    40054052                        if ( typeof context.getElementsByName !== "undefined" ) { 
    40064053                                var ret = [], results = context.getElementsByName(match[1]); 
     
    40294076                        for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { 
    40304077                                if ( elem ) { 
    4031                                         if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) { 
    4032                                                 if ( !inplace ) 
     4078                                        if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) { 
     4079                                                if ( !inplace ) { 
    40334080                                                        result.push( elem ); 
     4081                                                } 
    40344082                                        } else if ( inplace ) { 
    40354083                                                curLoop[i] = false; 
     
    40444092                }, 
    40454093                TAG: function(match, curLoop){ 
    4046                         for ( var i = 0; curLoop[i] === false; i++ ){} 
    4047                         return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase(); 
     4094                        return match[1].toLowerCase(); 
    40484095                }, 
    40494096                CHILD: function(match){ 
    4050                         if ( match[1] == "nth" ) { 
     4097                        if ( match[1] === "nth" ) { 
    40514098                                // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' 
    40524099                                var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( 
    4053                                         match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" || 
     4100                                        match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || 
    40544101                                        !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); 
    40554102 
     
    40804127                        if ( match[1] === "not" ) { 
    40814128                                // If we're dealing with a complex expression, or a simple one 
    4082                                 if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) { 
     4129                                if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { 
    40834130                                        match[3] = Sizzle(match[3], null, null, curLoop); 
    40844131                                } else { 
     
    41264173                }, 
    41274174                header: function(elem){ 
    4128                         return /h\d/i.test( elem.nodeName ); 
     4175                        return (/h\d/i).test( elem.nodeName ); 
    41294176                }, 
    41304177                text: function(elem){ 
     
    41534200                }, 
    41544201                button: function(elem){ 
    4155                         return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON"; 
     4202                        return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; 
    41564203                }, 
    41574204                input: function(elem){ 
    4158                         return /input|select|textarea|button/i.test(elem.nodeName); 
     4205                        return (/input|select|textarea|button/i).test(elem.nodeName); 
    41594206                } 
    41604207        }, 
     
    41794226                }, 
    41804227                nth: function(elem, i, match){ 
    4181                         return match[3] - 0 == i; 
     4228                        return match[3] - 0 === i; 
    41824229                }, 
    41834230                eq: function(elem, i, match){ 
    4184                         return match[3] - 0 == i; 
     4231                        return match[3] - 0 === i; 
    41854232                } 
    41864233        }, 
     
    41924239                                return filter( elem, i, match, array ); 
    41934240                        } else if ( name === "contains" ) { 
    4194                                 return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0; 
     4241                                return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; 
    41954242                        } else if ( name === "not" ) { 
    41964243                                var not = match[3]; 
    41974244 
    4198                                 for ( var i = 0, l = not.length; i < l; i++ ) { 
    4199                                         if ( not[i] === elem ) { 
     4245                                for ( var j = 0, l = not.length; j < l; j++ ) { 
     4246                                        if ( not[j] === elem ) { 
    42004247                                                return false; 
    42014248                                        } 
     
    42034250 
    42044251                                return true; 
     4252                        } else { 
     4253                                Sizzle.error( "Syntax error, unrecognized expression: " + name ); 
    42054254                        } 
    42064255                }, 
     
    42104259                                case 'only': 
    42114260                                case 'first': 
    4212                                         while (node = node.previousSibling)  { 
    4213                                                 if ( node.nodeType === 1 ) return false; 
     4261                                        while ( (node = node.previousSibling) )  { 
     4262                                                if ( node.nodeType === 1 ) {  
     4263                                                        return false;  
     4264                                                } 
    42144265                                        } 
    4215                                         if ( type == 'first') return true; 
     4266                                        if ( type === "first" ) {  
     4267                                                return true;  
     4268                                        } 
    42164269                                        node = elem; 
    42174270                                case 'last': 
    4218                                         while (node = node.nextSibling)  { 
    4219                                                 if ( node.nodeType === 1 ) return false; 
     4271                                        while ( (node = node.nextSibling) )      { 
     4272                                                if ( node.nodeType === 1 ) {  
     4273                                                        return false;  
     4274                                                } 
    42204275                                        } 
    42214276                                        return true; 
     
    42234278                                        var first = match[2], last = match[3]; 
    42244279 
    4225                                         if ( first == 1 && last == 0 ) { 
     4280                                        if ( first === 1 && last === 0 ) { 
    42264281                                                return true; 
    42274282                                        } 
     
    42414296                                         
    42424297                                        var diff = elem.nodeIndex - last; 
    4243                                         if ( first == 0 ) { 
    4244                                                 return diff == 0; 
     4298                                        if ( first === 0 ) { 
     4299                                                return diff === 0; 
    42454300                                        } else { 
    4246                                                 return ( diff % first == 0 && diff / first >= 0 ); 
     4301                                                return ( diff % first === 0 && diff / first >= 0 ); 
    42474302                                        } 
    42484303                        } 
     
    42524307                }, 
    42534308                TAG: function(elem, match){ 
    4254                         return (match === "*" && elem.nodeType === 1) || elem.nodeName === match; 
     4309                        return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; 
    42554310                }, 
    42564311                CLASS: function(elem, match){ 
     
    42804335                                value && result !== false : 
    42814336                                type === "!=" ? 
    4282                                 value != check : 
     4337                                value !== check : 
    42834338                                type === "^=" ? 
    42844339                                value.indexOf(check) === 0 : 
     
    42994354}; 
    43004355 
    4301 var origPOS = Expr.match.POS; 
     4356var origPOS = Expr.match.POS, 
     4357        fescape = function(all, num){ 
     4358                return "\\" + (num - 0 + 1); 
     4359        }; 
    43024360 
    43034361for ( var type in Expr.match ) { 
    4304         Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); 
     4362        Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); 
     4363        Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); 
    43054364} 
    43064365 
    43074366var makeArray = function(array, results) { 
    4308         array = Array.prototype.slice.call( array ); 
     4367        array = Array.prototype.slice.call( array, 0 ); 
    43094368 
    43104369        if ( results ) { 
     
    43184377// Perform a simple check to determine if the browser is capable of 
    43194378// converting a NodeList to an array using builtin methods. 
     4379// Also verifies that the returned array holds DOM nodes 
     4380// (which is not the case in the Blackberry browser) 
    43204381try { 
    4321         Array.prototype.slice.call( document.documentElement.childNodes ); 
     4382        Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; 
    43224383 
    43234384// Provide a fallback method if it does not work 
    43244385} catch(e){ 
    43254386        makeArray = function(array, results) { 
    4326                 var ret = results || []; 
     4387                var ret = results || [], i = 0; 
    43274388 
    43284389                if ( toString.call(array) === "[object Array]" ) { 
     
    43304391                } else { 
    43314392                        if ( typeof array.length === "number" ) { 
    4332                                 for ( var i = 0, l = array.length; i < l; i++ ) { 
     4393                                for ( var l = array.length; i < l; i++ ) { 
    43334394                                        ret.push( array[i] ); 
    43344395                                } 
    43354396                        } else { 
    4336                                 for ( var i = 0; array[i]; i++ ) { 
     4397                                for ( ; array[i]; i++ ) { 
    43374398                                        ret.push( array[i] ); 
    43384399                                } 
     
    43484409if ( document.documentElement.compareDocumentPosition ) { 
    43494410        sortOrder = function( a, b ) { 
     4411                if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { 
     4412                        if ( a == b ) { 
     4413                                hasDuplicate = true; 
     4414                        } 
     4415                        return a.compareDocumentPosition ? -1 : 1; 
     4416                } 
     4417 
    43504418                var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; 
    43514419                if ( ret === 0 ) { 
     
    43564424} else if ( "sourceIndex" in document.documentElement ) { 
    43574425        sortOrder = function( a, b ) { 
     4426                if ( !a.sourceIndex || !b.sourceIndex ) { 
     4427                        if ( a == b ) { 
     4428                                hasDuplicate = true; 
     4429                        } 
     4430                        return a.sourceIndex ? -1 : 1; 
     4431                } 
     4432 
    43584433                var ret = a.sourceIndex - b.sourceIndex; 
    43594434                if ( ret === 0 ) { 
     
    43644439} else if ( document.createRange ) { 
    43654440        sortOrder = function( a, b ) { 
     4441                if ( !a.ownerDocument || !b.ownerDocument ) { 
     4442                        if ( a == b ) { 
     4443                                hasDuplicate = true; 
     4444                        } 
     4445                        return a.ownerDocument ? -1 : 1; 
     4446                } 
     4447 
    43664448                var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); 
    43674449                aRange.setStart(a, 0); 
     
    43774459} 
    43784460 
     4461// Utility function for retreiving the text value of an array of DOM nodes 
     4462Sizzle.getText = function( elems ) { 
     4463        var ret = "", elem; 
     4464 
     4465        for ( var i = 0; elems[i]; i++ ) { 
     4466                elem = elems[i]; 
     4467 
     4468                // Get the text from text nodes and CDATA nodes 
     4469                if ( elem.nodeType === 3 || elem.nodeType === 4 ) { 
     4470                        ret += elem.nodeValue; 
     4471 
     4472                // Traverse everything else, except comment nodes 
     4473                } else if ( elem.nodeType !== 8 ) { 
     4474                        ret += Sizzle.getText( elem.childNodes ); 
     4475                } 
     4476        } 
     4477 
     4478        return ret; 
     4479}; 
     4480 
    43794481// Check to see if the browser returns elements by name when 
    43804482// querying by getElementById (and provide a workaround) 
     
    43824484        // We're going to inject a fake input element with a specified name 
    43834485        var form = document.createElement("div"), 
    4384                 id = "script" + (new Date).getTime(); 
     4486                id = "script" + (new Date()).getTime(); 
    43854487        form.innerHTML = "<a name='" + id + "'/>"; 
    43864488 
     
    43914493        // The workaround has to do additional checks after a getElementById 
    43924494        // Which slows things down for other browsers (hence the branching) 
    4393         if ( !!document.getElementById( id ) ) { 
     4495        if ( document.getElementById( id ) ) { 
    43944496                Expr.find.ID = function(match, context, isXML){ 
    43954497                        if ( typeof context.getElementById !== "undefined" && !isXML ) { 
     
    44064508 
    44074509        root.removeChild( form ); 
     4510        root = form = null; // release memory in IE 
    44084511})(); 
    44094512 
     
    44464549                }; 
    44474550        } 
     4551 
     4552        div = null; // release memory in IE 
    44484553})(); 
    44494554 
    4450 if ( document.querySelectorAll ) (function(){ 
    4451         var oldSizzle = Sizzle, div = document.createElement("div"); 
    4452         div.innerHTML = "<p class='TEST'></p>"; 
    4453  
    4454         // Safari can't handle uppercase or unicode characters when 
    4455         // in quirks mode. 
    4456         if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { 
     4555if ( document.querySelectorAll ) { 
     4556        (function(){ 
     4557                var oldSizzle = Sizzle, div = document.createElement("div"); 
     4558                div.innerHTML = "<p class='TEST'></p>"; 
     4559 
     4560                // Safari can't handle uppercase or unicode characters when 
     4561                // in quirks mode. 
     4562                if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { 
     4563                        return; 
     4564                } 
     4565         
     4566                Sizzle = function(query, context, extra, seed){ 
     4567                        context = context || document; 
     4568 
     4569                        // Only use querySelectorAll on non-XML documents 
     4570                        // (ID selectors don't work in non-HTML documents) 
     4571                        if ( !seed && context.nodeType === 9 && !Sizzle.isXML(context) ) { 
     4572                                try { 
     4573                                        return makeArray( context.querySelectorAll(query), extra ); 
     4574                                } catch(e){} 
     4575                        } 
     4576                 
     4577                        return oldSizzle(query, context, extra, seed); 
     4578                }; 
     4579 
     4580                for ( var prop in oldSizzle ) { 
     4581                        Sizzle[ prop ] = oldSizzle[ prop ]; 
     4582                } 
     4583 
     4584                div = null; // release memory in IE 
     4585        })(); 
     4586} 
     4587 
     4588(function(){ 
     4589        var div = document.createElement("div"); 
     4590 
     4591        div.innerHTML = "<div class='test e'></div><div class='test'></div>"; 
     4592 
     4593        // Opera can't find a second classname (in 9.6) 
     4594        // Also, make sure that getElementsByClassName actually exists 
     4595        if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { 
     4596                return; 
     4597        } 
     4598 
     4599        // Safari caches class attributes, doesn't catch changes (in 3.2) 
     4600        div.lastChild.className = "e"; 
     4601 
     4602        if ( div.getElementsByClassName("e").length === 1 ) { 
    44574603                return; 
    44584604        } 
    44594605         
    4460         Sizzle = function(query, context, extra, seed){ 
    4461                 context = context || document; 
    4462  
    4463                 // Only use querySelectorAll on non-XML documents 
    4464                 // (ID selectors don't work in non-HTML documents) 
    4465                 if ( !seed && context.nodeType === 9 && !isXML(context) ) { 
    4466                         try { 
    4467                                 return makeArray( context.querySelectorAll(query), extra ); 
    4468                         } catch(e){} 
    4469                 } 
    4470                  
    4471                 return oldSizzle(query, context, extra, seed); 
    4472         }; 
    4473  
    4474         for ( var prop in oldSizzle ) { 
    4475                 Sizzle[ prop ] = oldSizzle[ prop ]; 
    4476         } 
    4477 })(); 
    4478  
    4479 if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){ 
    4480         var div = document.createElement("div"); 
    4481         div.innerHTML = "<div class='test e'></div><div class='test'></div>"; 
    4482  
    4483         // Opera can't find a second classname (in 9.6) 
    4484         if ( div.getElementsByClassName("e").length === 0 ) 
    4485                 return; 
    4486  
    4487         // Safari caches class attributes, doesn't catch changes (in 3.2) 
    4488         div.lastChild.className = "e"; 
    4489  
    4490         if ( div.getElementsByClassName("e").length === 1 ) 
    4491                 return; 
    4492  
    44934606        Expr.order.splice(1, 0, "CLASS"); 
    44944607        Expr.find.CLASS = function(match, context, isXML) { 
     
    44974610                } 
    44984611        }; 
     4612 
     4613        div = null; // release memory in IE 
    44994614})(); 
    45004615 
    45014616function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 
    4502         var sibDir = dir == "previousSibling" && !isXML; 
    45034617        for ( var i = 0, l = checkSet.length; i < l; i++ ) { 
    45044618                var elem = checkSet[i]; 
    45054619                if ( elem ) { 
    4506                         if ( sibDir && elem.nodeType === 1 ){ 
    4507                                 elem.sizcache = doneName; 
    4508                                 elem.sizset = i; 
    4509                         } 
    45104620                        elem = elem[dir]; 
    45114621                        var match = false; 
     
    45224632                                } 
    45234633 
    4524                                 if ( elem.nodeName === cur ) { 
     4634                                if ( elem.nodeName.toLowerCase() === cur ) { 
    45254635                                        match = elem; 
    45264636                                        break; 
     
    45364646 
    45374647function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 
    4538         var sibDir = dir == "previousSibling" && !isXML; 
    45394648        for ( var i = 0, l = checkSet.length; i < l; i++ ) { 
    45404649                var elem = checkSet[i]; 
    45414650                if ( elem ) { 
    4542                         if ( sibDir && elem.nodeType === 1 ) { 
    4543                                 elem.sizcache = doneName; 
    4544                                 elem.sizset = i; 
    4545                         } 
    45464651                        elem = elem[dir]; 
    45474652                        var match = false; 
     
    45784683} 
    45794684 
    4580 var contains = document.compareDocumentPosition ? function(a, b){ 
    4581         return a.compareDocumentPosition(b) & 16; 
     4685Sizzle.contains = document.compareDocumentPosition ? function(a, b){ 
     4686        return !!(a.compareDocumentPosition(b) & 16); 
    45824687} : function(a, b){ 
    45834688        return a !== b && (a.contains ? a.contains(b) : true); 
    45844689}; 
    45854690 
    4586 var isXML = function(elem){ 
    4587         return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || 
    4588                 !!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML"; 
     4691Sizzle.isXML = function(elem){ 
     4692        // documentElement is verified for cases where it doesn't yet exist 
     4693        // (such as loading iframes in IE - #4833)  
     4694        var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; 
     4695        return documentElement ? documentElement.nodeName !== "HTML" : false; 
    45894696}; 
    45904697 
     
    51345241 
    51355242                getStart : function() { 
    5136                         var t = this, r = t.getRng(), e; 
    5137  
    5138                         if (r.duplicate || r.item) { 
    5139                                 if (r.item) 
    5140                                         return r.item(0); 
    5141  
    5142                                 r = r.duplicate(); 
    5143                                 r.collapse(1); 
    5144                                 e = r.parentElement(); 
    5145  
    5146                                 if (e && e.nodeName == 'BODY') 
    5147                                         return e.firstChild || e; 
    5148  
    5149                                 return e; 
     5243                        var rng = this.getRng(), startElement, parentElement, checkRng, node; 
     5244 
     5245                        if (rng.duplicate || rng.item) { 
     5246                                // Control selection, return first item 
     5247                                if (rng.item) 
     5248                                        return rng.item(0); 
     5249 
     5250                                // Get start element 
     5251                                checkRng = rng.duplicate(); 
     5252                                checkRng.collapse(1); 
     5253                                startElement = checkRng.parentElement(); 
     5254 
     5255                                // Check if range parent is inside the start element, then return the inner parent element 
     5256                                // This will fix issues when a single element is selected, IE would otherwise return the wrong start element 
     5257                                parentElement = node = rng.parentElement(); 
     5258                                while (node = node.parentNode) { 
     5259                                        if (node == startElement) { 
     5260                                                startElement = parentElement; 
     5261                                                break; 
     5262                                        } 
     5263                                } 
     5264 
     5265                                // If start element is body element try to move to the first child if it exists 
     5266                                if (startElement && startElement.nodeName == 'BODY') 
     5267                                        return startElement.firstChild || startElement; 
     5268 
     5269                                return startElement; 
    51505270                        } else { 
    5151                                 e = r.startContainer; 
    5152  
    5153                                 if (e.nodeType == 1 && e.hasChildNodes()) 
    5154                                         e = e.childNodes[Math.min(e.childNodes.length - 1, r.startOffset)]; 
    5155  
    5156                                 if (e && e.nodeType == 3) 
    5157                                         return e.parentNode; 
    5158  
    5159                                 return e; 
     5271                                startElement = rng.startContainer; 
     5272 
     5273                                if (startElement.nodeType == 1 && startElement.hasChildNodes()) 
     5274                                        startElement = startElement.childNodes[Math.min(startElement.childNodes.length - 1, rng.startOffset)]; 
     5275 
     5276                                if (startElement && startElement.nodeType == 3) 
     5277                                        return startElement.parentNode; 
     5278 
     5279                                return startElement; 
    51605280                        } 
    51615281                }, 
     
    53155435 
    53165436                                        function setEndPoint(start) { 
    5317                                                 var point = bookmark[start ? 'start' : 'end'], i, node, offset; 
     5437                                                var point = bookmark[start ? 'start' : 'end'], i, node, offset, children; 
    53185438 
    53195439                                                if (point) { 
    53205440                                                        // Find container node 
    5321                                                         for (node = root, i = point.length - 1; i >= 1; i--) 
    5322                                                                 node = node.childNodes[point[i]]; 
     5441                                                        for (node = root, i = point.length - 1; i >= 1; i--) { 
     5442                                                                children = node.childNodes; 
     5443 
     5444                                                                if (children.length) 
     5445                                                                        node = children[point[i]]; 
     5446                                                        } 
    53235447 
    53245448                                                        // Set offset within container node 
     
    53455469                                                                        idx = dom.nodeIndex(marker); 
    53465470                                                                } else { 
    5347                                                                         node = marker; 
     5471                                                                        node = marker.firstChild; 
    53485472                                                                        idx = 1; 
    53495473                                                                } 
     
    53555479                                                                        idx = dom.nodeIndex(marker); 
    53565480                                                                } else { 
    5357                                                                         node = marker; 
     5481                                                                        node = marker.firstChild; 
    53585482                                                                        idx = 1; 
    53595483                                                                } 
     
    53965520                                        }; 
    53975521 
     5522                                        function addBogus(node) { 
     5523                                                // Adds a bogus BR element for empty block elements 
     5524                                                // on non IE browsers just to have a place to put the caret 
     5525                                                if (!isIE && dom.isBlock(node) && !node.innerHTML) 
     5526                                                        node.innerHTML = '<br _mce_bogus="1" />'; 
     5527 
     5528                                                return node; 
     5529                                        }; 
     5530 
    53985531                                        // Restore start/end points 
    53995532                                        restoreEndPoint('start'); 
     
    54015534 
    54025535                                        rng = dom.createRng(); 
    5403                                         rng.setStart(startContainer, startOffset); 
    5404                                         rng.setEnd(endContainer, endOffset); 
     5536                                        rng.setStart(addBogus(startContainer), startOffset); 
     5537                                        rng.setEnd(addBogus(endContainer), endOffset); 
    54055538                                        t.setRng(rng); 
    54065539                                } else if (bookmark.name) { 
     
    81178250 
    81188251                        Event.add(t.id, 'click', t.showMenu, t); 
    8119                         Event.add(t.id + '_text', 'focus', function(e) { 
     8252                        Event.add(t.id + '_text', 'focus', function() { 
    81208253                                if (!t._focused) { 
    81218254                                        t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) { 
     
    1066410797                        // Add node change handlers 
    1066510798                        t.onMouseUp.add(t.nodeChanged); 
    10666                         t.onClick.add(t.nodeChanged); 
     10799                        //t.onClick.add(t.nodeChanged); 
    1066710800                        t.onKeyUp.add(function(ed, e) { 
    1066810801                                var c = e.keyCode; 
     
    1083810971 
    1083910972                                t.onKeyDown.add(function(ed, e) { 
     10973                                        var rng, tmpRng, parent, offset; 
     10974 
     10975                                        // IE has a really odd bug where the DOM might include an node that doesn't have 
     10976                                        // a proper structure. If you try to access nodeValue it would throw an illegal value exception. 
     10977                                        // This seems to only happen when you delete contents and it seems to be avoidable if you refresh the element 
     10978                                        // after you delete contents from it. See: #3008923 
     10979                                        if (isIE && e.keyCode == 46) { 
     10980                                                rng = t.selection.getRng(); 
     10981 
     10982                                                if (rng.parentElement) { 
     10983                                                        parent = rng.parentElement(); 
     10984 
     10985                                                        // Get the current caret position within the element 
     10986                                                        tmpRng = rng.duplicate(); 
     10987                                                        tmpRng.moveToElementText(parent); 
     10988                                                        tmpRng.setEndPoint('EndToEnd', rng); 
     10989                                                        offset = tmpRng.text.length; 
     10990 
     10991                                                        // Select next word when ctrl key is used in combo with delete 
     10992                                                        if (e.ctrlKey) { 
     10993                                                                rng.moveEnd('word', 1); 
     10994                                                                rng.select(); 
     10995                                                        } 
     10996 
     10997                                                        // Delete contents 
     10998                                                        t.selection.getSel().clear(); 
     10999 
     11000                                                        // Check if we are within the same parent 
     11001                                                        if (rng.parentElement() == parent) { 
     11002                                                                try { 
     11003                                                                        // Update the HTML and hopefully it will remove the artifacts 
     11004                                                                        parent.innerHTML = parent.innerHTML; 
     11005                                                                } catch (ex) { 
     11006                                                                        // And since it's IE it can sometimes produce an unknown runtime error 
     11007                                                                } 
     11008 
     11009                                                                // Restore the caret position 
     11010                                                                tmpRng.moveToElementText(parent); 
     11011                                                                tmpRng.collapse(); 
     11012                                                                tmpRng.move('character', offset); 
     11013                                                                tmpRng.select(); 
     11014                                                        } 
     11015 
     11016                                                        // Block the default delete behavior since it might be broken 
     11017                                                        e.preventDefault(); 
     11018                                                        return; 
     11019                                                } 
     11020                                        } 
     11021 
    1084011022                                        // Is caracter positon keys 
    1084111023                                        if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) { 
     
    1112911311 
    1113011312                        mceCleanup : function() { 
    11131                                 storeSelection(); 
     11313                                var bookmark = selection.getBookmark(); 
     11314 
    1113211315                                editor.setContent(editor.getContent({cleanup : TRUE}), {cleanup : TRUE}); 
    11133                                 restoreSelection(); 
     11316 
     11317                                selection.moveToBookmark(bookmark); 
    1113411318                        }, 
    1113511319 
     
    1144411628                FALSE = false; 
    1144511629 
     11630        function cloneFormats(node) { 
     11631                var clone, temp, inner; 
     11632 
     11633                do { 
     11634                        if (/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(node.nodeName)) { 
     11635                                if (clone) { 
     11636                                        temp = node.cloneNode(false); 
     11637                                        temp.appendChild(clone); 
     11638                                        clone = temp; 
     11639                                } else { 
     11640                                        clone = inner = node.cloneNode(false); 
     11641                                } 
     11642 
     11643                                clone.removeAttribute('id'); 
     11644                        } 
     11645                } while (node = node.parentNode); 
     11646 
     11647                if (clone) 
     11648                        return {wrapper : clone, inner : inner}; 
     11649        }; 
     11650 
    1144611651        // Checks if the selection/caret is at the end of the specified block element 
    1144711652        function isAtEnd(rng, par) { 
     
    1155211757                        } 
    1155311758 
    11554                         if (!isIE && s.force_p_newlines) { 
    11555                                 ed.onKeyPress.add(function(ed, e) { 
    11556                                         if (e.keyCode == 13 && !e.shiftKey && !t.insertPara(e)) 
    11557                                                 Event.cancel(e); 
    11558                                 }); 
     11759                        if (s.force_p_newlines) { 
     11760                                if (!isIE) { 
     11761                                        ed.onKeyPress.add(function(ed, e) { 
     11762                                                if (e.keyCode == 13 && !e.shiftKey && !t.insertPara(e)) 
     11763                                                        Event.cancel(e); 
     11764                                        }); 
     11765                                } else { 
     11766                                        // Ungly hack to for IE to preserve the formatting when you press 
     11767                                        // enter at the end of a block element with formatted contents 
     11768                                        // This logic overrides the browsers default logic with 
     11769                                        // custom logic that enables us to control the output 
     11770                                        tinymce.addUnload(function() { 
     11771                                                t._previousFormats = 0; // Fix IE leak 
     11772                                        }); 
     11773 
     11774                                        ed.onKeyPress.add(function(ed, e) { 
     11775                                                t._previousFormats = 0; 
     11776 
     11777                                                // Clone the current formats, this will later be applied to the new block contents 
     11778                                                if (e.keyCode == 13 && !e.shiftKey && ed.selection.isCollapsed() && s.keep_styles) 
     11779                                                        t._previousFormats = cloneFormats(ed.selection.getStart()); 
     11780                                        }); 
     11781 
     11782                                        ed.onKeyUp.add(function(ed, e) { 
     11783                                                // Let IE break the element and the wrap the new caret location in the previous formats 
     11784                                                if (e.keyCode == 13 && !e.shiftKey) { 
     11785                                                        var parent = ed.selection.getStart(), fmt = t._previousFormats; 
     11786 
     11787                                                        // Parent is an empty block 
     11788                                                        if (!parent.hasChildNodes()) { 
     11789                                                                parent = dom.getParent(parent, dom.isBlock); 
     11790 
     11791                                                                if (parent) { 
     11792                                                                        parent.innerHTML = ''; 
     11793         
     11794                                                                        if (t._previousFormats) { 
     11795                                                                                parent.appendChild(fmt.wrapper); 
     11796                                                                                fmt.inner.innerHTML = '\uFEFF'; 
     11797                                                                        } else 
     11798                                                                                parent.innerHTML = '\uFEFF'; 
     11799 
     11800                                                                        selection.select(parent, 1); 
     11801                                                                        ed.getDoc().execCommand('Delete', false, null); 
     11802                                                                } 
     11803                                                        } 
     11804                                                } 
     11805                                        }); 
     11806                                } 
    1155911807 
    1156011808                                if (isGecko) { 
     
    1205812306 
    1205912307                backspaceDelete : function(e, bs) { 
    12060                         var t = this, ed = t.editor, b = ed.getBody(), dom = ed.dom, n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n, w, tn; 
     12308                        var t = this, ed = t.editor, b = ed.getBody(), dom = ed.dom, n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n, w, tn, walker; 
     12309 
     12310                        // Delete when caret is behind a element doesn't work correctly on Gecko see #3011651 
     12311                        if (!bs && r.collapsed && sc.nodeType == 1 && r.startOffset == sc.childNodes.length) { 
     12312                                walker = new tinymce.dom.TreeWalker(sc.lastChild, sc); 
     12313 
     12314                                // Walk the dom backwards until we find a text node 
     12315                                for (n = sc.lastChild; n; n = walker.prev()) { 
     12316                                        if (n.nodeType == 3) { 
     12317                                                r.setStart(n, n.nodeValue.length); 
     12318                                                r.collapse(true); 
     12319                                                se.setRng(r); 
     12320                                                return; 
     12321                                        } 
     12322                                } 
     12323                        } 
    1206112324 
    1206212325                        // The caret sometimes gets stuck in Gecko if you delete empty paragraphs 
     
    1208912352                                } 
    1209012353                        } 
    12091  
    12092                         // Gecko generates BR elements here and there, we don't like those so lets remove them 
    12093                         function handler(e) { 
    12094                                 var pr; 
    12095  
    12096                                 e = e.target; 
    12097  
    12098                                 // A new BR was created in a block element, remove it 
    12099                                 if (e && e.parentNode && e.nodeName == 'BR' && (n = t.getParentBlock(e))) { 
    12100                                         pr = e.previousSibling; 
    12101  
    12102                                         Event.remove(b, 'DOMNodeInserted', handler); 
    12103  
    12104                                         // Is there whitespace at the end of the node before then we might need the pesky BR 
    12105                                         // to place the caret at a correct location see bug: #2013943 
    12106                                         if (pr && pr.nodeType == 3 && /\s+$/.test(pr.nodeValue)) 
    12107                                                 return; 
    12108  
    12109                                         // Only remove BR elements that got inserted in the middle of the text 
    12110                                         if (e.previousSibling || e.nextSibling) 
    12111                                                 ed.dom.remove(e); 
    12112                                 } 
    12113                         }; 
    12114  
    12115                         // Listen for new nodes 
    12116                         Event._add(b, 'DOMNodeInserted', handler); 
    12117  
    12118                         // Remove listener 
    12119                         window.setTimeout(function() { 
    12120                                 Event._remove(b, 'DOMNodeInserted', handler); 
    12121                         }, 1); 
    1212212354                } 
    1212312355        }); 
     
    1273612968                                if (container.nodeType == 1 || container.nodeValue === "") { 
    1273712969                                        container = container.nodeType == 1 ? container.childNodes[offset] : container; 
    12738                                         walker = new TreeWalker(container, container.parentNode); 
    12739                                         for (node = walker.current(); node; node = walker.next()) { 
    12740                                                 if (node.nodeType == 3 && !isBlock(node.parentNode) && !isWhiteSpaceNode(node)) { 
    12741                                                         rng.setStart(node, 0); 
    12742                                                         break; 
     12970 
     12971                                        // Might fail if the offset is behind the last element in it's container 
     12972                                        if (container) { 
     12973                                                walker = new TreeWalker(container, container.parentNode); 
     12974                                                for (node = walker.current(); node; node = walker.next()) { 
     12975                                                        if (node.nodeType == 3 && !isWhiteSpaceNode(node)) { 
     12976                                                                rng.setStart(node, 0); 
     12977                                                                break; 
     12978                                                        } 
    1274312979                                                } 
    1274412980                                        } 
     
    1294613182                                        rng.setEndAfter(node); 
    1294713183 
    12948                                         applyRngStyle(rng); 
     13184                                        applyRngStyle(expandRng(rng, formatList)); 
    1294913185                                } else { 
    1295013186                                        if (!selection.isCollapsed() || !format.inline) { 
     
    1337213608 
    1337313609                function isWhiteSpaceNode(node) { 
    13374                         return node && node.nodeType === 3 && /^\s*$/.test(node.nodeValue); 
     13610                        return node && node.nodeType === 3 && /^([\s\r\n]+|)$/.test(node.nodeValue); 
    1337513611                }; 
    1337613612 
     
    1391014146                                                                                textNode = node.firstChild; 
    1391114147 
    13912                                                                                 perform(node); 
    13913  
    13914                                                                                 rng = dom.createRng(); 
    13915                                                                                 rng.setStart(textNode, textNode.nodeValue.length); 
    13916                                                                                 rng.setEnd(textNode, textNode.nodeValue.length); 
    13917                                                                                 selection.setRng(rng); 
    13918                                                                                 ed.nodeChanged(); 
     14148                                                                                if (textNode) { 
     14149                                                                                        perform(node); 
     14150 
     14151                                                                                        rng = dom.createRng(); 
     14152                                                                                        rng.setStart(textNode, textNode.nodeValue.length); 
     14153                                                                                        rng.setEnd(textNode, textNode.nodeValue.length); 
     14154                                                                                        selection.setRng(rng); 
     14155                                                                                        ed.nodeChanged(); 
     14156                                                                                } else 
     14157                                                                                        dom.remove(node); 
    1391914158                                                                        } 
    1392014159                                                                }); 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/tiny_mce_src.js

    r7493 r7729  
    66                majorVersion : '3', 
    77 
    8                 minorVersion : '3.6', 
    9  
    10                 releaseDate : '2010-05-20', 
     8                minorVersion : '3.7', 
     9 
     10                releaseDate : '2010-06-10', 
    1111 
    1212                _init : function() { 
     
    32903290                                marker = dom.create('a'); 
    32913291                                parent = checkRng.parentElement(); 
     3292 
     3293                                // If parent doesn't have any children then set the container to that parent and the index to 0 
     3294                                if (!parent.hasChildNodes()) { 
     3295                                        domRange[start ? 'setStart' : 'setEnd'](parent, 0); 
     3296                                        return; 
     3297                                } 
     3298 
    32923299                                parent.appendChild(marker); 
    32933300                                checkRng.moveToElementText(marker); 
     
    34643471                                ieRng.moveToElementText(marker); 
    34653472                                marker.parentNode.removeChild(marker); 
    3466                                 ieRng.move('character', so); 
     3473 
     3474                                // Move if we need to, moving it 0 characters actually moves it! 
     3475                                if (so > 0) 
     3476                                        ieRng.move('character', so); 
    34673477                        } else { 
    34683478                                ieRng.moveToElementText(sc); 
     
    36243634(function(){ 
    36253635 
    3626 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g, 
     3636var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, 
    36273637        done = 0, 
    36283638        toString = Object.prototype.toString, 
    3629         hasDuplicate = false; 
     3639        hasDuplicate = false, 
     3640        baseHasDuplicate = true; 
     3641 
     3642// Here we check if the JavaScript engine is using some sort of 
     3643// optimization where it does not always call our comparision 
     3644// function. If that is the case, discard the hasDuplicate value. 
     3645//   Thus far that includes Google Chrome. 
     3646[0, 0].sort(function(){ 
     3647        baseHasDuplicate = false; 
     3648        return 0; 
     3649}); 
    36303650 
    36313651var Sizzle = function(selector, context, results, seed) { 
    36323652        results = results || []; 
    3633         var origContext = context = context || document; 
     3653        context = context || document; 
     3654 
     3655        var origContext = context; 
    36343656 
    36353657        if ( context.nodeType !== 1 && context.nodeType !== 9 ) { 
     
    36413663        } 
    36423664 
    3643         var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context); 
     3665        var parts = [], m, set, checkSet, extra, prune = true, contextXML = Sizzle.isXML(context), 
     3666                soFar = selector, ret, cur, pop, i; 
    36443667         
    36453668        // Reset the position of the chunker regexp (start from head) 
    3646         chunker.lastIndex = 0; 
    3647          
    3648         while ( (m = chunker.exec(selector)) !== null ) { 
    3649                 parts.push( m[1] ); 
     3669        do { 
     3670                chunker.exec(""); 
     3671                m = chunker.exec(soFar); 
     3672 
     3673                if ( m ) { 
     3674                        soFar = m[3]; 
    36503675                 
    3651                 if ( m[2] ) { 
    3652                         extra = RegExp.rightContext; 
    3653                         break; 
     3676                        parts.push( m[1] ); 
     3677                 
     3678                        if ( m[2] ) { 
     3679                                extra = m[3]; 
     3680                                break; 
     3681                        } 
    36543682                } 
    3655         } 
     3683        } while ( m ); 
    36563684 
    36573685        if ( parts.length > 1 && origPOS.exec( selector ) ) { 
     
    36663694                                selector = parts.shift(); 
    36673695 
    3668                                 if ( Expr.relative[ selector ] ) 
     3696                                if ( Expr.relative[ selector ] ) { 
    36693697                                        selector += parts.shift(); 
    3670  
     3698                                } 
     3699                                 
    36713700                                set = posProcess( selector, set ); 
    36723701                        } 
     
    36773706                if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && 
    36783707                                Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { 
    3679                         var ret = Sizzle.find( parts.shift(), context, contextXML ); 
     3708                        ret = Sizzle.find( parts.shift(), context, contextXML ); 
    36803709                        context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; 
    36813710                } 
    36823711 
    36833712                if ( context ) { 
    3684                         var ret = seed ? 
     3713                        ret = seed ? 
    36853714                                { expr: parts.pop(), set: makeArray(seed) } : 
    36863715                                Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); 
     
    36943723 
    36953724                        while ( parts.length ) { 
    3696                                 var cur = parts.pop(), pop = cur; 
     3725                                cur = parts.pop(); 
     3726                                pop = cur; 
    36973727 
    36983728                                if ( !Expr.relative[ cur ] ) { 
     
    37183748 
    37193749        if ( !checkSet ) { 
    3720                 throw "Syntax error, unrecognized expression: " + (cur || selector); 
     3750                Sizzle.error( cur || selector ); 
    37213751        } 
    37223752 
     
    37253755                        results.push.apply( results, checkSet ); 
    37263756                } else if ( context && context.nodeType === 1 ) { 
    3727                         for ( var i = 0; checkSet[i] != null; i++ ) { 
    3728                                 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { 
     3757                        for ( i = 0; checkSet[i] != null; i++ ) { 
     3758                                if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { 
    37293759                                        results.push( set[i] ); 
    37303760                                } 
    37313761                        } 
    37323762                } else { 
    3733                         for ( var i = 0; checkSet[i] != null; i++ ) { 
     3763                        for ( i = 0; checkSet[i] != null; i++ ) { 
    37343764                                if ( checkSet[i] && checkSet[i].nodeType === 1 ) { 
    37353765                                        results.push( set[i] ); 
     
    37513781Sizzle.uniqueSort = function(results){ 
    37523782        if ( sortOrder ) { 
    3753                 hasDuplicate = false; 
     3783                hasDuplicate = baseHasDuplicate; 
    37543784                results.sort(sortOrder); 
    37553785 
     
    37623792                } 
    37633793        } 
     3794 
     3795        return results; 
    37643796}; 
    37653797 
     
    37693801 
    37703802Sizzle.find = function(expr, context, isXML){ 
    3771         var set, match; 
     3803        var set; 
    37723804 
    37733805        if ( !expr ) { 
     
    37783810                var type = Expr.order[i], match; 
    37793811                 
    3780                 if ( (match = Expr.match[ type ].exec( expr )) ) { 
    3781                         var left = RegExp.leftContext; 
     3812                if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { 
     3813                        var left = match[1]; 
     3814                        match.splice(1,1); 
    37823815 
    37833816                        if ( left.substr( left.length - 1 ) !== "\\" ) { 
     
    38013834Sizzle.filter = function(expr, set, inplace, not){ 
    38023835        var old = expr, result = [], curLoop = set, match, anyFound, 
    3803                 isXMLFilter = set && set[0] && isXML(set[0]); 
     3836                isXMLFilter = set && set[0] && Sizzle.isXML(set[0]); 
    38043837 
    38053838        while ( expr && set.length ) { 
    38063839                for ( var type in Expr.filter ) { 
    3807                         if ( (match = Expr.match[ type ].exec( expr )) != null ) { 
    3808                                 var filter = Expr.filter[ type ], found, item; 
     3840                        if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { 
     3841                                var filter = Expr.filter[ type ], found, item, left = match[1]; 
    38093842                                anyFound = false; 
    38103843 
    3811                                 if ( curLoop == result ) { 
     3844                                match.splice(1,1); 
     3845 
     3846                                if ( left.substr( left.length - 1 ) === "\\" ) { 
     3847                                        continue; 
     3848                                } 
     3849 
     3850                                if ( curLoop === result ) { 
    38123851                                        result = []; 
    38133852                                } 
     
    38603899 
    38613900                // Improper expression 
    3862                 if ( expr == old ) { 
     3901                if ( expr === old ) { 
    38633902                        if ( anyFound == null ) { 
    3864                                 throw "Syntax error, unrecognized expression: " + expr; 
     3903                                Sizzle.error( expr ); 
    38653904                        } else { 
    38663905                                break; 
     
    38723911 
    38733912        return curLoop; 
     3913}; 
     3914 
     3915Sizzle.error = function( msg ) { 
     3916        throw "Syntax error, unrecognized expression: " + msg; 
    38743917}; 
    38753918 
     
    38773920        order: [ "ID", "NAME", "TAG" ], 
    38783921        match: { 
    3879                 ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, 
    3880                 CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, 
    3881                 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/, 
    3882                 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, 
    3883                 TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/, 
    3884                 CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, 
    3885                 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, 
    3886                 PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/ 
     3922                ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, 
     3923                CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, 
     3924                NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, 
     3925                ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, 
     3926                TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, 
     3927                CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/, 
     3928                POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, 
     3929                PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ 
    38873930        }, 
     3931        leftMatch: {}, 
    38883932        attrMap: { 
    38893933                "class": "className", 
     
    38963940        }, 
    38973941        relative: { 
    3898                 "+": function(checkSet, part, isXML){ 
     3942                "+": function(checkSet, part){ 
    38993943                        var isPartStr = typeof part === "string", 
    39003944                                isTag = isPartStr && !/\W/.test(part), 
    39013945                                isPartStrNotTag = isPartStr && !isTag; 
    39023946 
    3903                         if ( isTag && !isXML ) { 
    3904                                 part = part.toUpperCase(); 
     3947                        if ( isTag ) { 
     3948                                part = part.toLowerCase(); 
    39053949                        } 
    39063950 
     
    39093953                                        while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} 
    39103954 
    3911                                         checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ? 
     3955                                        checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? 
    39123956                                                elem || false : 
    39133957                                                elem === part; 
     
    39193963                        } 
    39203964                }, 
    3921                 ">": function(checkSet, part, isXML){ 
    3922                         var isPartStr = typeof part === "string"; 
     3965                ">": function(checkSet, part){ 
     3966                        var isPartStr = typeof part === "string", 
     3967                                elem, i = 0, l = checkSet.length; 
    39233968 
    39243969                        if ( isPartStr && !/\W/.test(part) ) { 
    3925                                 part = isXML ? part : part.toUpperCase(); 
    3926  
    3927                                 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 
    3928                                         var elem = checkSet[i]; 
     3970                                part = part.toLowerCase(); 
     3971 
     3972                                for ( ; i < l; i++ ) { 
     3973                                        elem = checkSet[i]; 
    39293974                                        if ( elem ) { 
    39303975                                                var parent = elem.parentNode; 
    3931                                                 checkSet[i] = parent.nodeName === part ? parent : false; 
     3976                                                checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; 
    39323977                                        } 
    39333978                                } 
    39343979                        } else { 
    3935                                 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 
    3936                                         var elem = checkSet[i]; 
     3980                                for ( ; i < l; i++ ) { 
     3981                                        elem = checkSet[i]; 
    39373982                                        if ( elem ) { 
    39383983                                                checkSet[i] = isPartStr ? 
     
    39483993                }, 
    39493994                "": function(checkSet, part, isXML){ 
    3950                         var doneName = done++, checkFn = dirCheck; 
    3951  
    3952                         if ( !part.match(/\W/) ) { 
    3953                                 var nodeCheck = part = isXML ? part : part.toUpperCase(); 
     3995                        var doneName = done++, checkFn = dirCheck, nodeCheck; 
     3996 
     3997                        if ( typeof part === "string" && !/\W/.test(part) ) { 
     3998                                part = part.toLowerCase(); 
     3999                                nodeCheck = part; 
    39544000                                checkFn = dirNodeCheck; 
    39554001                        } 
     
    39584004                }, 
    39594005                "~": function(checkSet, part, isXML){ 
    3960                         var doneName = done++, checkFn = dirCheck; 
    3961  
    3962                         if ( typeof part === "string" && !part.match(/\W/) ) { 
    3963                                 var nodeCheck = part = isXML ? part : part.toUpperCase(); 
     4006                        var doneName = done++, checkFn = dirCheck, nodeCheck; 
     4007 
     4008                        if ( typeof part === "string" && !/\W/.test(part) ) { 
     4009                                part = part.toLowerCase(); 
     4010                                nodeCheck = part; 
    39644011                                checkFn = dirNodeCheck; 
    39654012                        } 
     
    39754022                        } 
    39764023                }, 
    3977                 NAME: function(match, context, isXML){ 
     4024                NAME: function(match, context){ 
    39784025                        if ( typeof context.getElementsByName !== "undefined" ) { 
    39794026                                var ret = [], results = context.getElementsByName(match[1]); 
     
    40024049                        for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { 
    40034050                                if ( elem ) { 
    4004                                         if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) { 
    4005                                                 if ( !inplace ) 
     4051                                        if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) { 
     4052                                                if ( !inplace ) { 
    40064053                                                        result.push( elem ); 
     4054                                                } 
    40074055                                        } else if ( inplace ) { 
    40084056                                                curLoop[i] = false; 
     
    40174065                }, 
    40184066                TAG: function(match, curLoop){ 
    4019                         for ( var i = 0; curLoop[i] === false; i++ ){} 
    4020                         return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase(); 
     4067                        return match[1].toLowerCase(); 
    40214068                }, 
    40224069                CHILD: function(match){ 
    4023                         if ( match[1] == "nth" ) { 
     4070                        if ( match[1] === "nth" ) { 
    40244071                                // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' 
    40254072                                var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( 
    4026                                         match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" || 
     4073                                        match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || 
    40274074                                        !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); 
    40284075 
     
    40534100                        if ( match[1] === "not" ) { 
    40544101                                // If we're dealing with a complex expression, or a simple one 
    4055                                 if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) { 
     4102                                if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { 
    40564103                                        match[3] = Sizzle(match[3], null, null, curLoop); 
    40574104                                } else { 
     
    40994146                }, 
    41004147                header: function(elem){ 
    4101                         return /h\d/i.test( elem.nodeName ); 
     4148                        return (/h\d/i).test( elem.nodeName ); 
    41024149                }, 
    41034150                text: function(elem){ 
     
    41264173                }, 
    41274174                button: function(elem){ 
    4128                         return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON"; 
     4175                        return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; 
    41294176                }, 
    41304177                input: function(elem){ 
    4131                         return /input|select|textarea|button/i.test(elem.nodeName); 
     4178                        return (/input|select|textarea|button/i).test(elem.nodeName); 
    41324179                } 
    41334180        }, 
     
    41524199                }, 
    41534200                nth: function(elem, i, match){ 
    4154                         return match[3] - 0 == i; 
     4201                        return match[3] - 0 === i; 
    41554202                }, 
    41564203                eq: function(elem, i, match){ 
    4157                         return match[3] - 0 == i; 
     4204                        return match[3] - 0 === i; 
    41584205                } 
    41594206        }, 
     
    41654212                                return filter( elem, i, match, array ); 
    41664213                        } else if ( name === "contains" ) { 
    4167                                 return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0; 
     4214                                return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; 
    41684215                        } else if ( name === "not" ) { 
    41694216                                var not = match[3]; 
    41704217 
    4171                                 for ( var i = 0, l = not.length; i < l; i++ ) { 
    4172                                         if ( not[i] === elem ) { 
     4218                                for ( var j = 0, l = not.length; j < l; j++ ) { 
     4219                                        if ( not[j] === elem ) { 
    41734220                                                return false; 
    41744221                                        } 
     
    41764223 
    41774224                                return true; 
     4225                        } else { 
     4226                                Sizzle.error( "Syntax error, unrecognized expression: " + name ); 
    41784227                        } 
    41794228                }, 
     
    41834232                                case 'only': 
    41844233                                case 'first': 
    4185                                         while (node = node.previousSibling)  { 
    4186                                                 if ( node.nodeType === 1 ) return false; 
     4234                                        while ( (node = node.previousSibling) )  { 
     4235                                                if ( node.nodeType === 1 ) {  
     4236                                                        return false;  
     4237                                                } 
    41874238                                        } 
    4188                                         if ( type == 'first') return true; 
     4239                                        if ( type === "first" ) {  
     4240                                                return true;  
     4241                                        } 
    41894242                                        node = elem; 
    41904243                                case 'last': 
    4191                                         while (node = node.nextSibling)  { 
    4192                                                 if ( node.nodeType === 1 ) return false; 
     4244                                        while ( (node = node.nextSibling) )      { 
     4245                                                if ( node.nodeType === 1 ) {  
     4246                                                        return false;  
     4247                                                } 
    41934248                                        } 
    41944249                                        return true; 
     
    41964251                                        var first = match[2], last = match[3]; 
    41974252 
    4198                                         if ( first == 1 && last == 0 ) { 
     4253                                        if ( first === 1 && last === 0 ) { 
    41994254                                                return true; 
    42004255                                        } 
     
    42144269                                         
    42154270                                        var diff = elem.nodeIndex - last; 
    4216                                         if ( first == 0 ) { 
    4217                                                 return diff == 0; 
     4271                                        if ( first === 0 ) { 
     4272                                                return diff === 0; 
    42184273                                        } else { 
    4219                                                 return ( diff % first == 0 && diff / first >= 0 ); 
     4274                                                return ( diff % first === 0 && diff / first >= 0 ); 
    42204275                                        } 
    42214276                        } 
     
    42254280                }, 
    42264281                TAG: function(elem, match){ 
    4227                         return (match === "*" && elem.nodeType === 1) || elem.nodeName === match; 
     4282                        return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; 
    42284283                }, 
    42294284                CLASS: function(elem, match){ 
     
    42534308                                value && result !== false : 
    42544309                                type === "!=" ? 
    4255                                 value != check : 
     4310                                value !== check : 
    42564311                                type === "^=" ? 
    42574312                                value.indexOf(check) === 0 : 
     
    42724327}; 
    42734328 
    4274 var origPOS = Expr.match.POS; 
     4329var origPOS = Expr.match.POS, 
     4330        fescape = function(all, num){ 
     4331                return "\\" + (num - 0 + 1); 
     4332        }; 
    42754333 
    42764334for ( var type in Expr.match ) { 
    4277         Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); 
     4335        Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); 
     4336        Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); 
    42784337} 
    42794338 
    42804339var makeArray = function(array, results) { 
    4281         array = Array.prototype.slice.call( array ); 
     4340        array = Array.prototype.slice.call( array, 0 ); 
    42824341 
    42834342        if ( results ) { 
     
    42914350// Perform a simple check to determine if the browser is capable of 
    42924351// converting a NodeList to an array using builtin methods. 
     4352// Also verifies that the returned array holds DOM nodes 
     4353// (which is not the case in the Blackberry browser) 
    42934354try { 
    4294         Array.prototype.slice.call( document.documentElement.childNodes ); 
     4355        Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; 
    42954356 
    42964357// Provide a fallback method if it does not work 
    42974358} catch(e){ 
    42984359        makeArray = function(array, results) { 
    4299                 var ret = results || []; 
     4360                var ret = results || [], i = 0; 
    43004361 
    43014362                if ( toString.call(array) === "[object Array]" ) { 
     
    43034364                } else { 
    43044365                        if ( typeof array.length === "number" ) { 
    4305                                 for ( var i = 0, l = array.length; i < l; i++ ) { 
     4366                                for ( var l = array.length; i < l; i++ ) { 
    43064367                                        ret.push( array[i] ); 
    43074368                                } 
    43084369                        } else { 
    4309                                 for ( var i = 0; array[i]; i++ ) { 
     4370                                for ( ; array[i]; i++ ) { 
    43104371                                        ret.push( array[i] ); 
    43114372                                } 
     
    43214382if ( document.documentElement.compareDocumentPosition ) { 
    43224383        sortOrder = function( a, b ) { 
     4384                if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { 
     4385                        if ( a == b ) { 
     4386                                hasDuplicate = true; 
     4387                        } 
     4388                        return a.compareDocumentPosition ? -1 : 1; 
     4389                } 
     4390 
    43234391                var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; 
    43244392                if ( ret === 0 ) { 
     
    43294397} else if ( "sourceIndex" in document.documentElement ) { 
    43304398        sortOrder = function( a, b ) { 
     4399                if ( !a.sourceIndex || !b.sourceIndex ) { 
     4400                        if ( a == b ) { 
     4401                                hasDuplicate = true; 
     4402                        } 
     4403                        return a.sourceIndex ? -1 : 1; 
     4404                } 
     4405 
    43314406                var ret = a.sourceIndex - b.sourceIndex; 
    43324407                if ( ret === 0 ) { 
     
    43374412} else if ( document.createRange ) { 
    43384413        sortOrder = function( a, b ) { 
     4414                if ( !a.ownerDocument || !b.ownerDocument ) { 
     4415                        if ( a == b ) { 
     4416                                hasDuplicate = true; 
     4417                        } 
     4418                        return a.ownerDocument ? -1 : 1; 
     4419                } 
     4420 
    43394421                var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); 
    43404422                aRange.setStart(a, 0); 
     
    43504432} 
    43514433 
     4434// Utility function for retreiving the text value of an array of DOM nodes 
     4435Sizzle.getText = function( elems ) { 
     4436        var ret = "", elem; 
     4437 
     4438        for ( var i = 0; elems[i]; i++ ) { 
     4439                elem = elems[i]; 
     4440 
     4441                // Get the text from text nodes and CDATA nodes 
     4442                if ( elem.nodeType === 3 || elem.nodeType === 4 ) { 
     4443                        ret += elem.nodeValue; 
     4444 
     4445                // Traverse everything else, except comment nodes 
     4446                } else if ( elem.nodeType !== 8 ) { 
     4447                        ret += Sizzle.getText( elem.childNodes ); 
     4448                } 
     4449        } 
     4450 
     4451        return ret; 
     4452}; 
     4453 
    43524454// Check to see if the browser returns elements by name when 
    43534455// querying by getElementById (and provide a workaround) 
     
    43554457        // We're going to inject a fake input element with a specified name 
    43564458        var form = document.createElement("div"), 
    4357                 id = "script" + (new Date).getTime(); 
     4459                id = "script" + (new Date()).getTime(); 
    43584460        form.innerHTML = "<a name='" + id + "'/>"; 
    43594461 
     
    43644466        // The workaround has to do additional checks after a getElementById 
    43654467        // Which slows things down for other browsers (hence the branching) 
    4366         if ( !!document.getElementById( id ) ) { 
     4468        if ( document.getElementById( id ) ) { 
    43674469                Expr.find.ID = function(match, context, isXML){ 
    43684470                        if ( typeof context.getElementById !== "undefined" && !isXML ) { 
     
    43794481 
    43804482        root.removeChild( form ); 
     4483        root = form = null; // release memory in IE 
    43814484})(); 
    43824485 
     
    44194522                }; 
    44204523        } 
     4524 
     4525        div = null; // release memory in IE 
    44214526})(); 
    44224527 
    4423 if ( document.querySelectorAll ) (function(){ 
    4424         var oldSizzle = Sizzle, div = document.createElement("div"); 
    4425         div.innerHTML = "<p class='TEST'></p>"; 
    4426  
    4427         // Safari can't handle uppercase or unicode characters when 
    4428         // in quirks mode. 
    4429         if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { 
     4528if ( document.querySelectorAll ) { 
     4529        (function(){ 
     4530                var oldSizzle = Sizzle, div = document.createElement("div"); 
     4531                div.innerHTML = "<p class='TEST'></p>"; 
     4532 
     4533                // Safari can't handle uppercase or unicode characters when 
     4534                // in quirks mode. 
     4535                if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { 
     4536                        return; 
     4537                } 
     4538         
     4539                Sizzle = function(query, context, extra, seed){ 
     4540                        context = context || document; 
     4541 
     4542                        // Only use querySelectorAll on non-XML documents 
     4543                        // (ID selectors don't work in non-HTML documents) 
     4544                        if ( !seed && context.nodeType === 9 && !Sizzle.isXML(context) ) { 
     4545                                try { 
     4546                                        return makeArray( context.querySelectorAll(query), extra ); 
     4547                                } catch(e){} 
     4548                        } 
     4549                 
     4550                        return oldSizzle(query, context, extra, seed); 
     4551                }; 
     4552 
     4553                for ( var prop in oldSizzle ) { 
     4554                        Sizzle[ prop ] = oldSizzle[ prop ]; 
     4555                } 
     4556 
     4557                div = null; // release memory in IE 
     4558        })(); 
     4559} 
     4560 
     4561(function(){ 
     4562        var div = document.createElement("div"); 
     4563 
     4564        div.innerHTML = "<div class='test e'></div><div class='test'></div>"; 
     4565 
     4566        // Opera can't find a second classname (in 9.6) 
     4567        // Also, make sure that getElementsByClassName actually exists 
     4568        if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { 
     4569                return; 
     4570        } 
     4571 
     4572        // Safari caches class attributes, doesn't catch changes (in 3.2) 
     4573        div.lastChild.className = "e"; 
     4574 
     4575        if ( div.getElementsByClassName("e").length === 1 ) { 
    44304576                return; 
    44314577        } 
    44324578         
    4433         Sizzle = function(query, context, extra, seed){ 
    4434                 context = context || document; 
    4435  
    4436                 // Only use querySelectorAll on non-XML documents 
    4437                 // (ID selectors don't work in non-HTML documents) 
    4438                 if ( !seed && context.nodeType === 9 && !isXML(context) ) { 
    4439                         try { 
    4440                                 return makeArray( context.querySelectorAll(query), extra ); 
    4441                         } catch(e){} 
    4442                 } 
    4443                  
    4444                 return oldSizzle(query, context, extra, seed); 
    4445         }; 
    4446  
    4447         for ( var prop in oldSizzle ) { 
    4448                 Sizzle[ prop ] = oldSizzle[ prop ]; 
    4449         } 
    4450 })(); 
    4451  
    4452 if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){ 
    4453         var div = document.createElement("div"); 
    4454         div.innerHTML = "<div class='test e'></div><div class='test'></div>"; 
    4455  
    4456         // Opera can't find a second classname (in 9.6) 
    4457         if ( div.getElementsByClassName("e").length === 0 ) 
    4458                 return; 
    4459  
    4460         // Safari caches class attributes, doesn't catch changes (in 3.2) 
    4461         div.lastChild.className = "e"; 
    4462  
    4463         if ( div.getElementsByClassName("e").length === 1 ) 
    4464                 return; 
    4465  
    44664579        Expr.order.splice(1, 0, "CLASS"); 
    44674580        Expr.find.CLASS = function(match, context, isXML) { 
     
    44704583                } 
    44714584        }; 
     4585 
     4586        div = null; // release memory in IE 
    44724587})(); 
    44734588 
    44744589function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 
    4475         var sibDir = dir == "previousSibling" && !isXML; 
    44764590        for ( var i = 0, l = checkSet.length; i < l; i++ ) { 
    44774591                var elem = checkSet[i]; 
    44784592                if ( elem ) { 
    4479                         if ( sibDir && elem.nodeType === 1 ){ 
    4480                                 elem.sizcache = doneName; 
    4481                                 elem.sizset = i; 
    4482                         } 
    44834593                        elem = elem[dir]; 
    44844594                        var match = false; 
     
    44954605                                } 
    44964606 
    4497                                 if ( elem.nodeName === cur ) { 
     4607                                if ( elem.nodeName.toLowerCase() === cur ) { 
    44984608                                        match = elem; 
    44994609                                        break; 
     
    45094619 
    45104620function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 
    4511         var sibDir = dir == "previousSibling" && !isXML; 
    45124621        for ( var i = 0, l = checkSet.length; i < l; i++ ) { 
    45134622                var elem = checkSet[i]; 
    45144623                if ( elem ) { 
    4515                         if ( sibDir && elem.nodeType === 1 ) { 
    4516                                 elem.sizcache = doneName; 
    4517                                 elem.sizset = i; 
    4518                         } 
    45194624                        elem = elem[dir]; 
    45204625                        var match = false; 
     
    45514656} 
    45524657 
    4553 var contains = document.compareDocumentPosition ? function(a, b){ 
    4554         return a.compareDocumentPosition(b) & 16; 
     4658Sizzle.contains = document.compareDocumentPosition ? function(a, b){ 
     4659        return !!(a.compareDocumentPosition(b) & 16); 
    45554660} : function(a, b){ 
    45564661        return a !== b && (a.contains ? a.contains(b) : true); 
    45574662}; 
    45584663 
    4559 var isXML = function(elem){ 
    4560         return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || 
    4561                 !!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML"; 
     4664Sizzle.isXML = function(elem){ 
     4665        // documentElement is verified for cases where it doesn't yet exist 
     4666        // (such as loading iframes in IE - #4833)  
     4667        var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; 
     4668        return documentElement ? documentElement.nodeName !== "HTML" : false; 
    45624669}; 
    45634670 
     
    51075214 
    51085215                getStart : function() { 
    5109                         var t = this, r = t.getRng(), e; 
    5110  
    5111                         if (r.duplicate || r.item) { 
    5112                                 if (r.item) 
    5113                                         return r.item(0); 
    5114  
    5115                                 r = r.duplicate(); 
    5116                                 r.collapse(1); 
    5117                                 e = r.parentElement(); 
    5118  
    5119                                 if (e && e.nodeName == 'BODY') 
    5120                                         return e.firstChild || e; 
    5121  
    5122                                 return e; 
     5216                        var rng = this.getRng(), startElement, parentElement, checkRng, node; 
     5217 
     5218                        if (rng.duplicate || rng.item) { 
     5219                                // Control selection, return first item 
     5220                                if (rng.item) 
     5221                                        return rng.item(0); 
     5222 
     5223                                // Get start element 
     5224                                checkRng = rng.duplicate(); 
     5225                                checkRng.collapse(1); 
     5226                                startElement = checkRng.parentElement(); 
     5227 
     5228                                // Check if range parent is inside the start element, then return the inner parent element 
     5229                                // This will fix issues when a single element is selected, IE would otherwise return the wrong start element 
     5230                                parentElement = node = rng.parentElement(); 
     5231                                while (node = node.parentNode) { 
     5232                                        if (node == startElement) { 
     5233                                                startElement = parentElement; 
     5234                                                break; 
     5235                                        } 
     5236                                } 
     5237 
     5238                                // If start element is body element try to move to the first child if it exists 
     5239                                if (startElement && startElement.nodeName == 'BODY') 
     5240                                        return startElement.firstChild || startElement; 
     5241 
     5242                                return startElement; 
    51235243                        } else { 
    5124                                 e = r.startContainer; 
    5125  
    5126                                 if (e.nodeType == 1 && e.hasChildNodes()) 
    5127                                         e = e.childNodes[Math.min(e.childNodes.length - 1, r.startOffset)]; 
    5128  
    5129                                 if (e && e.nodeType == 3) 
    5130                                         return e.parentNode; 
    5131  
    5132                                 return e; 
     5244                                startElement = rng.startContainer; 
     5245 
     5246                                if (startElement.nodeType == 1 && startElement.hasChildNodes()) 
     5247                                        startElement = startElement.childNodes[Math.min(startElement.childNodes.length - 1, rng.startOffset)]; 
     5248 
     5249                                if (startElement && startElement.nodeType == 3) 
     5250                                        return startElement.parentNode; 
     5251 
     5252                                return startElement; 
    51335253                        } 
    51345254                }, 
     
    52885408 
    52895409                                        function setEndPoint(start) { 
    5290                                                 var point = bookmark[start ? 'start' : 'end'], i, node, offset; 
     5410                                                var point = bookmark[start ? 'start' : 'end'], i, node, offset, children; 
    52915411 
    52925412                                                if (point) { 
    52935413                                                        // Find container node 
    5294                                                         for (node = root, i = point.length - 1; i >= 1; i--) 
    5295                                                                 node = node.childNodes[point[i]]; 
     5414                                                        for (node = root, i = point.length - 1; i >= 1; i--) { 
     5415                                                                children = node.childNodes; 
     5416 
     5417                                                                if (children.length) 
     5418                                                                        node = children[point[i]]; 
     5419                                                        } 
    52965420 
    52975421                                                        // Set offset within container node 
     
    53185442                                                                        idx = dom.nodeIndex(marker); 
    53195443                                                                } else { 
    5320                                                                         node = marker; 
     5444                                                                        node = marker.firstChild; 
    53215445                                                                        idx = 1; 
    53225446                                                                } 
     
    53285452                                                                        idx = dom.nodeIndex(marker); 
    53295453                                                                } else { 
    5330                                                                         node = marker; 
     5454                                                                        node = marker.firstChild; 
    53315455                                                                        idx = 1; 
    53325456                                                                } 
     
    53695493                                        }; 
    53705494 
     5495                                        function addBogus(node) { 
     5496                                                // Adds a bogus BR element for empty block elements 
     5497                                                // on non IE browsers just to have a place to put the caret 
     5498                                                if (!isIE && dom.isBlock(node) && !node.innerHTML) 
     5499                                                        node.innerHTML = '<br _mce_bogus="1" />'; 
     5500 
     5501                                                return node; 
     5502                                        }; 
     5503 
    53715504                                        // Restore start/end points 
    53725505                                        restoreEndPoint('start'); 
     
    53745507 
    53755508                                        rng = dom.createRng(); 
    5376                                         rng.setStart(startContainer, startOffset); 
    5377                                         rng.setEnd(endContainer, endOffset); 
     5509                                        rng.setStart(addBogus(startContainer), startOffset); 
     5510                                        rng.setEnd(addBogus(endContainer), endOffset); 
    53785511                                        t.setRng(rng); 
    53795512                                } else if (bookmark.name) { 
     
    80908223 
    80918224                        Event.add(t.id, 'click', t.showMenu, t); 
    8092                         Event.add(t.id + '_text', 'focus', function(e) { 
     8225                        Event.add(t.id + '_text', 'focus', function() { 
    80938226                                if (!t._focused) { 
    80948227                                        t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) { 
     
    1063710770                        // Add node change handlers 
    1063810771                        t.onMouseUp.add(t.nodeChanged); 
    10639                         t.onClick.add(t.nodeChanged); 
     10772                        //t.onClick.add(t.nodeChanged); 
    1064010773                        t.onKeyUp.add(function(ed, e) { 
    1064110774                                var c = e.keyCode; 
     
    1081110944 
    1081210945                                t.onKeyDown.add(function(ed, e) { 
     10946                                        var rng, tmpRng, parent, offset; 
     10947 
     10948                                        // IE has a really odd bug where the DOM might include an node that doesn't have 
     10949                                        // a proper structure. If you try to access nodeValue it would throw an illegal value exception. 
     10950                                        // This seems to only happen when you delete contents and it seems to be avoidable if you refresh the element 
     10951                                        // after you delete contents from it. See: #3008923 
     10952                                        if (isIE && e.keyCode == 46) { 
     10953                                                rng = t.selection.getRng(); 
     10954 
     10955                                                if (rng.parentElement) { 
     10956                                                        parent = rng.parentElement(); 
     10957 
     10958                                                        // Get the current caret position within the element 
     10959                                                        tmpRng = rng.duplicate(); 
     10960                                                        tmpRng.moveToElementText(parent); 
     10961                                                        tmpRng.setEndPoint('EndToEnd', rng); 
     10962                                                        offset = tmpRng.text.length; 
     10963 
     10964                                                        // Select next word when ctrl key is used in combo with delete 
     10965                                                        if (e.ctrlKey) { 
     10966                                                                rng.moveEnd('word', 1); 
     10967                                                                rng.select(); 
     10968                                                        } 
     10969 
     10970                                                        // Delete contents 
     10971                                                        t.selection.getSel().clear(); 
     10972 
     10973                                                        // Check if we are within the same parent 
     10974                                                        if (rng.parentElement() == parent) { 
     10975                                                                try { 
     10976                                                                        // Update the HTML and hopefully it will remove the artifacts 
     10977                                                                        parent.innerHTML = parent.innerHTML; 
     10978                                                                } catch (ex) { 
     10979                                                                        // And since it's IE it can sometimes produce an unknown runtime error 
     10980                                                                } 
     10981 
     10982                                                                // Restore the caret position 
     10983                                                                tmpRng.moveToElementText(parent); 
     10984                                                                tmpRng.collapse(); 
     10985                                                                tmpRng.move('character', offset); 
     10986                                                                tmpRng.select(); 
     10987                                                        } 
     10988 
     10989                                                        // Block the default delete behavior since it might be broken 
     10990                                                        e.preventDefault(); 
     10991                                                        return; 
     10992                                                } 
     10993                                        } 
     10994 
    1081310995                                        // Is caracter positon keys 
    1081410996                                        if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) { 
     
    1110211284 
    1110311285                        mceCleanup : function() { 
    11104                                 storeSelection(); 
     11286                                var bookmark = selection.getBookmark(); 
     11287 
    1110511288                                editor.setContent(editor.getContent({cleanup : TRUE}), {cleanup : TRUE}); 
    11106                                 restoreSelection(); 
     11289 
     11290                                selection.moveToBookmark(bookmark); 
    1110711291                        }, 
    1110811292 
     
    1141711601                FALSE = false; 
    1141811602 
     11603        function cloneFormats(node) { 
     11604                var clone, temp, inner; 
     11605 
     11606                do { 
     11607                        if (/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(node.nodeName)) { 
     11608                                if (clone) { 
     11609                                        temp = node.cloneNode(false); 
     11610                                        temp.appendChild(clone); 
     11611                                        clone = temp; 
     11612                                } else { 
     11613                                        clone = inner = node.cloneNode(false); 
     11614                                } 
     11615 
     11616                                clone.removeAttribute('id'); 
     11617                        } 
     11618                } while (node = node.parentNode); 
     11619 
     11620                if (clone) 
     11621                        return {wrapper : clone, inner : inner}; 
     11622        }; 
     11623 
    1141911624        // Checks if the selection/caret is at the end of the specified block element 
    1142011625        function isAtEnd(rng, par) { 
     
    1152511730                        } 
    1152611731 
    11527                         if (!isIE && s.force_p_newlines) { 
    11528                                 ed.onKeyPress.add(function(ed, e) { 
    11529                                         if (e.keyCode == 13 && !e.shiftKey && !t.insertPara(e)) 
    11530                                                 Event.cancel(e); 
    11531                                 }); 
     11732                        if (s.force_p_newlines) { 
     11733                                if (!isIE) { 
     11734                                        ed.onKeyPress.add(function(ed, e) { 
     11735                                                if (e.keyCode == 13 && !e.shiftKey && !t.insertPara(e)) 
     11736                                                        Event.cancel(e); 
     11737                                        }); 
     11738                                } else { 
     11739                                        // Ungly hack to for IE to preserve the formatting when you press 
     11740                                        // enter at the end of a block element with formatted contents 
     11741                                        // This logic overrides the browsers default logic with 
     11742                                        // custom logic that enables us to control the output 
     11743                                        tinymce.addUnload(function() { 
     11744                                                t._previousFormats = 0; // Fix IE leak 
     11745                                        }); 
     11746 
     11747                                        ed.onKeyPress.add(function(ed, e) { 
     11748                                                t._previousFormats = 0; 
     11749 
     11750                                                // Clone the current formats, this will later be applied to the new block contents 
     11751                                                if (e.keyCode == 13 && !e.shiftKey && ed.selection.isCollapsed() && s.keep_styles) 
     11752                                                        t._previousFormats = cloneFormats(ed.selection.getStart()); 
     11753                                        }); 
     11754 
     11755                                        ed.onKeyUp.add(function(ed, e) { 
     11756                                                // Let IE break the element and the wrap the new caret location in the previous formats 
     11757                                                if (e.keyCode == 13 && !e.shiftKey) { 
     11758                                                        var parent = ed.selection.getStart(), fmt = t._previousFormats; 
     11759 
     11760                                                        // Parent is an empty block 
     11761                                                        if (!parent.hasChildNodes()) { 
     11762                                                                parent = dom.getParent(parent, dom.isBlock); 
     11763 
     11764                                                                if (parent) { 
     11765                                                                        parent.innerHTML = ''; 
     11766         
     11767                                                                        if (t._previousFormats) { 
     11768                                                                                parent.appendChild(fmt.wrapper); 
     11769                                                                                fmt.inner.innerHTML = '\uFEFF'; 
     11770                                                                        } else 
     11771                                                                                parent.innerHTML = '\uFEFF'; 
     11772 
     11773                                                                        selection.select(parent, 1); 
     11774                                                                        ed.getDoc().execCommand('Delete', false, null); 
     11775                                                                } 
     11776                                                        } 
     11777                                                } 
     11778                                        }); 
     11779                                } 
    1153211780 
    1153311781                                if (isGecko) { 
     
    1203112279 
    1203212280                backspaceDelete : function(e, bs) { 
    12033                         var t = this, ed = t.editor, b = ed.getBody(), dom = ed.dom, n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n, w, tn; 
     12281                        var t = this, ed = t.editor, b = ed.getBody(), dom = ed.dom, n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n, w, tn, walker; 
     12282 
     12283                        // Delete when caret is behind a element doesn't work correctly on Gecko see #3011651 
     12284                        if (!bs && r.collapsed && sc.nodeType == 1 && r.startOffset == sc.childNodes.length) { 
     12285                                walker = new tinymce.dom.TreeWalker(sc.lastChild, sc); 
     12286 
     12287                                // Walk the dom backwards until we find a text node 
     12288                                for (n = sc.lastChild; n; n = walker.prev()) { 
     12289                                        if (n.nodeType == 3) { 
     12290                                                r.setStart(n, n.nodeValue.length); 
     12291                                                r.collapse(true); 
     12292                                                se.setRng(r); 
     12293                                                return; 
     12294                                        } 
     12295                                } 
     12296                        } 
    1203412297 
    1203512298                        // The caret sometimes gets stuck in Gecko if you delete empty paragraphs 
     
    1206212325                                } 
    1206312326                        } 
    12064  
    12065                         // Gecko generates BR elements here and there, we don't like those so lets remove them 
    12066                         function handler(e) { 
    12067                                 var pr; 
    12068  
    12069                                 e = e.target; 
    12070  
    12071                                 // A new BR was created in a block element, remove it 
    12072                                 if (e && e.parentNode && e.nodeName == 'BR' && (n = t.getParentBlock(e))) { 
    12073                                         pr = e.previousSibling; 
    12074  
    12075                                         Event.remove(b, 'DOMNodeInserted', handler); 
    12076  
    12077                                         // Is there whitespace at the end of the node before then we might need the pesky BR 
    12078                                         // to place the caret at a correct location see bug: #2013943 
    12079                                         if (pr && pr.nodeType == 3 && /\s+$/.test(pr.nodeValue)) 
    12080                                                 return; 
    12081  
    12082                                         // Only remove BR elements that got inserted in the middle of the text 
    12083                                         if (e.previousSibling || e.nextSibling) 
    12084                                                 ed.dom.remove(e); 
    12085                                 } 
    12086                         }; 
    12087  
    12088                         // Listen for new nodes 
    12089                         Event._add(b, 'DOMNodeInserted', handler); 
    12090  
    12091                         // Remove listener 
    12092                         window.setTimeout(function() { 
    12093                                 Event._remove(b, 'DOMNodeInserted', handler); 
    12094                         }, 1); 
    1209512327                } 
    1209612328        }); 
     
    1270912941                                if (container.nodeType == 1 || container.nodeValue === "") { 
    1271012942                                        container = container.nodeType == 1 ? container.childNodes[offset] : container; 
    12711                                         walker = new TreeWalker(container, container.parentNode); 
    12712                                         for (node = walker.current(); node; node = walker.next()) { 
    12713                                                 if (node.nodeType == 3 && !isBlock(node.parentNode) && !isWhiteSpaceNode(node)) { 
    12714                                                         rng.setStart(node, 0); 
    12715                                                         break; 
     12943 
     12944                                        // Might fail if the offset is behind the last element in it's container 
     12945                                        if (container) { 
     12946                                                walker = new TreeWalker(container, container.parentNode); 
     12947                                                for (node = walker.current(); node; node = walker.next()) { 
     12948                                                        if (node.nodeType == 3 && !isWhiteSpaceNode(node)) { 
     12949                                                                rng.setStart(node, 0); 
     12950                                                                break; 
     12951                                                        } 
    1271612952                                                } 
    1271712953                                        } 
     
    1291913155                                        rng.setEndAfter(node); 
    1292013156 
    12921                                         applyRngStyle(rng); 
     13157                                        applyRngStyle(expandRng(rng, formatList)); 
    1292213158                                } else { 
    1292313159                                        if (!selection.isCollapsed() || !format.inline) { 
     
    1334513581 
    1334613582                function isWhiteSpaceNode(node) { 
    13347                         return node && node.nodeType === 3 && /^\s*$/.test(node.nodeValue); 
     13583                        return node && node.nodeType === 3 && /^([\s\r\n]+|)$/.test(node.nodeValue); 
    1334813584                }; 
    1334913585 
     
    1388314119                                                                                textNode = node.firstChild; 
    1388414120 
    13885                                                                                 perform(node); 
    13886  
    13887                                                                                 rng = dom.createRng(); 
    13888                                                                                 rng.setStart(textNode, textNode.nodeValue.length); 
    13889                                                                                 rng.setEnd(textNode, textNode.nodeValue.length); 
    13890                                                                                 selection.setRng(rng); 
    13891                                                                                 ed.nodeChanged(); 
     14121                                                                                if (textNode) { 
     14122                                                                                        perform(node); 
     14123 
     14124                                                                                        rng = dom.createRng(); 
     14125                                                                                        rng.setStart(textNode, textNode.nodeValue.length); 
     14126                                                                                        rng.setEnd(textNode, textNode.nodeValue.length); 
     14127                                                                                        selection.setRng(rng); 
     14128                                                                                        ed.nodeChanged(); 
     14129                                                                                } else 
     14130                                                                                        dom.remove(node); 
    1389214131                                                                        } 
    1389314132                                                                }); 
  • trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/tests/ie_selection.html

    r7493 r7729  
    267267                equals(rng.endContainer.nodeName, 'BODY'); 
    268268                equals(rng.endOffset, 1); 
     269        }); 
     270 
     271        test("Selection end within emtpy element", function() { 
     272                var rng; 
     273 
     274                editor.focus(); 
     275                editor.getBody().innerHTML = '<p>123</p><p></p>'; 
     276 
     277                rng = editor.execCommand('SelectAll'); 
     278 
     279                rng = editor.selection.getRng(true); 
     280                equals(rng.startContainer.nodeName, '#text'); 
     281                equals(rng.startOffset, 0); 
     282                equals(rng.endContainer.nodeName, 'P'); 
     283                equals(rng.endOffset, 0); 
    269284        }); 
    270285} else { 
Note: See TracChangeset for help on using the changeset viewer.