Changeset 7729
- Timestamp:
- 06/12/10 07:17:45 (2 years ago)
- Location:
- trunk/TinyMCEPlugin
- Files:
-
- 20 edited
-
lib/Foswiki/Plugins/TinyMCEPlugin.pm (modified) (1 diff)
-
pub/System/TinyMCEPlugin/tinymce/changelog.txt (modified) (1 diff)
-
pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/Editor.js (modified) (2 diffs)
-
pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/EditorCommands.js (modified) (1 diff)
-
pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/ForceBlocks.js (modified) (4 diffs)
-
pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/Formatter.js (modified) (4 diffs)
-
pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/dom/Selection.js (modified) (6 diffs)
-
pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/dom/Sizzle.js (modified) (49 diffs)
-
pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/dom/TridentSelection.js (modified) (2 diffs)
-
pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/ui/ListBox.js (modified) (1 diff)
-
pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/plugins/contextmenu/editor_plugin_src.js (modified) (1 diff)
-
pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/plugins/fullpage/editor_plugin_src.js (modified) (1 diff)
-
pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/plugins/fullscreen/editor_plugin_src.js (modified) (1 diff)
-
pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/plugins/spellchecker/editor_plugin_src.js (modified) (7 diffs)
-
pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/plugins/table/js/table.js (modified) (1 diff)
-
pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/themes/advanced/editor_template_src.js (modified) (4 diffs)
-
pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/tiny_mce_jquery_src.js (modified) (21 diffs)
-
pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/tiny_mce_prototype_src.js (modified) (70 diffs)
-
pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/tiny_mce_src.js (modified) (70 diffs)
-
pub/System/TinyMCEPlugin/tinymce/tests/ie_selection.html (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/TinyMCEPlugin/lib/Foswiki/Plugins/TinyMCEPlugin.pm
r7692 r7729 9 9 10 10 our $VERSION = '$Rev$'; 11 our $RELEASE = ' 21 May2010';11 our $RELEASE = '12 Jun 2010'; 12 12 our $SHORTDESCRIPTION = 'Integration of the Tiny MCE WYSIWYG Editor'; 13 13 our $NO_PREFS_IN_TOPIC = 1; -
trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/changelog.txt
r7493 r7729 1 Version 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. 1 23 Version 3.3.6 (2010-05-20) 2 24 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 2391 2391 // Add node change handlers 2392 2392 t.onMouseUp.add(t.nodeChanged); 2393 t.onClick.add(t.nodeChanged);2393 //t.onClick.add(t.nodeChanged); 2394 2394 t.onKeyUp.add(function(ed, e) { 2395 2395 var c = e.keyCode; … … 2565 2565 2566 2566 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 2567 2616 // Is caracter positon keys 2568 2617 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 251 251 252 252 mceCleanup : function() { 253 storeSelection(); 253 var bookmark = selection.getBookmark(); 254 254 255 editor.setContent(editor.getContent({cleanup : TRUE}), {cleanup : TRUE}); 255 restoreSelection(); 256 257 selection.moveToBookmark(bookmark); 256 258 }, 257 259 -
trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/ForceBlocks.js
r7493 r7729 20 20 FALSE = false; 21 21 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 22 43 // Checks if the selection/caret is at the end of the specified block element 23 44 function isAtEnd(rng, par) { … … 131 152 } 132 153 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 } 138 202 139 203 if (isGecko) { … … 637 701 638 702 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 } 640 719 641 720 // The caret sometimes gets stuck in Gecko if you delete empty paragraphs … … 668 747 } 669 748 } 670 671 // Gecko generates BR elements here and there, we don't like those so lets remove them672 function handler(e) {673 var pr;674 675 e = e.target;676 677 // A new BR was created in a block element, remove it678 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 BR684 // to place the caret at a correct location see bug: #2013943685 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 text689 if (e.previousSibling || e.nextSibling)690 ed.dom.remove(e);691 }692 };693 694 // Listen for new nodes695 Event._add(b, 'DOMNodeInserted', handler);696 697 // Remove listener698 window.setTimeout(function() {699 Event._remove(b, 'DOMNodeInserted', handler);700 }, 1);701 749 } 702 750 }); -
trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/Formatter.js
r7493 r7729 143 143 if (container.nodeType == 1 || container.nodeValue === "") { 144 144 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 } 150 154 } 151 155 } … … 356 360 rng.setEndAfter(node); 357 361 358 applyRngStyle( rng);362 applyRngStyle(expandRng(rng, formatList)); 359 363 } else { 360 364 if (!selection.isCollapsed() || !format.inline) { … … 865 869 866 870 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); 868 872 }; 869 873 … … 1497 1501 textNode = node.firstChild; 1498 1502 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); 1506 1513 } 1507 1514 }); -
trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/dom/Selection.js
r7493 r7729 171 171 */ 172 172 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; 187 200 } 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; 197 210 } 198 211 }, … … 375 388 376 389 function setEndPoint(start) { 377 var point = bookmark[start ? 'start' : 'end'], i, node, offset ;390 var point = bookmark[start ? 'start' : 'end'], i, node, offset, children; 378 391 379 392 if (point) { 380 393 // 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 } 383 400 384 401 // Set offset within container node … … 405 422 idx = dom.nodeIndex(marker); 406 423 } else { 407 node = marker ;424 node = marker.firstChild; 408 425 idx = 1; 409 426 } … … 415 432 idx = dom.nodeIndex(marker); 416 433 } else { 417 node = marker ;434 node = marker.firstChild; 418 435 idx = 1; 419 436 } … … 456 473 }; 457 474 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 458 484 // Restore start/end points 459 485 restoreEndPoint('start'); … … 461 487 462 488 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); 465 491 t.setRng(rng); 466 492 } else if (bookmark.name) { -
trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/dom/Sizzle.js
r5654 r7729 9 9 (function(){ 10 10 11 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^ [\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,11 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, 12 12 done = 0, 13 13 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 }); 15 25 16 26 var Sizzle = function(selector, context, results, seed) { 17 27 results = results || []; 18 var origContext = context = context || document; 28 context = context || document; 29 30 var origContext = context; 19 31 20 32 if ( context.nodeType !== 1 && context.nodeType !== 9 ) { … … 26 38 } 27 39 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; 29 42 30 43 // 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]; 35 50 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 ); 41 59 42 60 if ( parts.length > 1 && origPOS.exec( selector ) ) { … … 51 69 selector = parts.shift(); 52 70 53 if ( Expr.relative[ selector ] ) 71 if ( Expr.relative[ selector ] ) { 54 72 selector += parts.shift(); 55 73 } 74 56 75 set = posProcess( selector, set ); 57 76 } … … 62 81 if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && 63 82 Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { 64 varret = Sizzle.find( parts.shift(), context, contextXML );83 ret = Sizzle.find( parts.shift(), context, contextXML ); 65 84 context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; 66 85 } 67 86 68 87 if ( context ) { 69 varret = seed ?88 ret = seed ? 70 89 { expr: parts.pop(), set: makeArray(seed) } : 71 90 Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); … … 79 98 80 99 while ( parts.length ) { 81 var cur = parts.pop(), pop = cur; 100 cur = parts.pop(); 101 pop = cur; 82 102 83 103 if ( !Expr.relative[ cur ] ) { … … 103 123 104 124 if ( !checkSet ) { 105 throw "Syntax error, unrecognized expression: " + (cur || selector);125 Sizzle.error( cur || selector ); 106 126 } 107 127 … … 110 130 results.push.apply( results, checkSet ); 111 131 } else if ( context && context.nodeType === 1 ) { 112 for ( vari = 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])) ) { 114 134 results.push( set[i] ); 115 135 } 116 136 } 117 137 } else { 118 for ( vari = 0; checkSet[i] != null; i++ ) {138 for ( i = 0; checkSet[i] != null; i++ ) { 119 139 if ( checkSet[i] && checkSet[i].nodeType === 1 ) { 120 140 results.push( set[i] ); … … 136 156 Sizzle.uniqueSort = function(results){ 137 157 if ( sortOrder ) { 138 hasDuplicate = false;158 hasDuplicate = baseHasDuplicate; 139 159 results.sort(sortOrder); 140 160 … … 147 167 } 148 168 } 169 170 return results; 149 171 }; 150 172 … … 154 176 155 177 Sizzle.find = function(expr, context, isXML){ 156 var set , match;178 var set; 157 179 158 180 if ( !expr ) { … … 163 185 var type = Expr.order[i], match; 164 186 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); 167 190 168 191 if ( left.substr( left.length - 1 ) !== "\\" ) { … … 186 209 Sizzle.filter = function(expr, set, inplace, not){ 187 210 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]); 189 212 190 213 while ( expr && set.length ) { 191 214 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]; 194 217 anyFound = false; 195 218 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 ) { 197 226 result = []; 198 227 } … … 245 274 246 275 // Improper expression 247 if ( expr == old ) {276 if ( expr === old ) { 248 277 if ( anyFound == null ) { 249 throw "Syntax error, unrecognized expression: " + expr;278 Sizzle.error( expr ); 250 279 } else { 251 280 break; … … 257 286 258 287 return curLoop; 288 }; 289 290 Sizzle.error = function( msg ) { 291 throw "Syntax error, unrecognized expression: " + msg; 259 292 }; 260 293 … … 262 295 order: [ "ID", "NAME", "TAG" ], 263 296 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\))?/ 272 305 }, 306 leftMatch: {}, 273 307 attrMap: { 274 308 "class": "className", … … 281 315 }, 282 316 relative: { 283 "+": function(checkSet, part , isXML){317 "+": function(checkSet, part){ 284 318 var isPartStr = typeof part === "string", 285 319 isTag = isPartStr && !/\W/.test(part), 286 320 isPartStrNotTag = isPartStr && !isTag; 287 321 288 if ( isTag && !isXML) {289 part = part.to UpperCase();322 if ( isTag ) { 323 part = part.toLowerCase(); 290 324 } 291 325 … … 294 328 while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} 295 329 296 checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?330 checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? 297 331 elem || false : 298 332 elem === part; … … 304 338 } 305 339 }, 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; 308 343 309 344 if ( isPartStr && !/\W/.test(part) ) { 310 part = isXML ? part : part.toUpperCase();311 312 for ( var i = 0, l = checkSet.length; i < l; i++ ) {313 varelem = checkSet[i];345 part = part.toLowerCase(); 346 347 for ( ; i < l; i++ ) { 348 elem = checkSet[i]; 314 349 if ( elem ) { 315 350 var parent = elem.parentNode; 316 checkSet[i] = parent.nodeName === part ? parent : false;351 checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; 317 352 } 318 353 } 319 354 } else { 320 for ( var i = 0, l = checkSet.length; i < l; i++ ) {321 varelem = checkSet[i];355 for ( ; i < l; i++ ) { 356 elem = checkSet[i]; 322 357 if ( elem ) { 323 358 checkSet[i] = isPartStr ? … … 333 368 }, 334 369 "": 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; 339 375 checkFn = dirNodeCheck; 340 376 } … … 343 379 }, 344 380 "~": 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; 349 386 checkFn = dirNodeCheck; 350 387 } … … 360 397 } 361 398 }, 362 NAME: function(match, context , isXML){399 NAME: function(match, context){ 363 400 if ( typeof context.getElementsByName !== "undefined" ) { 364 401 var ret = [], results = context.getElementsByName(match[1]); … … 387 424 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { 388 425 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 ) { 391 428 result.push( elem ); 429 } 392 430 } else if ( inplace ) { 393 431 curLoop[i] = false; … … 402 440 }, 403 441 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(); 406 443 }, 407 444 CHILD: function(match){ 408 if ( match[1] == "nth" ) {445 if ( match[1] === "nth" ) { 409 446 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' 410 447 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" || 412 449 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); 413 450 … … 438 475 if ( match[1] === "not" ) { 439 476 // 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]) ) { 441 478 match[3] = Sizzle(match[3], null, null, curLoop); 442 479 } else { … … 484 521 }, 485 522 header: function(elem){ 486 return /h\d/i.test( elem.nodeName );523 return (/h\d/i).test( elem.nodeName ); 487 524 }, 488 525 text: function(elem){ … … 511 548 }, 512 549 button: function(elem){ 513 return "button" === elem.type || elem.nodeName.to UpperCase() === "BUTTON";550 return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; 514 551 }, 515 552 input: function(elem){ 516 return /input|select|textarea|button/i.test(elem.nodeName);553 return (/input|select|textarea|button/i).test(elem.nodeName); 517 554 } 518 555 }, … … 537 574 }, 538 575 nth: function(elem, i, match){ 539 return match[3] - 0 == i;576 return match[3] - 0 === i; 540 577 }, 541 578 eq: function(elem, i, match){ 542 return match[3] - 0 == i;579 return match[3] - 0 === i; 543 580 } 544 581 }, … … 550 587 return filter( elem, i, match, array ); 551 588 } 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; 553 590 } else if ( name === "not" ) { 554 591 var not = match[3]; 555 592 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 ) { 558 595 return false; 559 596 } … … 561 598 562 599 return true; 600 } else { 601 Sizzle.error( "Syntax error, unrecognized expression: " + name ); 563 602 } 564 603 }, … … 568 607 case 'only': 569 608 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 } 574 617 node = elem; 575 618 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 } 578 623 } 579 624 return true; … … 581 626 var first = match[2], last = match[3]; 582 627 583 if ( first == 1 && last== 0 ) {628 if ( first === 1 && last === 0 ) { 584 629 return true; 585 630 } … … 599 644 600 645 var diff = elem.nodeIndex - last; 601 if ( first == 0 ) {602 return diff == 0;646 if ( first === 0 ) { 647 return diff === 0; 603 648 } else { 604 return ( diff % first == 0 && diff / first >= 0 );649 return ( diff % first === 0 && diff / first >= 0 ); 605 650 } 606 651 } … … 610 655 }, 611 656 TAG: function(elem, match){ 612 return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;657 return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; 613 658 }, 614 659 CLASS: function(elem, match){ … … 638 683 value && result !== false : 639 684 type === "!=" ? 640 value != check :685 value !== check : 641 686 type === "^=" ? 642 687 value.indexOf(check) === 0 : … … 657 702 }; 658 703 659 var origPOS = Expr.match.POS; 704 var origPOS = Expr.match.POS, 705 fescape = function(all, num){ 706 return "\\" + (num - 0 + 1); 707 }; 660 708 661 709 for ( 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) ); 663 712 } 664 713 665 714 var makeArray = function(array, results) { 666 array = Array.prototype.slice.call( array );715 array = Array.prototype.slice.call( array, 0 ); 667 716 668 717 if ( results ) { … … 676 725 // Perform a simple check to determine if the browser is capable of 677 726 // 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) 678 729 try { 679 Array.prototype.slice.call( document.documentElement.childNodes );730 Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; 680 731 681 732 // Provide a fallback method if it does not work 682 733 } catch(e){ 683 734 makeArray = function(array, results) { 684 var ret = results || [] ;735 var ret = results || [], i = 0; 685 736 686 737 if ( toString.call(array) === "[object Array]" ) { … … 688 739 } else { 689 740 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++ ) { 691 742 ret.push( array[i] ); 692 743 } 693 744 } else { 694 for ( var i = 0; array[i]; i++ ) {745 for ( ; array[i]; i++ ) { 695 746 ret.push( array[i] ); 696 747 } … … 706 757 if ( document.documentElement.compareDocumentPosition ) { 707 758 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 708 766 var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; 709 767 if ( ret === 0 ) { … … 714 772 } else if ( "sourceIndex" in document.documentElement ) { 715 773 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 716 781 var ret = a.sourceIndex - b.sourceIndex; 717 782 if ( ret === 0 ) { … … 722 787 } else if ( document.createRange ) { 723 788 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 724 796 var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); 725 797 aRange.setStart(a, 0); … … 735 807 } 736 808 809 // Utility function for retreiving the text value of an array of DOM nodes 810 Sizzle.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 737 829 // Check to see if the browser returns elements by name when 738 830 // querying by getElementById (and provide a workaround) … … 740 832 // We're going to inject a fake input element with a specified name 741 833 var form = document.createElement("div"), 742 id = "script" + (new Date ).getTime();834 id = "script" + (new Date()).getTime(); 743 835 form.innerHTML = "<a name='" + id + "'/>"; 744 836 … … 749 841 // The workaround has to do additional checks after a getElementById 750 842 // Which slows things down for other browsers (hence the branching) 751 if ( !!document.getElementById( id ) ) {843 if ( document.getElementById( id ) ) { 752 844 Expr.find.ID = function(match, context, isXML){ 753 845 if ( typeof context.getElementById !== "undefined" && !isXML ) { … … 764 856 765 857 root.removeChild( form ); 858 root = form = null; // release memory in IE 766 859 })(); 767 860 … … 804 897 }; 805 898 } 899 900 div = null; // release memory in IE 806 901 })(); 807 902 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 ) { 903 if ( 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 ) { 815 944 return; 816 945 } 817 818 Sizzle = function(query, context, extra, seed){819 context = context || document;820 821 // Only use querySelectorAll on non-XML documents822 // (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;844 946 845 947 // Safari caches class attributes, doesn't catch changes (in 3.2) 846 948 div.lastChild.className = "e"; 847 949 848 if ( div.getElementsByClassName("e").length === 1 ) 950 if ( div.getElementsByClassName("e").length === 1 ) { 849 951 return; 850 952 } 953 851 954 Expr.order.splice(1, 0, "CLASS"); 852 955 Expr.find.CLASS = function(match, context, isXML) { … … 855 958 } 856 959 }; 960 961 div = null; // release memory in IE 857 962 })(); 858 963 859 964 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 860 var sibDir = dir == "previousSibling" && !isXML;861 965 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 862 966 var elem = checkSet[i]; 863 967 if ( elem ) { 864 if ( sibDir && elem.nodeType === 1 ){865 elem.sizcache = doneName;866 elem.sizset = i;867 }868 968 elem = elem[dir]; 869 969 var match = false; … … 880 980 } 881 981 882 if ( elem.nodeName === cur ) {982 if ( elem.nodeName.toLowerCase() === cur ) { 883 983 match = elem; 884 984 break; … … 894 994 895 995 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 896 var sibDir = dir == "previousSibling" && !isXML;897 996 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 898 997 var elem = checkSet[i]; 899 998 if ( elem ) { 900 if ( sibDir && elem.nodeType === 1 ) {901 elem.sizcache = doneName;902 elem.sizset = i;903 }904 999 elem = elem[dir]; 905 1000 var match = false; … … 936 1031 } 937 1032 938 var contains = document.compareDocumentPosition ?function(a, b){939 return a.compareDocumentPosition(b) & 16;1033 Sizzle.contains = document.compareDocumentPosition ? function(a, b){ 1034 return !!(a.compareDocumentPosition(b) & 16); 940 1035 } : function(a, b){ 941 1036 return a !== b && (a.contains ? a.contains(b) : true); 942 1037 }; 943 1038 944 var isXML = function(elem){ 945 return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || 946 !!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML"; 1039 Sizzle.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; 947 1044 }; 948 1045 -
trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/dom/TridentSelection.js
r7493 r7729 42 42 marker = dom.create('a'); 43 43 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 44 51 parent.appendChild(marker); 45 52 checkRng.moveToElementText(marker); … … 216 223 ieRng.moveToElementText(marker); 217 224 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); 219 229 } else { 220 230 ieRng.moveToElementText(sc); -
trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/classes/ui/ListBox.js
r6655 r7729 317 317 318 318 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() { 320 320 if (!t._focused) { 321 321 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 48 48 49 49 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 }); 51 53 Event.cancel(e); 52 54 } 55 }); 56 57 ed.onRemove.add(function() { 58 if (t._menu) 59 t._menu.removeAll(); 53 60 }); 54 61 -
trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/plugins/fullpage/editor_plugin_src.js
r7229 r7729 86 86 var t = this, sp, ep, c = o.content, v, st = ''; 87 87 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 88 92 if (o.source_view && ed.getParam('fullpage_hide_in_source_view')) 89 93 return; -
trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/plugins/fullscreen/editor_plugin_src.js
r7493 r7729 120 120 121 121 // 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); 123 123 innerSize = fed.dom.getSize(fed.getContainer().getElementsByTagName('iframe')[0]); 124 124 -
trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/plugins/spellchecker/editor_plugin_src.js
r7398 r7729 262 262 263 263 _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 265 267 266 268 if (!m) { … … 277 279 } 278 280 279 if (dom.hasClass( e.target, 'mceItemHiddenSpellWord')) {281 if (dom.hasClass(wordSpan, 'mceItemHiddenSpellWord')) { 280 282 m.removeAll(); 281 283 m.add({title : 'spellchecker.wait', 'class' : 'mceMenuItemTitle'}).setDisabled(1); 282 284 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) { 284 286 var ignoreRpc; 285 287 … … 290 292 each(r, function(v) { 291 293 m.add({title : v, onclick : function() { 292 dom.replace(ed.getDoc().createTextNode(v), e.target);294 dom.replace(ed.getDoc().createTextNode(v), wordSpan); 293 295 t._checkDone(); 294 296 }}); … … 303 305 title : 'spellchecker.ignore_word', 304 306 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); 308 310 t._checkDone(); 309 311 … … 321 323 title : 'spellchecker.ignore_words', 322 324 onclick : function() { 323 var word = e.target.innerHTML;325 var word = wordSpan.innerHTML; 324 326 325 327 t._removeWords(dom.decode(word)); … … 341 343 title : 'spellchecker.learn_word', 342 344 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); 346 348 t._checkDone(); 347 349 … … 357 359 }); 358 360 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); 362 364 363 365 return tinymce.dom.Event.cancel(e); -
trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/plugins/table/js/table.js
r7230 r7729 317 317 dir = dom.getAttrib(elm, 'dir'); 318 318 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"); 320 320 formObj.caption.checked = elm.getElementsByTagName('caption').length > 0; 321 321 -
trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/themes/advanced/editor_template_src.js
r7493 r7729 227 227 228 228 ed.focus(); 229 ed.undoManager.add(); 229 230 230 231 // Toggle off the current format … … 234 235 else 235 236 ed.formatter.apply(name); 237 238 ed.undoManager.add(); 239 ed.nodeChanged(); 236 240 237 241 return false; // No auto select … … 298 302 onselect : function(v) { 299 303 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 300 310 return false; // No auto select 301 311 } … … 317 327 if (v['class']) { 318 328 ed.focus(); 329 ed.undoManager.add(); 319 330 ed.formatter.toggle('fontsize_class', {value : v['class']}); 331 ed.undoManager.add(); 332 ed.nodeChanged(); 320 333 } else 321 334 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 }); 322 340 323 341 return false; // No auto select -
trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/tiny_mce_jquery_src.js
r7493 r7729 6 6 majorVersion : '3', 7 7 8 minorVersion : '3. 6',9 10 releaseDate : '2010-0 5-20',8 minorVersion : '3.7', 9 10 releaseDate : '2010-06-10', 11 11 12 12 _init : function() { … … 3531 3531 marker = dom.create('a'); 3532 3532 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 3533 3540 parent.appendChild(marker); 3534 3541 checkRng.moveToElementText(marker); … … 3705 3712 ieRng.moveToElementText(marker); 3706 3713 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); 3708 3718 } else { 3709 3719 ieRng.moveToElementText(sc); … … 4375 4385 4376 4386 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; 4391 4414 } 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; 4401 4424 } 4402 4425 }, … … 4556 4579 4557 4580 function setEndPoint(start) { 4558 var point = bookmark[start ? 'start' : 'end'], i, node, offset ;4581 var point = bookmark[start ? 'start' : 'end'], i, node, offset, children; 4559 4582 4560 4583 if (point) { 4561 4584 // 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 } 4564 4591 4565 4592 // Set offset within container node … … 4586 4613 idx = dom.nodeIndex(marker); 4587 4614 } else { 4588 node = marker ;4615 node = marker.firstChild; 4589 4616 idx = 1; 4590 4617 } … … 4596 4623 idx = dom.nodeIndex(marker); 4597 4624 } else { 4598 node = marker ;4625 node = marker.firstChild; 4599 4626 idx = 1; 4600 4627 } … … 4637 4664 }; 4638 4665 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 4639 4675 // Restore start/end points 4640 4676 restoreEndPoint('start'); … … 4642 4678 4643 4679 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); 4646 4682 t.setRng(rng); 4647 4683 } else if (bookmark.name) { … … 7358 7394 7359 7395 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() { 7361 7397 if (!t._focused) { 7362 7398 t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) { … … 9910 9946 // Add node change handlers 9911 9947 t.onMouseUp.add(t.nodeChanged); 9912 t.onClick.add(t.nodeChanged);9948 //t.onClick.add(t.nodeChanged); 9913 9949 t.onKeyUp.add(function(ed, e) { 9914 9950 var c = e.keyCode; … … 10084 10120 10085 10121 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 10086 10171 // Is caracter positon keys 10087 10172 if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) { … … 10375 10460 10376 10461 mceCleanup : function() { 10377 storeSelection(); 10462 var bookmark = selection.getBookmark(); 10463 10378 10464 editor.setContent(editor.getContent({cleanup : TRUE}), {cleanup : TRUE}); 10379 restoreSelection(); 10465 10466 selection.moveToBookmark(bookmark); 10380 10467 }, 10381 10468 … … 10690 10777 FALSE = false; 10691 10778 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 10692 10800 // Checks if the selection/caret is at the end of the specified block element 10693 10801 function isAtEnd(rng, par) { … … 10798 10906 } 10799 10907 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 } 10805 10956 10806 10957 if (isGecko) { … … 11304 11455 11305 11456 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 } 11307 11473 11308 11474 // The caret sometimes gets stuck in Gecko if you delete empty paragraphs … … 11335 11501 } 11336 11502 } 11337 11338 // Gecko generates BR elements here and there, we don't like those so lets remove them11339 function handler(e) {11340 var pr;11341 11342 e = e.target;11343 11344 // A new BR was created in a block element, remove it11345 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 BR11351 // to place the caret at a correct location see bug: #201394311352 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 text11356 if (e.previousSibling || e.nextSibling)11357 ed.dom.remove(e);11358 }11359 };11360 11361 // Listen for new nodes11362 Event._add(b, 'DOMNodeInserted', handler);11363 11364 // Remove listener11365 window.setTimeout(function() {11366 Event._remove(b, 'DOMNodeInserted', handler);11367 }, 1);11368 11503 } 11369 11504 }); … … 11982 12117 if (container.nodeType == 1 || container.nodeValue === "") { 11983 12118 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 } 11989 12128 } 11990 12129 } … … 12192 12331 rng.setEndAfter(node); 12193 12332 12194 applyRngStyle( rng);12333 applyRngStyle(expandRng(rng, formatList)); 12195 12334 } else { 12196 12335 if (!selection.isCollapsed() || !format.inline) { … … 12618 12757 12619 12758 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); 12621 12760 }; 12622 12761 … … 13156 13295 textNode = node.firstChild; 13157 13296 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); 13165 13307 } 13166 13308 }); -
trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/tiny_mce_prototype_src.js
r7493 r7729 6 6 majorVersion : '3', 7 7 8 minorVersion : '3. 6',9 10 releaseDate : '2010-0 5-20',8 minorVersion : '3.7', 9 10 releaseDate : '2010-06-10', 11 11 12 12 _init : function() { … … 3317 3317 marker = dom.create('a'); 3318 3318 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 3319 3326 parent.appendChild(marker); 3320 3327 checkRng.moveToElementText(marker); … … 3491 3498 ieRng.moveToElementText(marker); 3492 3499 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); 3494 3504 } else { 3495 3505 ieRng.moveToElementText(sc); … … 3651 3661 (function(){ 3652 3662 3653 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^ [\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,3663 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, 3654 3664 done = 0, 3655 3665 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 }); 3657 3677 3658 3678 var Sizzle = function(selector, context, results, seed) { 3659 3679 results = results || []; 3660 var origContext = context = context || document; 3680 context = context || document; 3681 3682 var origContext = context; 3661 3683 3662 3684 if ( context.nodeType !== 1 && context.nodeType !== 9 ) { … … 3668 3690 } 3669 3691 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; 3671 3694 3672 3695 // 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]; 3677 3702 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 } 3681 3709 } 3682 } 3710 } while ( m ); 3683 3711 3684 3712 if ( parts.length > 1 && origPOS.exec( selector ) ) { … … 3693 3721 selector = parts.shift(); 3694 3722 3695 if ( Expr.relative[ selector ] ) 3723 if ( Expr.relative[ selector ] ) { 3696 3724 selector += parts.shift(); 3697 3725 } 3726 3698 3727 set = posProcess( selector, set ); 3699 3728 } … … 3704 3733 if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && 3705 3734 Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { 3706 varret = Sizzle.find( parts.shift(), context, contextXML );3735 ret = Sizzle.find( parts.shift(), context, contextXML ); 3707 3736 context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; 3708 3737 } 3709 3738 3710 3739 if ( context ) { 3711 varret = seed ?3740 ret = seed ? 3712 3741 { expr: parts.pop(), set: makeArray(seed) } : 3713 3742 Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); … … 3721 3750 3722 3751 while ( parts.length ) { 3723 var cur = parts.pop(), pop = cur; 3752 cur = parts.pop(); 3753 pop = cur; 3724 3754 3725 3755 if ( !Expr.relative[ cur ] ) { … … 3745 3775 3746 3776 if ( !checkSet ) { 3747 throw "Syntax error, unrecognized expression: " + (cur || selector);3777 Sizzle.error( cur || selector ); 3748 3778 } 3749 3779 … … 3752 3782 results.push.apply( results, checkSet ); 3753 3783 } else if ( context && context.nodeType === 1 ) { 3754 for ( vari = 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])) ) { 3756 3786 results.push( set[i] ); 3757 3787 } 3758 3788 } 3759 3789 } else { 3760 for ( vari = 0; checkSet[i] != null; i++ ) {3790 for ( i = 0; checkSet[i] != null; i++ ) { 3761 3791 if ( checkSet[i] && checkSet[i].nodeType === 1 ) { 3762 3792 results.push( set[i] ); … … 3778 3808 Sizzle.uniqueSort = function(results){ 3779 3809 if ( sortOrder ) { 3780 hasDuplicate = false;3810 hasDuplicate = baseHasDuplicate; 3781 3811 results.sort(sortOrder); 3782 3812 … … 3789 3819 } 3790 3820 } 3821 3822 return results; 3791 3823 }; 3792 3824 … … 3796 3828 3797 3829 Sizzle.find = function(expr, context, isXML){ 3798 var set , match;3830 var set; 3799 3831 3800 3832 if ( !expr ) { … … 3805 3837 var type = Expr.order[i], match; 3806 3838 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); 3809 3842 3810 3843 if ( left.substr( left.length - 1 ) !== "\\" ) { … … 3828 3861 Sizzle.filter = function(expr, set, inplace, not){ 3829 3862 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]); 3831 3864 3832 3865 while ( expr && set.length ) { 3833 3866 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]; 3836 3869 anyFound = false; 3837 3870 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 ) { 3839 3878 result = []; 3840 3879 } … … 3887 3926 3888 3927 // Improper expression 3889 if ( expr == old ) {3928 if ( expr === old ) { 3890 3929 if ( anyFound == null ) { 3891 throw "Syntax error, unrecognized expression: " + expr;3930 Sizzle.error( expr ); 3892 3931 } else { 3893 3932 break; … … 3899 3938 3900 3939 return curLoop; 3940 }; 3941 3942 Sizzle.error = function( msg ) { 3943 throw "Syntax error, unrecognized expression: " + msg; 3901 3944 }; 3902 3945 … … 3904 3947 order: [ "ID", "NAME", "TAG" ], 3905 3948 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\))?/ 3914 3957 }, 3958 leftMatch: {}, 3915 3959 attrMap: { 3916 3960 "class": "className", … … 3923 3967 }, 3924 3968 relative: { 3925 "+": function(checkSet, part , isXML){3969 "+": function(checkSet, part){ 3926 3970 var isPartStr = typeof part === "string", 3927 3971 isTag = isPartStr && !/\W/.test(part), 3928 3972 isPartStrNotTag = isPartStr && !isTag; 3929 3973 3930 if ( isTag && !isXML) {3931 part = part.to UpperCase();3974 if ( isTag ) { 3975 part = part.toLowerCase(); 3932 3976 } 3933 3977 … … 3936 3980 while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} 3937 3981 3938 checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?3982 checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? 3939 3983 elem || false : 3940 3984 elem === part; … … 3946 3990 } 3947 3991 }, 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; 3950 3995 3951 3996 if ( isPartStr && !/\W/.test(part) ) { 3952 part = isXML ? part : part.toUpperCase();3953 3954 for ( var i = 0, l = checkSet.length; i < l; i++ ) {3955 varelem = checkSet[i];3997 part = part.toLowerCase(); 3998 3999 for ( ; i < l; i++ ) { 4000 elem = checkSet[i]; 3956 4001 if ( elem ) { 3957 4002 var parent = elem.parentNode; 3958 checkSet[i] = parent.nodeName === part ? parent : false;4003 checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; 3959 4004 } 3960 4005 } 3961 4006 } else { 3962 for ( var i = 0, l = checkSet.length; i < l; i++ ) {3963 varelem = checkSet[i];4007 for ( ; i < l; i++ ) { 4008 elem = checkSet[i]; 3964 4009 if ( elem ) { 3965 4010 checkSet[i] = isPartStr ? … … 3975 4020 }, 3976 4021 "": 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; 3981 4027 checkFn = dirNodeCheck; 3982 4028 } … … 3985 4031 }, 3986 4032 "~": 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; 3991 4038 checkFn = dirNodeCheck; 3992 4039 } … … 4002 4049 } 4003 4050 }, 4004 NAME: function(match, context , isXML){4051 NAME: function(match, context){ 4005 4052 if ( typeof context.getElementsByName !== "undefined" ) { 4006 4053 var ret = [], results = context.getElementsByName(match[1]); … … 4029 4076 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { 4030 4077 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 ) { 4033 4080 result.push( elem ); 4081 } 4034 4082 } else if ( inplace ) { 4035 4083 curLoop[i] = false; … … 4044 4092 }, 4045 4093 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(); 4048 4095 }, 4049 4096 CHILD: function(match){ 4050 if ( match[1] == "nth" ) {4097 if ( match[1] === "nth" ) { 4051 4098 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' 4052 4099 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" || 4054 4101 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); 4055 4102 … … 4080 4127 if ( match[1] === "not" ) { 4081 4128 // 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]) ) { 4083 4130 match[3] = Sizzle(match[3], null, null, curLoop); 4084 4131 } else { … … 4126 4173 }, 4127 4174 header: function(elem){ 4128 return /h\d/i.test( elem.nodeName );4175 return (/h\d/i).test( elem.nodeName ); 4129 4176 }, 4130 4177 text: function(elem){ … … 4153 4200 }, 4154 4201 button: function(elem){ 4155 return "button" === elem.type || elem.nodeName.to UpperCase() === "BUTTON";4202 return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; 4156 4203 }, 4157 4204 input: function(elem){ 4158 return /input|select|textarea|button/i.test(elem.nodeName);4205 return (/input|select|textarea|button/i).test(elem.nodeName); 4159 4206 } 4160 4207 }, … … 4179 4226 }, 4180 4227 nth: function(elem, i, match){ 4181 return match[3] - 0 == i;4228 return match[3] - 0 === i; 4182 4229 }, 4183 4230 eq: function(elem, i, match){ 4184 return match[3] - 0 == i;4231 return match[3] - 0 === i; 4185 4232 } 4186 4233 }, … … 4192 4239 return filter( elem, i, match, array ); 4193 4240 } 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; 4195 4242 } else if ( name === "not" ) { 4196 4243 var not = match[3]; 4197 4244 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 ) { 4200 4247 return false; 4201 4248 } … … 4203 4250 4204 4251 return true; 4252 } else { 4253 Sizzle.error( "Syntax error, unrecognized expression: " + name ); 4205 4254 } 4206 4255 }, … … 4210 4259 case 'only': 4211 4260 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 } 4214 4265 } 4215 if ( type == 'first') return true; 4266 if ( type === "first" ) { 4267 return true; 4268 } 4216 4269 node = elem; 4217 4270 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 } 4220 4275 } 4221 4276 return true; … … 4223 4278 var first = match[2], last = match[3]; 4224 4279 4225 if ( first == 1 && last== 0 ) {4280 if ( first === 1 && last === 0 ) { 4226 4281 return true; 4227 4282 } … … 4241 4296 4242 4297 var diff = elem.nodeIndex - last; 4243 if ( first == 0 ) {4244 return diff == 0;4298 if ( first === 0 ) { 4299 return diff === 0; 4245 4300 } else { 4246 return ( diff % first == 0 && diff / first >= 0 );4301 return ( diff % first === 0 && diff / first >= 0 ); 4247 4302 } 4248 4303 } … … 4252 4307 }, 4253 4308 TAG: function(elem, match){ 4254 return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;4309 return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; 4255 4310 }, 4256 4311 CLASS: function(elem, match){ … … 4280 4335 value && result !== false : 4281 4336 type === "!=" ? 4282 value != check :4337 value !== check : 4283 4338 type === "^=" ? 4284 4339 value.indexOf(check) === 0 : … … 4299 4354 }; 4300 4355 4301 var origPOS = Expr.match.POS; 4356 var origPOS = Expr.match.POS, 4357 fescape = function(all, num){ 4358 return "\\" + (num - 0 + 1); 4359 }; 4302 4360 4303 4361 for ( 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) ); 4305 4364 } 4306 4365 4307 4366 var makeArray = function(array, results) { 4308 array = Array.prototype.slice.call( array );4367 array = Array.prototype.slice.call( array, 0 ); 4309 4368 4310 4369 if ( results ) { … … 4318 4377 // Perform a simple check to determine if the browser is capable of 4319 4378 // 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) 4320 4381 try { 4321 Array.prototype.slice.call( document.documentElement.childNodes );4382 Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; 4322 4383 4323 4384 // Provide a fallback method if it does not work 4324 4385 } catch(e){ 4325 4386 makeArray = function(array, results) { 4326 var ret = results || [] ;4387 var ret = results || [], i = 0; 4327 4388 4328 4389 if ( toString.call(array) === "[object Array]" ) { … … 4330 4391 } else { 4331 4392 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++ ) { 4333 4394 ret.push( array[i] ); 4334 4395 } 4335 4396 } else { 4336 for ( var i = 0; array[i]; i++ ) {4397 for ( ; array[i]; i++ ) { 4337 4398 ret.push( array[i] ); 4338 4399 } … … 4348 4409 if ( document.documentElement.compareDocumentPosition ) { 4349 4410 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 4350 4418 var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; 4351 4419 if ( ret === 0 ) { … … 4356 4424 } else if ( "sourceIndex" in document.documentElement ) { 4357 4425 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 4358 4433 var ret = a.sourceIndex - b.sourceIndex; 4359 4434 if ( ret === 0 ) { … … 4364 4439 } else if ( document.createRange ) { 4365 4440 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 4366 4448 var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); 4367 4449 aRange.setStart(a, 0); … … 4377 4459 } 4378 4460 4461 // Utility function for retreiving the text value of an array of DOM nodes 4462 Sizzle.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 4379 4481 // Check to see if the browser returns elements by name when 4380 4482 // querying by getElementById (and provide a workaround) … … 4382 4484 // We're going to inject a fake input element with a specified name 4383 4485 var form = document.createElement("div"), 4384 id = "script" + (new Date ).getTime();4486 id = "script" + (new Date()).getTime(); 4385 4487 form.innerHTML = "<a name='" + id + "'/>"; 4386 4488 … … 4391 4493 // The workaround has to do additional checks after a getElementById 4392 4494 // Which slows things down for other browsers (hence the branching) 4393 if ( !!document.getElementById( id ) ) {4495 if ( document.getElementById( id ) ) { 4394 4496 Expr.find.ID = function(match, context, isXML){ 4395 4497 if ( typeof context.getElementById !== "undefined" && !isXML ) { … … 4406 4508 4407 4509 root.removeChild( form ); 4510 root = form = null; // release memory in IE 4408 4511 })(); 4409 4512 … … 4446 4549 }; 4447 4550 } 4551 4552 div = null; // release memory in IE 4448 4553 })(); 4449 4554 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 ) { 4555 if ( 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 ) { 4457 4603 return; 4458 4604 } 4459 4605 4460 Sizzle = function(query, context, extra, seed){4461 context = context || document;4462 4463 // Only use querySelectorAll on non-XML documents4464 // (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 4493 4606 Expr.order.splice(1, 0, "CLASS"); 4494 4607 Expr.find.CLASS = function(match, context, isXML) { … … 4497 4610 } 4498 4611 }; 4612 4613 div = null; // release memory in IE 4499 4614 })(); 4500 4615 4501 4616 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 4502 var sibDir = dir == "previousSibling" && !isXML;4503 4617 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 4504 4618 var elem = checkSet[i]; 4505 4619 if ( elem ) { 4506 if ( sibDir && elem.nodeType === 1 ){4507 elem.sizcache = doneName;4508 elem.sizset = i;4509 }4510 4620 elem = elem[dir]; 4511 4621 var match = false; … … 4522 4632 } 4523 4633 4524 if ( elem.nodeName === cur ) {4634 if ( elem.nodeName.toLowerCase() === cur ) { 4525 4635 match = elem; 4526 4636 break; … … 4536 4646 4537 4647 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 4538 var sibDir = dir == "previousSibling" && !isXML;4539 4648 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 4540 4649 var elem = checkSet[i]; 4541 4650 if ( elem ) { 4542 if ( sibDir && elem.nodeType === 1 ) {4543 elem.sizcache = doneName;4544 elem.sizset = i;4545 }4546 4651 elem = elem[dir]; 4547 4652 var match = false; … … 4578 4683 } 4579 4684 4580 var contains = document.compareDocumentPosition ?function(a, b){4581 return a.compareDocumentPosition(b) & 16;4685 Sizzle.contains = document.compareDocumentPosition ? function(a, b){ 4686 return !!(a.compareDocumentPosition(b) & 16); 4582 4687 } : function(a, b){ 4583 4688 return a !== b && (a.contains ? a.contains(b) : true); 4584 4689 }; 4585 4690 4586 var isXML = function(elem){ 4587 return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || 4588 !!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML"; 4691 Sizzle.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; 4589 4696 }; 4590 4697 … … 5134 5241 5135 5242 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; 5150 5270 } 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; 5160 5280 } 5161 5281 }, … … 5315 5435 5316 5436 function setEndPoint(start) { 5317 var point = bookmark[start ? 'start' : 'end'], i, node, offset ;5437 var point = bookmark[start ? 'start' : 'end'], i, node, offset, children; 5318 5438 5319 5439 if (point) { 5320 5440 // 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 } 5323 5447 5324 5448 // Set offset within container node … … 5345 5469 idx = dom.nodeIndex(marker); 5346 5470 } else { 5347 node = marker ;5471 node = marker.firstChild; 5348 5472 idx = 1; 5349 5473 } … … 5355 5479 idx = dom.nodeIndex(marker); 5356 5480 } else { 5357 node = marker ;5481 node = marker.firstChild; 5358 5482 idx = 1; 5359 5483 } … … 5396 5520 }; 5397 5521 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 5398 5531 // Restore start/end points 5399 5532 restoreEndPoint('start'); … … 5401 5534 5402 5535 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); 5405 5538 t.setRng(rng); 5406 5539 } else if (bookmark.name) { … … 8117 8250 8118 8251 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() { 8120 8253 if (!t._focused) { 8121 8254 t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) { … … 10664 10797 // Add node change handlers 10665 10798 t.onMouseUp.add(t.nodeChanged); 10666 t.onClick.add(t.nodeChanged);10799 //t.onClick.add(t.nodeChanged); 10667 10800 t.onKeyUp.add(function(ed, e) { 10668 10801 var c = e.keyCode; … … 10838 10971 10839 10972 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 10840 11022 // Is caracter positon keys 10841 11023 if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) { … … 11129 11311 11130 11312 mceCleanup : function() { 11131 storeSelection(); 11313 var bookmark = selection.getBookmark(); 11314 11132 11315 editor.setContent(editor.getContent({cleanup : TRUE}), {cleanup : TRUE}); 11133 restoreSelection(); 11316 11317 selection.moveToBookmark(bookmark); 11134 11318 }, 11135 11319 … … 11444 11628 FALSE = false; 11445 11629 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 11446 11651 // Checks if the selection/caret is at the end of the specified block element 11447 11652 function isAtEnd(rng, par) { … … 11552 11757 } 11553 11758 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 } 11559 11807 11560 11808 if (isGecko) { … … 12058 12306 12059 12307 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 } 12061 12324 12062 12325 // The caret sometimes gets stuck in Gecko if you delete empty paragraphs … … 12089 12352 } 12090 12353 } 12091 12092 // Gecko generates BR elements here and there, we don't like those so lets remove them12093 function handler(e) {12094 var pr;12095 12096 e = e.target;12097 12098 // A new BR was created in a block element, remove it12099 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 BR12105 // to place the caret at a correct location see bug: #201394312106 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 text12110 if (e.previousSibling || e.nextSibling)12111 ed.dom.remove(e);12112 }12113 };12114 12115 // Listen for new nodes12116 Event._add(b, 'DOMNodeInserted', handler);12117 12118 // Remove listener12119 window.setTimeout(function() {12120 Event._remove(b, 'DOMNodeInserted', handler);12121 }, 1);12122 12354 } 12123 12355 }); … … 12736 12968 if (container.nodeType == 1 || container.nodeValue === "") { 12737 12969 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 } 12743 12979 } 12744 12980 } … … 12946 13182 rng.setEndAfter(node); 12947 13183 12948 applyRngStyle( rng);13184 applyRngStyle(expandRng(rng, formatList)); 12949 13185 } else { 12950 13186 if (!selection.isCollapsed() || !format.inline) { … … 13372 13608 13373 13609 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); 13375 13611 }; 13376 13612 … … 13910 14146 textNode = node.firstChild; 13911 14147 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); 13919 14158 } 13920 14159 }); -
trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/jscripts/tiny_mce/tiny_mce_src.js
r7493 r7729 6 6 majorVersion : '3', 7 7 8 minorVersion : '3. 6',9 10 releaseDate : '2010-0 5-20',8 minorVersion : '3.7', 9 10 releaseDate : '2010-06-10', 11 11 12 12 _init : function() { … … 3290 3290 marker = dom.create('a'); 3291 3291 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 3292 3299 parent.appendChild(marker); 3293 3300 checkRng.moveToElementText(marker); … … 3464 3471 ieRng.moveToElementText(marker); 3465 3472 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); 3467 3477 } else { 3468 3478 ieRng.moveToElementText(sc); … … 3624 3634 (function(){ 3625 3635 3626 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^ [\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,3636 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, 3627 3637 done = 0, 3628 3638 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 }); 3630 3650 3631 3651 var Sizzle = function(selector, context, results, seed) { 3632 3652 results = results || []; 3633 var origContext = context = context || document; 3653 context = context || document; 3654 3655 var origContext = context; 3634 3656 3635 3657 if ( context.nodeType !== 1 && context.nodeType !== 9 ) { … … 3641 3663 } 3642 3664 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; 3644 3667 3645 3668 // 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]; 3650 3675 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 } 3654 3682 } 3655 } 3683 } while ( m ); 3656 3684 3657 3685 if ( parts.length > 1 && origPOS.exec( selector ) ) { … … 3666 3694 selector = parts.shift(); 3667 3695 3668 if ( Expr.relative[ selector ] ) 3696 if ( Expr.relative[ selector ] ) { 3669 3697 selector += parts.shift(); 3670 3698 } 3699 3671 3700 set = posProcess( selector, set ); 3672 3701 } … … 3677 3706 if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && 3678 3707 Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { 3679 varret = Sizzle.find( parts.shift(), context, contextXML );3708 ret = Sizzle.find( parts.shift(), context, contextXML ); 3680 3709 context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; 3681 3710 } 3682 3711 3683 3712 if ( context ) { 3684 varret = seed ?3713 ret = seed ? 3685 3714 { expr: parts.pop(), set: makeArray(seed) } : 3686 3715 Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); … … 3694 3723 3695 3724 while ( parts.length ) { 3696 var cur = parts.pop(), pop = cur; 3725 cur = parts.pop(); 3726 pop = cur; 3697 3727 3698 3728 if ( !Expr.relative[ cur ] ) { … … 3718 3748 3719 3749 if ( !checkSet ) { 3720 throw "Syntax error, unrecognized expression: " + (cur || selector);3750 Sizzle.error( cur || selector ); 3721 3751 } 3722 3752 … … 3725 3755 results.push.apply( results, checkSet ); 3726 3756 } else if ( context && context.nodeType === 1 ) { 3727 for ( vari = 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])) ) { 3729 3759 results.push( set[i] ); 3730 3760 } 3731 3761 } 3732 3762 } else { 3733 for ( vari = 0; checkSet[i] != null; i++ ) {3763 for ( i = 0; checkSet[i] != null; i++ ) { 3734 3764 if ( checkSet[i] && checkSet[i].nodeType === 1 ) { 3735 3765 results.push( set[i] ); … … 3751 3781 Sizzle.uniqueSort = function(results){ 3752 3782 if ( sortOrder ) { 3753 hasDuplicate = false;3783 hasDuplicate = baseHasDuplicate; 3754 3784 results.sort(sortOrder); 3755 3785 … … 3762 3792 } 3763 3793 } 3794 3795 return results; 3764 3796 }; 3765 3797 … … 3769 3801 3770 3802 Sizzle.find = function(expr, context, isXML){ 3771 var set , match;3803 var set; 3772 3804 3773 3805 if ( !expr ) { … … 3778 3810 var type = Expr.order[i], match; 3779 3811 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); 3782 3815 3783 3816 if ( left.substr( left.length - 1 ) !== "\\" ) { … … 3801 3834 Sizzle.filter = function(expr, set, inplace, not){ 3802 3835 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]); 3804 3837 3805 3838 while ( expr && set.length ) { 3806 3839 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]; 3809 3842 anyFound = false; 3810 3843 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 ) { 3812 3851 result = []; 3813 3852 } … … 3860 3899 3861 3900 // Improper expression 3862 if ( expr == old ) {3901 if ( expr === old ) { 3863 3902 if ( anyFound == null ) { 3864 throw "Syntax error, unrecognized expression: " + expr;3903 Sizzle.error( expr ); 3865 3904 } else { 3866 3905 break; … … 3872 3911 3873 3912 return curLoop; 3913 }; 3914 3915 Sizzle.error = function( msg ) { 3916 throw "Syntax error, unrecognized expression: " + msg; 3874 3917 }; 3875 3918 … … 3877 3920 order: [ "ID", "NAME", "TAG" ], 3878 3921 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\))?/ 3887 3930 }, 3931 leftMatch: {}, 3888 3932 attrMap: { 3889 3933 "class": "className", … … 3896 3940 }, 3897 3941 relative: { 3898 "+": function(checkSet, part , isXML){3942 "+": function(checkSet, part){ 3899 3943 var isPartStr = typeof part === "string", 3900 3944 isTag = isPartStr && !/\W/.test(part), 3901 3945 isPartStrNotTag = isPartStr && !isTag; 3902 3946 3903 if ( isTag && !isXML) {3904 part = part.to UpperCase();3947 if ( isTag ) { 3948 part = part.toLowerCase(); 3905 3949 } 3906 3950 … … 3909 3953 while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} 3910 3954 3911 checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?3955 checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? 3912 3956 elem || false : 3913 3957 elem === part; … … 3919 3963 } 3920 3964 }, 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; 3923 3968 3924 3969 if ( isPartStr && !/\W/.test(part) ) { 3925 part = isXML ? part : part.toUpperCase();3926 3927 for ( var i = 0, l = checkSet.length; i < l; i++ ) {3928 varelem = checkSet[i];3970 part = part.toLowerCase(); 3971 3972 for ( ; i < l; i++ ) { 3973 elem = checkSet[i]; 3929 3974 if ( elem ) { 3930 3975 var parent = elem.parentNode; 3931 checkSet[i] = parent.nodeName === part ? parent : false;3976 checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; 3932 3977 } 3933 3978 } 3934 3979 } else { 3935 for ( var i = 0, l = checkSet.length; i < l; i++ ) {3936 varelem = checkSet[i];3980 for ( ; i < l; i++ ) { 3981 elem = checkSet[i]; 3937 3982 if ( elem ) { 3938 3983 checkSet[i] = isPartStr ? … … 3948 3993 }, 3949 3994 "": 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; 3954 4000 checkFn = dirNodeCheck; 3955 4001 } … … 3958 4004 }, 3959 4005 "~": 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; 3964 4011 checkFn = dirNodeCheck; 3965 4012 } … … 3975 4022 } 3976 4023 }, 3977 NAME: function(match, context , isXML){4024 NAME: function(match, context){ 3978 4025 if ( typeof context.getElementsByName !== "undefined" ) { 3979 4026 var ret = [], results = context.getElementsByName(match[1]); … … 4002 4049 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { 4003 4050 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 ) { 4006 4053 result.push( elem ); 4054 } 4007 4055 } else if ( inplace ) { 4008 4056 curLoop[i] = false; … … 4017 4065 }, 4018 4066 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(); 4021 4068 }, 4022 4069 CHILD: function(match){ 4023 if ( match[1] == "nth" ) {4070 if ( match[1] === "nth" ) { 4024 4071 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' 4025 4072 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" || 4027 4074 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); 4028 4075 … … 4053 4100 if ( match[1] === "not" ) { 4054 4101 // 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]) ) { 4056 4103 match[3] = Sizzle(match[3], null, null, curLoop); 4057 4104 } else { … … 4099 4146 }, 4100 4147 header: function(elem){ 4101 return /h\d/i.test( elem.nodeName );4148 return (/h\d/i).test( elem.nodeName ); 4102 4149 }, 4103 4150 text: function(elem){ … … 4126 4173 }, 4127 4174 button: function(elem){ 4128 return "button" === elem.type || elem.nodeName.to UpperCase() === "BUTTON";4175 return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; 4129 4176 }, 4130 4177 input: function(elem){ 4131 return /input|select|textarea|button/i.test(elem.nodeName);4178 return (/input|select|textarea|button/i).test(elem.nodeName); 4132 4179 } 4133 4180 }, … … 4152 4199 }, 4153 4200 nth: function(elem, i, match){ 4154 return match[3] - 0 == i;4201 return match[3] - 0 === i; 4155 4202 }, 4156 4203 eq: function(elem, i, match){ 4157 return match[3] - 0 == i;4204 return match[3] - 0 === i; 4158 4205 } 4159 4206 }, … … 4165 4212 return filter( elem, i, match, array ); 4166 4213 } 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; 4168 4215 } else if ( name === "not" ) { 4169 4216 var not = match[3]; 4170 4217 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 ) { 4173 4220 return false; 4174 4221 } … … 4176 4223 4177 4224 return true; 4225 } else { 4226 Sizzle.error( "Syntax error, unrecognized expression: " + name ); 4178 4227 } 4179 4228 }, … … 4183 4232 case 'only': 4184 4233 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 } 4187 4238 } 4188 if ( type == 'first') return true; 4239 if ( type === "first" ) { 4240 return true; 4241 } 4189 4242 node = elem; 4190 4243 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 } 4193 4248 } 4194 4249 return true; … … 4196 4251 var first = match[2], last = match[3]; 4197 4252 4198 if ( first == 1 && last== 0 ) {4253 if ( first === 1 && last === 0 ) { 4199 4254 return true; 4200 4255 } … … 4214 4269 4215 4270 var diff = elem.nodeIndex - last; 4216 if ( first == 0 ) {4217 return diff == 0;4271 if ( first === 0 ) { 4272 return diff === 0; 4218 4273 } else { 4219 return ( diff % first == 0 && diff / first >= 0 );4274 return ( diff % first === 0 && diff / first >= 0 ); 4220 4275 } 4221 4276 } … … 4225 4280 }, 4226 4281 TAG: function(elem, match){ 4227 return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;4282 return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; 4228 4283 }, 4229 4284 CLASS: function(elem, match){ … … 4253 4308 value && result !== false : 4254 4309 type === "!=" ? 4255 value != check :4310 value !== check : 4256 4311 type === "^=" ? 4257 4312 value.indexOf(check) === 0 : … … 4272 4327 }; 4273 4328 4274 var origPOS = Expr.match.POS; 4329 var origPOS = Expr.match.POS, 4330 fescape = function(all, num){ 4331 return "\\" + (num - 0 + 1); 4332 }; 4275 4333 4276 4334 for ( 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) ); 4278 4337 } 4279 4338 4280 4339 var makeArray = function(array, results) { 4281 array = Array.prototype.slice.call( array );4340 array = Array.prototype.slice.call( array, 0 ); 4282 4341 4283 4342 if ( results ) { … … 4291 4350 // Perform a simple check to determine if the browser is capable of 4292 4351 // 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) 4293 4354 try { 4294 Array.prototype.slice.call( document.documentElement.childNodes );4355 Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; 4295 4356 4296 4357 // Provide a fallback method if it does not work 4297 4358 } catch(e){ 4298 4359 makeArray = function(array, results) { 4299 var ret = results || [] ;4360 var ret = results || [], i = 0; 4300 4361 4301 4362 if ( toString.call(array) === "[object Array]" ) { … … 4303 4364 } else { 4304 4365 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++ ) { 4306 4367 ret.push( array[i] ); 4307 4368 } 4308 4369 } else { 4309 for ( var i = 0; array[i]; i++ ) {4370 for ( ; array[i]; i++ ) { 4310 4371 ret.push( array[i] ); 4311 4372 } … … 4321 4382 if ( document.documentElement.compareDocumentPosition ) { 4322 4383 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 4323 4391 var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; 4324 4392 if ( ret === 0 ) { … … 4329 4397 } else if ( "sourceIndex" in document.documentElement ) { 4330 4398 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 4331 4406 var ret = a.sourceIndex - b.sourceIndex; 4332 4407 if ( ret === 0 ) { … … 4337 4412 } else if ( document.createRange ) { 4338 4413 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 4339 4421 var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); 4340 4422 aRange.setStart(a, 0); … … 4350 4432 } 4351 4433 4434 // Utility function for retreiving the text value of an array of DOM nodes 4435 Sizzle.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 4352 4454 // Check to see if the browser returns elements by name when 4353 4455 // querying by getElementById (and provide a workaround) … … 4355 4457 // We're going to inject a fake input element with a specified name 4356 4458 var form = document.createElement("div"), 4357 id = "script" + (new Date ).getTime();4459 id = "script" + (new Date()).getTime(); 4358 4460 form.innerHTML = "<a name='" + id + "'/>"; 4359 4461 … … 4364 4466 // The workaround has to do additional checks after a getElementById 4365 4467 // Which slows things down for other browsers (hence the branching) 4366 if ( !!document.getElementById( id ) ) {4468 if ( document.getElementById( id ) ) { 4367 4469 Expr.find.ID = function(match, context, isXML){ 4368 4470 if ( typeof context.getElementById !== "undefined" && !isXML ) { … … 4379 4481 4380 4482 root.removeChild( form ); 4483 root = form = null; // release memory in IE 4381 4484 })(); 4382 4485 … … 4419 4522 }; 4420 4523 } 4524 4525 div = null; // release memory in IE 4421 4526 })(); 4422 4527 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 ) { 4528 if ( 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 ) { 4430 4576 return; 4431 4577 } 4432 4578 4433 Sizzle = function(query, context, extra, seed){4434 context = context || document;4435 4436 // Only use querySelectorAll on non-XML documents4437 // (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 4466 4579 Expr.order.splice(1, 0, "CLASS"); 4467 4580 Expr.find.CLASS = function(match, context, isXML) { … … 4470 4583 } 4471 4584 }; 4585 4586 div = null; // release memory in IE 4472 4587 })(); 4473 4588 4474 4589 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 4475 var sibDir = dir == "previousSibling" && !isXML;4476 4590 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 4477 4591 var elem = checkSet[i]; 4478 4592 if ( elem ) { 4479 if ( sibDir && elem.nodeType === 1 ){4480 elem.sizcache = doneName;4481 elem.sizset = i;4482 }4483 4593 elem = elem[dir]; 4484 4594 var match = false; … … 4495 4605 } 4496 4606 4497 if ( elem.nodeName === cur ) {4607 if ( elem.nodeName.toLowerCase() === cur ) { 4498 4608 match = elem; 4499 4609 break; … … 4509 4619 4510 4620 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 4511 var sibDir = dir == "previousSibling" && !isXML;4512 4621 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 4513 4622 var elem = checkSet[i]; 4514 4623 if ( elem ) { 4515 if ( sibDir && elem.nodeType === 1 ) {4516 elem.sizcache = doneName;4517 elem.sizset = i;4518 }4519 4624 elem = elem[dir]; 4520 4625 var match = false; … … 4551 4656 } 4552 4657 4553 var contains = document.compareDocumentPosition ?function(a, b){4554 return a.compareDocumentPosition(b) & 16;4658 Sizzle.contains = document.compareDocumentPosition ? function(a, b){ 4659 return !!(a.compareDocumentPosition(b) & 16); 4555 4660 } : function(a, b){ 4556 4661 return a !== b && (a.contains ? a.contains(b) : true); 4557 4662 }; 4558 4663 4559 var isXML = function(elem){ 4560 return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || 4561 !!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML"; 4664 Sizzle.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; 4562 4669 }; 4563 4670 … … 5107 5214 5108 5215 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; 5123 5243 } 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; 5133 5253 } 5134 5254 }, … … 5288 5408 5289 5409 function setEndPoint(start) { 5290 var point = bookmark[start ? 'start' : 'end'], i, node, offset ;5410 var point = bookmark[start ? 'start' : 'end'], i, node, offset, children; 5291 5411 5292 5412 if (point) { 5293 5413 // 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 } 5296 5420 5297 5421 // Set offset within container node … … 5318 5442 idx = dom.nodeIndex(marker); 5319 5443 } else { 5320 node = marker ;5444 node = marker.firstChild; 5321 5445 idx = 1; 5322 5446 } … … 5328 5452 idx = dom.nodeIndex(marker); 5329 5453 } else { 5330 node = marker ;5454 node = marker.firstChild; 5331 5455 idx = 1; 5332 5456 } … … 5369 5493 }; 5370 5494 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 5371 5504 // Restore start/end points 5372 5505 restoreEndPoint('start'); … … 5374 5507 5375 5508 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); 5378 5511 t.setRng(rng); 5379 5512 } else if (bookmark.name) { … … 8090 8223 8091 8224 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() { 8093 8226 if (!t._focused) { 8094 8227 t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) { … … 10637 10770 // Add node change handlers 10638 10771 t.onMouseUp.add(t.nodeChanged); 10639 t.onClick.add(t.nodeChanged);10772 //t.onClick.add(t.nodeChanged); 10640 10773 t.onKeyUp.add(function(ed, e) { 10641 10774 var c = e.keyCode; … … 10811 10944 10812 10945 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 10813 10995 // Is caracter positon keys 10814 10996 if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) { … … 11102 11284 11103 11285 mceCleanup : function() { 11104 storeSelection(); 11286 var bookmark = selection.getBookmark(); 11287 11105 11288 editor.setContent(editor.getContent({cleanup : TRUE}), {cleanup : TRUE}); 11106 restoreSelection(); 11289 11290 selection.moveToBookmark(bookmark); 11107 11291 }, 11108 11292 … … 11417 11601 FALSE = false; 11418 11602 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 11419 11624 // Checks if the selection/caret is at the end of the specified block element 11420 11625 function isAtEnd(rng, par) { … … 11525 11730 } 11526 11731 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 } 11532 11780 11533 11781 if (isGecko) { … … 12031 12279 12032 12280 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 } 12034 12297 12035 12298 // The caret sometimes gets stuck in Gecko if you delete empty paragraphs … … 12062 12325 } 12063 12326 } 12064 12065 // Gecko generates BR elements here and there, we don't like those so lets remove them12066 function handler(e) {12067 var pr;12068 12069 e = e.target;12070 12071 // A new BR was created in a block element, remove it12072 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 BR12078 // to place the caret at a correct location see bug: #201394312079 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 text12083 if (e.previousSibling || e.nextSibling)12084 ed.dom.remove(e);12085 }12086 };12087 12088 // Listen for new nodes12089 Event._add(b, 'DOMNodeInserted', handler);12090 12091 // Remove listener12092 window.setTimeout(function() {12093 Event._remove(b, 'DOMNodeInserted', handler);12094 }, 1);12095 12327 } 12096 12328 }); … … 12709 12941 if (container.nodeType == 1 || container.nodeValue === "") { 12710 12942 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 } 12716 12952 } 12717 12953 } … … 12919 13155 rng.setEndAfter(node); 12920 13156 12921 applyRngStyle( rng);13157 applyRngStyle(expandRng(rng, formatList)); 12922 13158 } else { 12923 13159 if (!selection.isCollapsed() || !format.inline) { … … 13345 13581 13346 13582 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); 13348 13584 }; 13349 13585 … … 13883 14119 textNode = node.firstChild; 13884 14120 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); 13892 14131 } 13893 14132 }); -
trunk/TinyMCEPlugin/pub/System/TinyMCEPlugin/tinymce/tests/ie_selection.html
r7493 r7729 267 267 equals(rng.endContainer.nodeName, 'BODY'); 268 268 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); 269 284 }); 270 285 } else {
Note: See TracChangeset
for help on using the changeset viewer.
