Version Notes
3.3.7.0
Download this release
Release Info
Developer | Magento Core Team |
Extension | Lib_Js_TinyMCE |
Version | 3.3.7.0 |
Comparing to | |
See all releases |
Code changes from version 3.3.2.0 to 3.3.7.0
- js/tiny_mce/classes/Editor.js +76 -7
- js/tiny_mce/classes/EditorCommands.js +15 -5
- js/tiny_mce/classes/ForceBlocks.js +93 -38
- js/tiny_mce/classes/Formatter.js +62 -33
- js/tiny_mce/classes/adapter/jquery/jquery.tinymce.js +17 -8
- js/tiny_mce/classes/dom/DOMUtils.js +9 -6
- js/tiny_mce/classes/dom/RangeUtils.js +28 -0
- js/tiny_mce/classes/dom/Selection.js +85 -39
- js/tiny_mce/classes/dom/Sizzle.js +234 -137
- js/tiny_mce/classes/dom/TridentSelection.js +99 -92
- js/tiny_mce/classes/tinymce.js +9 -0
- js/tiny_mce/classes/ui/ListBox.js +1 -1
- js/tiny_mce/jquery.tinymce.js +1 -1
- js/tiny_mce/langs/en.js +17 -16
- js/tiny_mce/plugins/autoresize/editor_plugin.js +1 -1
- js/tiny_mce/plugins/autoresize/editor_plugin_src.js +23 -21
- js/tiny_mce/plugins/contextmenu/editor_plugin.js +1 -1
- js/tiny_mce/plugins/contextmenu/editor_plugin_src.js +23 -3
- js/tiny_mce/plugins/fullpage/editor_plugin.js +1 -1
- js/tiny_mce/plugins/fullpage/editor_plugin_src.js +4 -0
- js/tiny_mce/plugins/fullscreen/editor_plugin.js +1 -1
- js/tiny_mce/plugins/fullscreen/editor_plugin_src.js +6 -3
- js/tiny_mce/plugins/legacyoutput/editor_plugin.js +1 -1
- js/tiny_mce/plugins/legacyoutput/editor_plugin_src.js +1 -1
- js/tiny_mce/plugins/paste/editor_plugin.js +1 -1
- js/tiny_mce/plugins/paste/editor_plugin_src.js +18 -7
- js/tiny_mce/plugins/spellchecker/editor_plugin.js +1 -1
- js/tiny_mce/plugins/spellchecker/editor_plugin_src.js +100 -24
- js/tiny_mce/plugins/style/props.htm +2 -5
- js/tiny_mce/plugins/table/editor_plugin.js +1 -1
- js/tiny_mce/plugins/table/editor_plugin_src.js +12 -5
- js/tiny_mce/plugins/table/js/cell.js +1 -1
- js/tiny_mce/plugins/table/js/row.js +1 -1
- js/tiny_mce/plugins/table/js/table.js +2 -2
- js/tiny_mce/plugins/template/template.htm +0 -1
- js/tiny_mce/plugins/wordcount/editor_plugin.js +1 -1
- js/tiny_mce/plugins/wordcount/editor_plugin_src.js +1 -1
- js/tiny_mce/themes/advanced/charmap.htm +0 -1
- js/tiny_mce/themes/advanced/editor_template.js +1 -1
- js/tiny_mce/themes/advanced/editor_template_src.js +38 -11
- js/tiny_mce/themes/advanced/skins/default/ui.css +1 -1
- js/tiny_mce/themes/advanced/skins/o2k7/ui.css +1 -1
- js/tiny_mce/themes/advanced/source_editor.htm +0 -1
- js/tiny_mce/tiny_mce.js +1 -1
- js/tiny_mce/tiny_mce_jquery.js +1 -1
- js/tiny_mce/tiny_mce_jquery_src.js +455 -215
- js/tiny_mce/tiny_mce_prototype.js +0 -1
js/tiny_mce/classes/Editor.js
CHANGED
@@ -480,6 +480,12 @@
|
|
480 |
if (!t.getElement())
|
481 |
return;
|
482 |
|
|
|
|
|
|
|
|
|
|
|
|
|
483 |
// Add hidden input for non input elements inside form elements
|
484 |
if (!/TEXTAREA|INPUT/i.test(t.getElement().nodeName) && s.hidden_input && DOM.getParent(id, 'form'))
|
485 |
DOM.insertAfter(DOM.create('input', {type : 'hidden', name : id}), id);
|
@@ -916,6 +922,7 @@
|
|
916 |
hilitecolor : {inline : 'span', styles : {backgroundColor : '%value'}},
|
917 |
fontname : {inline : 'span', styles : {fontFamily : '%value'}},
|
918 |
fontsize : {inline : 'span', styles : {fontSize : '%value'}},
|
|
|
919 |
blockquote : {block : 'blockquote', wrapper : 1, remove : 'all'},
|
920 |
|
921 |
removeformat : [
|
@@ -1321,13 +1328,28 @@
|
|
1321 |
* @param {Boolean} sf Skip DOM focus. Just set is as the active editor.
|
1322 |
*/
|
1323 |
focus : function(sf) {
|
1324 |
-
var oed, t = this, ce = t.settings.content_editable;
|
1325 |
|
1326 |
if (!sf) {
|
|
|
|
|
|
|
|
|
|
|
|
|
1327 |
// Is not content editable
|
1328 |
if (!ce)
|
1329 |
t.getWin().focus();
|
1330 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1331 |
// #ifdef contentEditable
|
1332 |
|
1333 |
// Content editable mode ends here
|
@@ -2368,7 +2390,7 @@
|
|
2368 |
|
2369 |
// Add node change handlers
|
2370 |
t.onMouseUp.add(t.nodeChanged);
|
2371 |
-
t.onClick.add(t.nodeChanged);
|
2372 |
t.onKeyUp.add(function(ed, e) {
|
2373 |
var c = e.keyCode;
|
2374 |
|
@@ -2389,11 +2411,9 @@
|
|
2389 |
}
|
2390 |
|
2391 |
// Add default shortcuts for gecko
|
2392 |
-
|
2393 |
-
|
2394 |
-
|
2395 |
-
t.addShortcut('ctrl+u', t.getLang('underline_desc'), 'Underline');
|
2396 |
-
}
|
2397 |
|
2398 |
// BlockFormat shortcuts keys
|
2399 |
for (i=1; i<=6; i++)
|
@@ -2544,6 +2564,55 @@
|
|
2544 |
});
|
2545 |
|
2546 |
t.onKeyDown.add(function(ed, e) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2547 |
// Is caracter positon keys
|
2548 |
if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) {
|
2549 |
if (t.undoManager.typing)
|
480 |
if (!t.getElement())
|
481 |
return;
|
482 |
|
483 |
+
// Is a iPad/iPhone, then skip initialization. We need to sniff here since the
|
484 |
+
// browser says it has contentEditable support but there is no visible caret
|
485 |
+
// We will remove this check ones Apple implements full contentEditable support
|
486 |
+
if (tinymce.isIDevice)
|
487 |
+
return;
|
488 |
+
|
489 |
// Add hidden input for non input elements inside form elements
|
490 |
if (!/TEXTAREA|INPUT/i.test(t.getElement().nodeName) && s.hidden_input && DOM.getParent(id, 'form'))
|
491 |
DOM.insertAfter(DOM.create('input', {type : 'hidden', name : id}), id);
|
922 |
hilitecolor : {inline : 'span', styles : {backgroundColor : '%value'}},
|
923 |
fontname : {inline : 'span', styles : {fontFamily : '%value'}},
|
924 |
fontsize : {inline : 'span', styles : {fontSize : '%value'}},
|
925 |
+
fontsize_class : {inline : 'span', attributes : {'class' : '%value'}},
|
926 |
blockquote : {block : 'blockquote', wrapper : 1, remove : 'all'},
|
927 |
|
928 |
removeformat : [
|
1328 |
* @param {Boolean} sf Skip DOM focus. Just set is as the active editor.
|
1329 |
*/
|
1330 |
focus : function(sf) {
|
1331 |
+
var oed, t = this, ce = t.settings.content_editable, ieRng, controlElm, doc = t.getDoc();
|
1332 |
|
1333 |
if (!sf) {
|
1334 |
+
// Get selected control element
|
1335 |
+
ieRng = t.selection.getRng();
|
1336 |
+
if (ieRng.item) {
|
1337 |
+
controlElm = ieRng.item(0);
|
1338 |
+
}
|
1339 |
+
|
1340 |
// Is not content editable
|
1341 |
if (!ce)
|
1342 |
t.getWin().focus();
|
1343 |
|
1344 |
+
// Restore selected control element
|
1345 |
+
// This is needed when for example an image is selected within a
|
1346 |
+
// layer a call to focus will then remove the control selection
|
1347 |
+
if (controlElm && controlElm.ownerDocument == doc) {
|
1348 |
+
ieRng = doc.body.createControlRange();
|
1349 |
+
ieRng.addElement(controlElm);
|
1350 |
+
ieRng.select();
|
1351 |
+
}
|
1352 |
+
|
1353 |
// #ifdef contentEditable
|
1354 |
|
1355 |
// Content editable mode ends here
|
2390 |
|
2391 |
// Add node change handlers
|
2392 |
t.onMouseUp.add(t.nodeChanged);
|
2393 |
+
//t.onClick.add(t.nodeChanged);
|
2394 |
t.onKeyUp.add(function(ed, e) {
|
2395 |
var c = e.keyCode;
|
2396 |
|
2411 |
}
|
2412 |
|
2413 |
// Add default shortcuts for gecko
|
2414 |
+
t.addShortcut('ctrl+b', t.getLang('bold_desc'), 'Bold');
|
2415 |
+
t.addShortcut('ctrl+i', t.getLang('italic_desc'), 'Italic');
|
2416 |
+
t.addShortcut('ctrl+u', t.getLang('underline_desc'), 'Underline');
|
|
|
|
|
2417 |
|
2418 |
// BlockFormat shortcuts keys
|
2419 |
for (i=1; i<=6; i++)
|
2564 |
});
|
2565 |
|
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 |
+
|
2616 |
// Is caracter positon keys
|
2617 |
if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) {
|
2618 |
if (t.undoManager.typing)
|
js/tiny_mce/classes/EditorCommands.js
CHANGED
@@ -155,7 +155,7 @@
|
|
155 |
}
|
156 |
|
157 |
// Present alert message about clipboard access not being available
|
158 |
-
if (failed || !doc.
|
159 |
if (tinymce.isGecko) {
|
160 |
editor.windowManager.confirm(editor.getLang('clipboard_msg'), function(state) {
|
161 |
if (state)
|
@@ -250,16 +250,18 @@
|
|
250 |
},
|
251 |
|
252 |
mceCleanup : function() {
|
253 |
-
|
|
|
254 |
editor.setContent(editor.getContent({cleanup : TRUE}), {cleanup : TRUE});
|
255 |
-
|
|
|
256 |
},
|
257 |
|
258 |
mceRemoveNode : function(command, ui, value) {
|
259 |
var node = value || selection.getNode();
|
260 |
|
261 |
// Make sure that the body node isn't removed
|
262 |
-
if (node !=
|
263 |
storeSelection();
|
264 |
editor.dom.remove(node, TRUE);
|
265 |
restoreSelection();
|
@@ -364,8 +366,16 @@
|
|
364 |
if (value.href)
|
365 |
dom.setAttribs(link, value);
|
366 |
else
|
367 |
-
|
368 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
369 |
}
|
370 |
});
|
371 |
|
155 |
}
|
156 |
|
157 |
// Present alert message about clipboard access not being available
|
158 |
+
if (failed || !doc.queryCommandSupported(command)) {
|
159 |
if (tinymce.isGecko) {
|
160 |
editor.windowManager.confirm(editor.getLang('clipboard_msg'), function(state) {
|
161 |
if (state)
|
250 |
},
|
251 |
|
252 |
mceCleanup : function() {
|
253 |
+
var bookmark = selection.getBookmark();
|
254 |
+
|
255 |
editor.setContent(editor.getContent({cleanup : TRUE}), {cleanup : TRUE});
|
256 |
+
|
257 |
+
selection.moveToBookmark(bookmark);
|
258 |
},
|
259 |
|
260 |
mceRemoveNode : function(command, ui, value) {
|
261 |
var node = value || selection.getNode();
|
262 |
|
263 |
// Make sure that the body node isn't removed
|
264 |
+
if (node != editor.getBody()) {
|
265 |
storeSelection();
|
266 |
editor.dom.remove(node, TRUE);
|
267 |
restoreSelection();
|
366 |
if (value.href)
|
367 |
dom.setAttribs(link, value);
|
368 |
else
|
369 |
+
editor.dom.remove(link, TRUE);
|
370 |
}
|
371 |
+
},
|
372 |
+
|
373 |
+
selectAll : function() {
|
374 |
+
var root = dom.getRoot();
|
375 |
+
var rng = dom.createRng();
|
376 |
+
rng.setStart(root, 0);
|
377 |
+
rng.setEnd(root, root.childNodes.length);
|
378 |
+
editor.selection.setRng(rng);
|
379 |
}
|
380 |
});
|
381 |
|
js/tiny_mce/classes/ForceBlocks.js
CHANGED
@@ -19,6 +19,27 @@
|
|
19 |
TRUE = true,
|
20 |
FALSE = false;
|
21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
// Checks if the selection/caret is at the end of the specified block element
|
23 |
function isAtEnd(rng, par) {
|
24 |
var rng2 = par.ownerDocument.createRange();
|
@@ -130,11 +151,54 @@
|
|
130 |
}
|
131 |
}
|
132 |
|
133 |
-
if (
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
138 |
|
139 |
if (isGecko) {
|
140 |
ed.onKeyDown.add(function(ed, e) {
|
@@ -175,7 +239,7 @@
|
|
175 |
};
|
176 |
|
177 |
ed.onKeyPress.add(function(ed, e) {
|
178 |
-
if (e.keyCode == 13 && (e.shiftKey || s.force_br_newlines)) {
|
179 |
insertBr(ed);
|
180 |
Event.cancel(e);
|
181 |
}
|
@@ -285,6 +349,13 @@
|
|
285 |
}
|
286 |
}
|
287 |
} else {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
288 |
tr = d.body.createTextRange();
|
289 |
tr.moveToElementText(b);
|
290 |
tr.collapse(1);
|
@@ -629,7 +700,22 @@
|
|
629 |
},
|
630 |
|
631 |
backspaceDelete : function(e, bs) {
|
632 |
-
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;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
633 |
|
634 |
// The caret sometimes gets stuck in Gecko if you delete empty paragraphs
|
635 |
// This workaround removes the element by hand and moves the caret to the previous element
|
@@ -660,37 +746,6 @@
|
|
660 |
}
|
661 |
}
|
662 |
}
|
663 |
-
|
664 |
-
// Gecko generates BR elements here and there, we don't like those so lets remove them
|
665 |
-
function handler(e) {
|
666 |
-
var pr;
|
667 |
-
|
668 |
-
e = e.target;
|
669 |
-
|
670 |
-
// A new BR was created in a block element, remove it
|
671 |
-
if (e && e.parentNode && e.nodeName == 'BR' && (n = t.getParentBlock(e))) {
|
672 |
-
pr = e.previousSibling;
|
673 |
-
|
674 |
-
Event.remove(b, 'DOMNodeInserted', handler);
|
675 |
-
|
676 |
-
// Is there whitespace at the end of the node before then we might need the pesky BR
|
677 |
-
// to place the caret at a correct location see bug: #2013943
|
678 |
-
if (pr && pr.nodeType == 3 && /\s+$/.test(pr.nodeValue))
|
679 |
-
return;
|
680 |
-
|
681 |
-
// Only remove BR elements that got inserted in the middle of the text
|
682 |
-
if (e.previousSibling || e.nextSibling)
|
683 |
-
ed.dom.remove(e);
|
684 |
-
}
|
685 |
-
};
|
686 |
-
|
687 |
-
// Listen for new nodes
|
688 |
-
Event._add(b, 'DOMNodeInserted', handler);
|
689 |
-
|
690 |
-
// Remove listener
|
691 |
-
window.setTimeout(function() {
|
692 |
-
Event._remove(b, 'DOMNodeInserted', handler);
|
693 |
-
}, 1);
|
694 |
}
|
695 |
});
|
696 |
})(tinymce);
|
19 |
TRUE = true,
|
20 |
FALSE = false;
|
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 |
+
|
43 |
// Checks if the selection/caret is at the end of the specified block element
|
44 |
function isAtEnd(rng, par) {
|
45 |
var rng2 = par.ownerDocument.createRange();
|
151 |
}
|
152 |
}
|
153 |
|
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 |
+
}
|
202 |
|
203 |
if (isGecko) {
|
204 |
ed.onKeyDown.add(function(ed, e) {
|
239 |
};
|
240 |
|
241 |
ed.onKeyPress.add(function(ed, e) {
|
242 |
+
if (e.keyCode == 13 && (e.shiftKey || (s.force_br_newlines && !dom.getParent(selection.getNode(), 'h1,h2,h3,h4,h5,h6,ol,ul')))) {
|
243 |
insertBr(ed);
|
244 |
Event.cancel(e);
|
245 |
}
|
349 |
}
|
350 |
}
|
351 |
} else {
|
352 |
+
// Force control range into text range
|
353 |
+
if (r.item) {
|
354 |
+
tr = d.body.createTextRange();
|
355 |
+
tr.moveToElementText(r.item(0));
|
356 |
+
r = tr;
|
357 |
+
}
|
358 |
+
|
359 |
tr = d.body.createTextRange();
|
360 |
tr.moveToElementText(b);
|
361 |
tr.collapse(1);
|
700 |
},
|
701 |
|
702 |
backspaceDelete : function(e, bs) {
|
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 |
+
}
|
719 |
|
720 |
// The caret sometimes gets stuck in Gecko if you delete empty paragraphs
|
721 |
// This workaround removes the element by hand and moves the caret to the previous element
|
746 |
}
|
747 |
}
|
748 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
749 |
}
|
750 |
});
|
751 |
})(tinymce);
|
js/tiny_mce/classes/Formatter.js
CHANGED
@@ -141,11 +141,16 @@
|
|
141 |
|
142 |
// Move startContainer/startOffset in to a suitable node
|
143 |
if (container.nodeType == 1 || container.nodeValue === "") {
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
|
|
|
|
|
|
|
|
|
|
149 |
}
|
150 |
}
|
151 |
}
|
@@ -227,7 +232,7 @@
|
|
227 |
}
|
228 |
});
|
229 |
|
230 |
-
//
|
231 |
if (!format.inline || found) {
|
232 |
currentWrapElm = 0;
|
233 |
return;
|
@@ -320,14 +325,23 @@
|
|
320 |
});
|
321 |
});
|
322 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
323 |
// Look for parent with similar style format
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
|
|
|
|
331 |
|
332 |
// Merge next and previous siblings if they are similar <b>text</b><b>text</b> becomes <b>texttext</b>
|
333 |
if (node) {
|
@@ -345,7 +359,7 @@
|
|
345 |
rng.setStartBefore(node);
|
346 |
rng.setEndAfter(node);
|
347 |
|
348 |
-
applyRngStyle(rng);
|
349 |
} else {
|
350 |
if (!selection.isCollapsed() || !format.inline) {
|
351 |
// Apply formatting to selection
|
@@ -462,7 +476,13 @@
|
|
462 |
var node = dom.get(start ? '_start' : '_end'),
|
463 |
out = node[start ? 'firstChild' : 'lastChild'];
|
464 |
|
465 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
466 |
|
467 |
return out;
|
468 |
};
|
@@ -525,7 +545,7 @@
|
|
525 |
};
|
526 |
|
527 |
/**
|
528 |
-
* Toggles the
|
529 |
*
|
530 |
* @method toggle
|
531 |
* @param {String} name Name of format to apply/remove.
|
@@ -546,9 +566,10 @@
|
|
546 |
* @param {Node} node Node to check the format on.
|
547 |
* @param {String} name Format name to check.
|
548 |
* @param {Object} vars Optional list of variables to replace before checking it.
|
|
|
549 |
* @return {Object} Returns the format object it matches or undefined if it doesn't match.
|
550 |
*/
|
551 |
-
function matchNode(node, name, vars) {
|
552 |
var formatList = get(name), format, i, classes;
|
553 |
|
554 |
function matchItems(node, format, item_name) {
|
@@ -565,7 +586,10 @@
|
|
565 |
else
|
566 |
value = getStyle(node, key);
|
567 |
|
568 |
-
if (!
|
|
|
|
|
|
|
569 |
return;
|
570 |
}
|
571 |
}
|
@@ -603,7 +627,7 @@
|
|
603 |
};
|
604 |
|
605 |
/**
|
606 |
-
* Matches the current selection or
|
607 |
*
|
608 |
* @method match
|
609 |
* @param {String} name Name of format to match.
|
@@ -617,7 +641,7 @@
|
|
617 |
function matchParents(node) {
|
618 |
// Find first node with similar format settings
|
619 |
node = dom.getParent(node, function(node) {
|
620 |
-
return !!matchNode(node, name, vars);
|
621 |
});
|
622 |
|
623 |
// Do an exact check on the similar format element
|
@@ -764,7 +788,7 @@
|
|
764 |
* Checks if the specified nodes name matches the format inline/block or selector.
|
765 |
*
|
766 |
* @private
|
767 |
-
* @param {Node} node Node to match
|
768 |
* @param {Object} format Format object o match with.
|
769 |
* @return {boolean} true/false if the format matches.
|
770 |
*/
|
@@ -844,7 +868,7 @@
|
|
844 |
};
|
845 |
|
846 |
function isWhiteSpaceNode(node) {
|
847 |
-
return node && node.nodeType === 3 &&
|
848 |
};
|
849 |
|
850 |
function wrap(node, name, attrs) {
|
@@ -1042,7 +1066,7 @@
|
|
1042 |
* @param {Object} format Format object with items to remove from node.
|
1043 |
* @param {Object} vars Name/value object with variables to apply to format.
|
1044 |
* @param {Node} node Node to remove the format styles on.
|
1045 |
-
* @param {Node} compare_node Optional compare node, if
|
1046 |
* @return {Boolean} True/false if the node was removed or not.
|
1047 |
*/
|
1048 |
function removeFormat(format, vars, node, compare_node) {
|
@@ -1252,7 +1276,7 @@
|
|
1252 |
*
|
1253 |
* @private
|
1254 |
* @param {Node} node1 First node to compare with.
|
1255 |
-
* @param {Node} node2
|
1256 |
* @return {boolean} True/false if the nodes are the same or not.
|
1257 |
*/
|
1258 |
function compareElements(node1, node2) {
|
@@ -1381,7 +1405,7 @@
|
|
1381 |
* @return {boolean} True/false if the node is a text block.
|
1382 |
*/
|
1383 |
function isTextBlock(name) {
|
1384 |
-
return /^(h[1-6]|p|div|pre|address)$/.test(name);
|
1385 |
};
|
1386 |
|
1387 |
function getContainer(rng, start) {
|
@@ -1447,6 +1471,7 @@
|
|
1447 |
// Pending apply or remove formats
|
1448 |
if (hasPending()) {
|
1449 |
ed.getDoc().execCommand('FontName', false, 'mceinline');
|
|
|
1450 |
|
1451 |
// IE will convert the current word
|
1452 |
each(dom.select('font,span'), function(node) {
|
@@ -1466,21 +1491,25 @@
|
|
1466 |
|
1467 |
each('onKeyDown,onKeyUp,onKeyPress,onMouseUp'.split(','), function(event) {
|
1468 |
ed[event].addToTop(function(ed, e) {
|
1469 |
-
|
|
|
1470 |
each(dom.select('font,span'), function(node) {
|
1471 |
-
var
|
1472 |
|
1473 |
// Look for marker
|
1474 |
if (isCaretNode(node)) {
|
1475 |
textNode = node.firstChild;
|
1476 |
|
1477 |
-
|
|
|
1478 |
|
1479 |
-
|
1480 |
-
|
1481 |
-
|
1482 |
-
|
1483 |
-
|
|
|
|
|
1484 |
}
|
1485 |
});
|
1486 |
|
141 |
|
142 |
// Move startContainer/startOffset in to a suitable node
|
143 |
if (container.nodeType == 1 || container.nodeValue === "") {
|
144 |
+
container = container.nodeType == 1 ? container.childNodes[offset] : container;
|
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 |
+
}
|
154 |
}
|
155 |
}
|
156 |
}
|
232 |
}
|
233 |
});
|
234 |
|
235 |
+
// Continue processing if a selector match wasn't found and a inline element is defined
|
236 |
if (!format.inline || found) {
|
237 |
currentWrapElm = 0;
|
238 |
return;
|
325 |
});
|
326 |
});
|
327 |
|
328 |
+
// Remove child if direct parent is of same type
|
329 |
+
if (matchNode(node.parentNode, name, vars)) {
|
330 |
+
dom.remove(node, 1);
|
331 |
+
node = 0;
|
332 |
+
return TRUE;
|
333 |
+
}
|
334 |
+
|
335 |
// Look for parent with similar style format
|
336 |
+
if (format.merge_with_parents) {
|
337 |
+
dom.getParent(node.parentNode, function(parent) {
|
338 |
+
if (matchNode(parent, name, vars)) {
|
339 |
+
dom.remove(node, 1);
|
340 |
+
node = 0;
|
341 |
+
return TRUE;
|
342 |
+
}
|
343 |
+
});
|
344 |
+
}
|
345 |
|
346 |
// Merge next and previous siblings if they are similar <b>text</b><b>text</b> becomes <b>texttext</b>
|
347 |
if (node) {
|
359 |
rng.setStartBefore(node);
|
360 |
rng.setEndAfter(node);
|
361 |
|
362 |
+
applyRngStyle(expandRng(rng, formatList));
|
363 |
} else {
|
364 |
if (!selection.isCollapsed() || !format.inline) {
|
365 |
// Apply formatting to selection
|
476 |
var node = dom.get(start ? '_start' : '_end'),
|
477 |
out = node[start ? 'firstChild' : 'lastChild'];
|
478 |
|
479 |
+
// If the end is placed within the start the result will be removed
|
480 |
+
// So this checks if the out node is a bookmark node if it is it
|
481 |
+
// checks for another more suitable node
|
482 |
+
if (isBookmarkNode(out))
|
483 |
+
out = out[start ? 'firstChild' : 'lastChild'];
|
484 |
+
|
485 |
+
dom.remove(node, true);
|
486 |
|
487 |
return out;
|
488 |
};
|
545 |
};
|
546 |
|
547 |
/**
|
548 |
+
* Toggles the specified format on/off.
|
549 |
*
|
550 |
* @method toggle
|
551 |
* @param {String} name Name of format to apply/remove.
|
566 |
* @param {Node} node Node to check the format on.
|
567 |
* @param {String} name Format name to check.
|
568 |
* @param {Object} vars Optional list of variables to replace before checking it.
|
569 |
+
* @param {Boolean} similar Match format that has similar properties.
|
570 |
* @return {Object} Returns the format object it matches or undefined if it doesn't match.
|
571 |
*/
|
572 |
+
function matchNode(node, name, vars, similar) {
|
573 |
var formatList = get(name), format, i, classes;
|
574 |
|
575 |
function matchItems(node, format, item_name) {
|
586 |
else
|
587 |
value = getStyle(node, key);
|
588 |
|
589 |
+
if (similar && !value && !format.exact)
|
590 |
+
return;
|
591 |
+
|
592 |
+
if ((!similar || format.exact) && !isEq(value, replaceVars(items[key], vars)))
|
593 |
return;
|
594 |
}
|
595 |
}
|
627 |
};
|
628 |
|
629 |
/**
|
630 |
+
* Matches the current selection or specified node against the specified format name.
|
631 |
*
|
632 |
* @method match
|
633 |
* @param {String} name Name of format to match.
|
641 |
function matchParents(node) {
|
642 |
// Find first node with similar format settings
|
643 |
node = dom.getParent(node, function(node) {
|
644 |
+
return !!matchNode(node, name, vars, true);
|
645 |
});
|
646 |
|
647 |
// Do an exact check on the similar format element
|
788 |
* Checks if the specified nodes name matches the format inline/block or selector.
|
789 |
*
|
790 |
* @private
|
791 |
+
* @param {Node} node Node to match against the specified format.
|
792 |
* @param {Object} format Format object o match with.
|
793 |
* @return {boolean} true/false if the format matches.
|
794 |
*/
|
868 |
};
|
869 |
|
870 |
function isWhiteSpaceNode(node) {
|
871 |
+
return node && node.nodeType === 3 && /^([\s\r\n]+|)$/.test(node.nodeValue);
|
872 |
};
|
873 |
|
874 |
function wrap(node, name, attrs) {
|
1066 |
* @param {Object} format Format object with items to remove from node.
|
1067 |
* @param {Object} vars Name/value object with variables to apply to format.
|
1068 |
* @param {Node} node Node to remove the format styles on.
|
1069 |
+
* @param {Node} compare_node Optional compare node, if specified the styles will be compared to that node.
|
1070 |
* @return {Boolean} True/false if the node was removed or not.
|
1071 |
*/
|
1072 |
function removeFormat(format, vars, node, compare_node) {
|
1276 |
*
|
1277 |
* @private
|
1278 |
* @param {Node} node1 First node to compare with.
|
1279 |
+
* @param {Node} node2 Second node to compare with.
|
1280 |
* @return {boolean} True/false if the nodes are the same or not.
|
1281 |
*/
|
1282 |
function compareElements(node1, node2) {
|
1405 |
* @return {boolean} True/false if the node is a text block.
|
1406 |
*/
|
1407 |
function isTextBlock(name) {
|
1408 |
+
return /^(h[1-6]|p|div|pre|address|dl|dt|dd)$/.test(name);
|
1409 |
};
|
1410 |
|
1411 |
function getContainer(rng, start) {
|
1471 |
// Pending apply or remove formats
|
1472 |
if (hasPending()) {
|
1473 |
ed.getDoc().execCommand('FontName', false, 'mceinline');
|
1474 |
+
pendingFormats.lastRng = selection.getRng();
|
1475 |
|
1476 |
// IE will convert the current word
|
1477 |
each(dom.select('font,span'), function(node) {
|
1491 |
|
1492 |
each('onKeyDown,onKeyUp,onKeyPress,onMouseUp'.split(','), function(event) {
|
1493 |
ed[event].addToTop(function(ed, e) {
|
1494 |
+
// Do we have pending formats and is the selection moved has moved
|
1495 |
+
if (hasPending() && !tinymce.dom.RangeUtils.compareRanges(pendingFormats.lastRng, selection.getRng())) {
|
1496 |
each(dom.select('font,span'), function(node) {
|
1497 |
+
var textNode, rng;
|
1498 |
|
1499 |
// Look for marker
|
1500 |
if (isCaretNode(node)) {
|
1501 |
textNode = node.firstChild;
|
1502 |
|
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);
|
1513 |
}
|
1514 |
});
|
1515 |
|
js/tiny_mce/classes/adapter/jquery/jquery.tinymce.js
CHANGED
@@ -19,7 +19,7 @@
|
|
19 |
|
20 |
// No match then just ignore the call
|
21 |
if (!self.length)
|
22 |
-
return;
|
23 |
|
24 |
// Get editor instance
|
25 |
if (!settings)
|
@@ -91,7 +91,8 @@
|
|
91 |
|
92 |
// Setup tinyMCEPreInit object this will later be used by the TinyMCE
|
93 |
// core script to locate other resources like CSS files, dialogs etc
|
94 |
-
|
|
|
95 |
base : base,
|
96 |
suffix : suffix,
|
97 |
query : query
|
@@ -143,6 +144,11 @@
|
|
143 |
success : function() {
|
144 |
tinymce.dom.Event.domLoaded = 1;
|
145 |
lazyLoading = 2;
|
|
|
|
|
|
|
|
|
|
|
146 |
init();
|
147 |
|
148 |
$.each(delayedInits, function(i, init) {
|
@@ -157,6 +163,8 @@
|
|
157 |
else
|
158 |
init();
|
159 |
}
|
|
|
|
|
160 |
};
|
161 |
|
162 |
// Add :tinymce psuedo selector this will select elements that has been converted into editor instances
|
@@ -242,20 +250,21 @@
|
|
242 |
var self = this;
|
243 |
|
244 |
if (!containsTinyMCE(self))
|
245 |
-
return origFn.
|
246 |
|
247 |
if (value !== undefined) {
|
248 |
loadOrSave.call(self.filter(":tinymce"), value);
|
249 |
-
origFn.
|
250 |
|
251 |
return self; // return original set for chaining
|
252 |
} else {
|
253 |
var ret = "";
|
254 |
-
|
|
|
255 |
(textProc ? self : self.eq(0)).each(function(i, node) {
|
256 |
var ed = tinyMCEInstance(node);
|
257 |
|
258 |
-
ret += ed ? (textProc ? ed.getContent().replace(/<(?:"[^"]*"|'[^']*'|[^'">])*>/g, "") : ed.getContent()) : origFn.
|
259 |
});
|
260 |
|
261 |
return ret;
|
@@ -272,7 +281,7 @@
|
|
272 |
var self = this;
|
273 |
|
274 |
if (!containsTinyMCE(self))
|
275 |
-
return origFn.
|
276 |
|
277 |
if (value !== undefined) {
|
278 |
self.filter(":tinymce").each(function(i, node) {
|
@@ -281,7 +290,7 @@
|
|
281 |
ed && ed.setContent(prepend ? value + ed.getContent() : ed.getContent() + value);
|
282 |
});
|
283 |
|
284 |
-
origFn.
|
285 |
|
286 |
return self; // return original set for chaining
|
287 |
}
|
19 |
|
20 |
// No match then just ignore the call
|
21 |
if (!self.length)
|
22 |
+
return self;
|
23 |
|
24 |
// Get editor instance
|
25 |
if (!settings)
|
91 |
|
92 |
// Setup tinyMCEPreInit object this will later be used by the TinyMCE
|
93 |
// core script to locate other resources like CSS files, dialogs etc
|
94 |
+
// You can also predefined a tinyMCEPreInit object and then it will use that instead
|
95 |
+
win.tinyMCEPreInit = win.tinyMCEPreInit || {
|
96 |
base : base,
|
97 |
suffix : suffix,
|
98 |
query : query
|
144 |
success : function() {
|
145 |
tinymce.dom.Event.domLoaded = 1;
|
146 |
lazyLoading = 2;
|
147 |
+
|
148 |
+
// Execute callback after mainscript has been loaded and before the initialization occurs
|
149 |
+
if (settings.script_loaded)
|
150 |
+
settings.script_loaded();
|
151 |
+
|
152 |
init();
|
153 |
|
154 |
$.each(delayedInits, function(i, init) {
|
163 |
else
|
164 |
init();
|
165 |
}
|
166 |
+
|
167 |
+
return self;
|
168 |
};
|
169 |
|
170 |
// Add :tinymce psuedo selector this will select elements that has been converted into editor instances
|
250 |
var self = this;
|
251 |
|
252 |
if (!containsTinyMCE(self))
|
253 |
+
return origFn.apply(self, arguments);
|
254 |
|
255 |
if (value !== undefined) {
|
256 |
loadOrSave.call(self.filter(":tinymce"), value);
|
257 |
+
origFn.apply(self.not(":tinymce"), arguments);
|
258 |
|
259 |
return self; // return original set for chaining
|
260 |
} else {
|
261 |
var ret = "";
|
262 |
+
var args = arguments;
|
263 |
+
|
264 |
(textProc ? self : self.eq(0)).each(function(i, node) {
|
265 |
var ed = tinyMCEInstance(node);
|
266 |
|
267 |
+
ret += ed ? (textProc ? ed.getContent().replace(/<(?:"[^"]*"|'[^']*'|[^'">])*>/g, "") : ed.getContent()) : origFn.apply($(node), args);
|
268 |
});
|
269 |
|
270 |
return ret;
|
281 |
var self = this;
|
282 |
|
283 |
if (!containsTinyMCE(self))
|
284 |
+
return origFn.apply(self, arguments);
|
285 |
|
286 |
if (value !== undefined) {
|
287 |
self.filter(":tinymce").each(function(i, node) {
|
290 |
ed && ed.setContent(prepend ? value + ed.getContent() : ed.getContent() + value);
|
291 |
});
|
292 |
|
293 |
+
origFn.apply(self.not(":tinymce"), arguments);
|
294 |
|
295 |
return self; // return original set for chaining
|
296 |
}
|
js/tiny_mce/classes/dom/DOMUtils.js
CHANGED
@@ -441,7 +441,7 @@
|
|
441 |
if (keep_children) {
|
442 |
while (child = node.firstChild) {
|
443 |
// IE 8 will crash if you don't remove completely empty text nodes
|
444 |
-
if (child.nodeType !== 3 || child.nodeValue)
|
445 |
parent.insertBefore(child, node);
|
446 |
else
|
447 |
node.removeChild(child);
|
@@ -512,7 +512,7 @@
|
|
512 |
* @method getStyle
|
513 |
* @param {String/Element} n HTML element or element id string to get style from.
|
514 |
* @param {String} na Style name to return.
|
515 |
-
* @param {
|
516 |
* @return {String} Current style or computed style value of a element.
|
517 |
*/
|
518 |
getStyle : function(n, na, c) {
|
@@ -1226,7 +1226,7 @@
|
|
1226 |
// So if we replace the p elements with divs and mark them and then replace them back to paragraphs
|
1227 |
// after we use innerHTML we can fix the DOM tree
|
1228 |
h = h.replace(/<p ([^>]+)>|<p>/ig, '<div $1 _mce_tmp="1">');
|
1229 |
-
h = h.replace(/<\/p>/
|
1230 |
|
1231 |
// Set the new HTML with DIVs
|
1232 |
set();
|
@@ -1857,10 +1857,13 @@
|
|
1857 |
for (lastNodeType = node.nodeType, node = node.previousSibling, lastNode = node; node; node = node.previousSibling) {
|
1858 |
nodeType = node.nodeType;
|
1859 |
|
1860 |
-
//
|
1861 |
-
if (
|
1862 |
-
|
|
|
|
|
1863 |
|
|
|
1864 |
lastNodeType = nodeType;
|
1865 |
}
|
1866 |
}
|
441 |
if (keep_children) {
|
442 |
while (child = node.firstChild) {
|
443 |
// IE 8 will crash if you don't remove completely empty text nodes
|
444 |
+
if (!tinymce.isIE || child.nodeType !== 3 || child.nodeValue)
|
445 |
parent.insertBefore(child, node);
|
446 |
else
|
447 |
node.removeChild(child);
|
512 |
* @method getStyle
|
513 |
* @param {String/Element} n HTML element or element id string to get style from.
|
514 |
* @param {String} na Style name to return.
|
515 |
+
* @param {Boolean} c Computed style.
|
516 |
* @return {String} Current style or computed style value of a element.
|
517 |
*/
|
518 |
getStyle : function(n, na, c) {
|
1226 |
// So if we replace the p elements with divs and mark them and then replace them back to paragraphs
|
1227 |
// after we use innerHTML we can fix the DOM tree
|
1228 |
h = h.replace(/<p ([^>]+)>|<p>/ig, '<div $1 _mce_tmp="1">');
|
1229 |
+
h = h.replace(/<\/p>/gi, '</div>');
|
1230 |
|
1231 |
// Set the new HTML with DIVs
|
1232 |
set();
|
1857 |
for (lastNodeType = node.nodeType, node = node.previousSibling, lastNode = node; node; node = node.previousSibling) {
|
1858 |
nodeType = node.nodeType;
|
1859 |
|
1860 |
+
// Normalize text nodes
|
1861 |
+
if (normalized && nodeType == 3) {
|
1862 |
+
if (nodeType == lastNodeType || !node.nodeValue.length)
|
1863 |
+
continue;
|
1864 |
+
}
|
1865 |
|
1866 |
+
idx++;
|
1867 |
lastNodeType = nodeType;
|
1868 |
}
|
1869 |
}
|
js/tiny_mce/classes/dom/RangeUtils.js
CHANGED
@@ -197,4 +197,32 @@
|
|
197 |
};
|
198 |
*/
|
199 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
})(tinymce);
|
197 |
};
|
198 |
*/
|
199 |
};
|
200 |
+
|
201 |
+
/**
|
202 |
+
* Compares two ranges and checks if they are equal.
|
203 |
+
*
|
204 |
+
* @static
|
205 |
+
* @param {DOMRange} rng1 First range to compare.
|
206 |
+
* @param {DOMRange} rng2 First range to compare.
|
207 |
+
* @return {Boolean} true/false if the ranges are equal.
|
208 |
+
*/
|
209 |
+
tinymce.dom.RangeUtils.compareRanges = function(rng1, rng2) {
|
210 |
+
if (rng1 && rng2) {
|
211 |
+
// Compare native IE ranges
|
212 |
+
if (rng1.item || rng1.duplicate) {
|
213 |
+
// Both are control ranges and the selected element matches
|
214 |
+
if (rng1.item && rng2.item && rng1.item(0) === rng2.item(0))
|
215 |
+
return true;
|
216 |
+
|
217 |
+
// Both are text ranges and the range matches
|
218 |
+
if (rng1.isEqual && rng2.isEqual && rng2.isEqual(rng1))
|
219 |
+
return true;
|
220 |
+
} else {
|
221 |
+
// Compare w3c ranges
|
222 |
+
return rng1.startContainer == rng2.startContainer && rng1.startOffset == rng2.startOffset;
|
223 |
+
}
|
224 |
+
}
|
225 |
+
|
226 |
+
return false;
|
227 |
+
};
|
228 |
})(tinymce);
|
js/tiny_mce/classes/dom/Selection.js
CHANGED
@@ -125,17 +125,21 @@
|
|
125 |
h += '<span id="__caret">_</span>';
|
126 |
|
127 |
// Delete and insert new node
|
128 |
-
|
|
|
129 |
// WebKit will fail if the body is empty since the range is then invalid and it can't insert contents
|
130 |
d.body.innerHTML = h;
|
131 |
} else {
|
132 |
r.deleteContents();
|
133 |
-
|
|
|
|
|
|
|
|
|
134 |
}
|
135 |
|
136 |
// Move to caret marker
|
137 |
c = t.dom.get('__caret');
|
138 |
-
|
139 |
// Make sure we wrap it compleatly, Opera fails with a simple select call
|
140 |
r = d.createRange();
|
141 |
r.setStartBefore(c);
|
@@ -166,30 +170,43 @@
|
|
166 |
* @return {Element} Start element of selection range.
|
167 |
*/
|
168 |
getStart : function() {
|
169 |
-
var
|
170 |
-
|
171 |
-
if (r.duplicate || r.item) {
|
172 |
-
if (r.item)
|
173 |
-
return r.item(0);
|
174 |
|
175 |
-
|
176 |
-
|
177 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
|
179 |
-
|
180 |
-
|
|
|
181 |
|
182 |
-
return
|
183 |
} else {
|
184 |
-
|
185 |
|
186 |
-
if (
|
187 |
-
|
188 |
|
189 |
-
if (
|
190 |
-
return
|
191 |
|
192 |
-
return
|
193 |
}
|
194 |
},
|
195 |
|
@@ -269,10 +286,10 @@
|
|
269 |
point.push(offset);
|
270 |
} else {
|
271 |
childNodes = container.childNodes;
|
272 |
-
|
273 |
-
if (offset >= childNodes.length) {
|
274 |
after = 1;
|
275 |
-
offset = childNodes.length - 1;
|
276 |
}
|
277 |
|
278 |
point.push(t.dom.nodeIndex(childNodes[offset], normalized) + after);
|
@@ -358,7 +375,7 @@
|
|
358 |
* @return {Boolean} true/false if it was successful or not.
|
359 |
*/
|
360 |
moveToBookmark : function(bookmark) {
|
361 |
-
var t = this, dom = t.dom, marker1, marker2, rng, root;
|
362 |
|
363 |
// Clear selection cache
|
364 |
if (t.tridentSel)
|
@@ -370,12 +387,16 @@
|
|
370 |
root = dom.getRoot();
|
371 |
|
372 |
function setEndPoint(start) {
|
373 |
-
var point = bookmark[start ? 'start' : 'end'], i, node, offset;
|
374 |
|
375 |
if (point) {
|
376 |
// Find container node
|
377 |
-
for (node = root, i = point.length - 1; i >= 1; i--)
|
378 |
-
|
|
|
|
|
|
|
|
|
379 |
|
380 |
// Set offset within container node
|
381 |
if (start)
|
@@ -390,8 +411,6 @@
|
|
390 |
|
391 |
t.setRng(rng);
|
392 |
} else if (bookmark.id) {
|
393 |
-
rng = dom.createRng();
|
394 |
-
|
395 |
function restoreEndPoint(suffix) {
|
396 |
var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev, keep = bookmark.keep;
|
397 |
|
@@ -402,21 +421,22 @@
|
|
402 |
if (!keep) {
|
403 |
idx = dom.nodeIndex(marker);
|
404 |
} else {
|
405 |
-
node = marker;
|
406 |
idx = 1;
|
407 |
}
|
408 |
|
409 |
-
|
410 |
-
|
411 |
} else {
|
412 |
if (!keep) {
|
413 |
idx = dom.nodeIndex(marker);
|
414 |
} else {
|
415 |
-
node = marker;
|
416 |
idx = 1;
|
417 |
}
|
418 |
|
419 |
-
|
|
|
420 |
}
|
421 |
|
422 |
if (!keep) {
|
@@ -441,19 +461,33 @@
|
|
441 |
dom.remove(next);
|
442 |
|
443 |
if (suffix == 'start') {
|
444 |
-
|
445 |
-
|
446 |
-
} else
|
447 |
-
|
|
|
|
|
448 |
}
|
449 |
}
|
450 |
}
|
451 |
};
|
452 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
453 |
// Restore start/end points
|
454 |
restoreEndPoint('start');
|
455 |
restoreEndPoint('end');
|
456 |
|
|
|
|
|
|
|
457 |
t.setRng(rng);
|
458 |
} else if (bookmark.name) {
|
459 |
t.select(dom.select(bookmark.name)[bookmark.index]);
|
@@ -591,6 +625,16 @@
|
|
591 |
if (!r)
|
592 |
r = t.win.document.createRange ? t.win.document.createRange() : t.win.document.body.createTextRange();
|
593 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
594 |
return r;
|
595 |
},
|
596 |
|
@@ -602,13 +646,15 @@
|
|
602 |
*/
|
603 |
setRng : function(r) {
|
604 |
var s, t = this;
|
605 |
-
|
606 |
if (!t.tridentSel) {
|
607 |
s = t.getSel();
|
608 |
|
609 |
if (s) {
|
|
|
610 |
s.removeAllRanges();
|
611 |
s.addRange(r);
|
|
|
612 |
}
|
613 |
} else {
|
614 |
// Is W3C Range
|
125 |
h += '<span id="__caret">_</span>';
|
126 |
|
127 |
// Delete and insert new node
|
128 |
+
|
129 |
+
if (r.startContainer == d && r.endContainer == d) {
|
130 |
// WebKit will fail if the body is empty since the range is then invalid and it can't insert contents
|
131 |
d.body.innerHTML = h;
|
132 |
} else {
|
133 |
r.deleteContents();
|
134 |
+
if (d.body.childNodes.length == 0) {
|
135 |
+
d.body.innerHTML = h;
|
136 |
+
} else {
|
137 |
+
r.insertNode(r.createContextualFragment(h));
|
138 |
+
}
|
139 |
}
|
140 |
|
141 |
// Move to caret marker
|
142 |
c = t.dom.get('__caret');
|
|
|
143 |
// Make sure we wrap it compleatly, Opera fails with a simple select call
|
144 |
r = d.createRange();
|
145 |
r.setStartBefore(c);
|
170 |
* @return {Element} Start element of selection range.
|
171 |
*/
|
172 |
getStart : function() {
|
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;
|
200 |
} else {
|
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;
|
210 |
}
|
211 |
},
|
212 |
|
286 |
point.push(offset);
|
287 |
} else {
|
288 |
childNodes = container.childNodes;
|
289 |
+
|
290 |
+
if (offset >= childNodes.length && childNodes.length) {
|
291 |
after = 1;
|
292 |
+
offset = Math.max(0, childNodes.length - 1);
|
293 |
}
|
294 |
|
295 |
point.push(t.dom.nodeIndex(childNodes[offset], normalized) + after);
|
375 |
* @return {Boolean} true/false if it was successful or not.
|
376 |
*/
|
377 |
moveToBookmark : function(bookmark) {
|
378 |
+
var t = this, dom = t.dom, marker1, marker2, rng, root, startContainer, endContainer, startOffset, endOffset;
|
379 |
|
380 |
// Clear selection cache
|
381 |
if (t.tridentSel)
|
387 |
root = dom.getRoot();
|
388 |
|
389 |
function setEndPoint(start) {
|
390 |
+
var point = bookmark[start ? 'start' : 'end'], i, node, offset, children;
|
391 |
|
392 |
if (point) {
|
393 |
// Find container node
|
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 |
+
}
|
400 |
|
401 |
// Set offset within container node
|
402 |
if (start)
|
411 |
|
412 |
t.setRng(rng);
|
413 |
} else if (bookmark.id) {
|
|
|
|
|
414 |
function restoreEndPoint(suffix) {
|
415 |
var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev, keep = bookmark.keep;
|
416 |
|
421 |
if (!keep) {
|
422 |
idx = dom.nodeIndex(marker);
|
423 |
} else {
|
424 |
+
node = marker.firstChild;
|
425 |
idx = 1;
|
426 |
}
|
427 |
|
428 |
+
startContainer = endContainer = node;
|
429 |
+
startOffset = endOffset = idx;
|
430 |
} else {
|
431 |
if (!keep) {
|
432 |
idx = dom.nodeIndex(marker);
|
433 |
} else {
|
434 |
+
node = marker.firstChild;
|
435 |
idx = 1;
|
436 |
}
|
437 |
|
438 |
+
endContainer = node;
|
439 |
+
endOffset = idx;
|
440 |
}
|
441 |
|
442 |
if (!keep) {
|
461 |
dom.remove(next);
|
462 |
|
463 |
if (suffix == 'start') {
|
464 |
+
startContainer = endContainer = prev;
|
465 |
+
startOffset = endOffset = idx;
|
466 |
+
} else {
|
467 |
+
endContainer = prev;
|
468 |
+
endOffset = idx;
|
469 |
+
}
|
470 |
}
|
471 |
}
|
472 |
}
|
473 |
};
|
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 |
+
|
484 |
// Restore start/end points
|
485 |
restoreEndPoint('start');
|
486 |
restoreEndPoint('end');
|
487 |
|
488 |
+
rng = dom.createRng();
|
489 |
+
rng.setStart(addBogus(startContainer), startOffset);
|
490 |
+
rng.setEnd(addBogus(endContainer), endOffset);
|
491 |
t.setRng(rng);
|
492 |
} else if (bookmark.name) {
|
493 |
t.select(dom.select(bookmark.name)[bookmark.index]);
|
625 |
if (!r)
|
626 |
r = t.win.document.createRange ? t.win.document.createRange() : t.win.document.body.createTextRange();
|
627 |
|
628 |
+
if (t.selectedRange && t.explicitRange) {
|
629 |
+
if (r.compareBoundaryPoints(r.START_TO_START, t.selectedRange) === 0 && r.compareBoundaryPoints(r.END_TO_END, t.selectedRange) === 0) {
|
630 |
+
// Safari, Opera and Chrome only ever select text which causes the range to change.
|
631 |
+
// This lets us use the originally set range if the selection hasn't been changed by the user.
|
632 |
+
r = t.explicitRange;
|
633 |
+
} else {
|
634 |
+
t.selectedRange = null;
|
635 |
+
t.explicitRange = null;
|
636 |
+
}
|
637 |
+
}
|
638 |
return r;
|
639 |
},
|
640 |
|
646 |
*/
|
647 |
setRng : function(r) {
|
648 |
var s, t = this;
|
649 |
+
|
650 |
if (!t.tridentSel) {
|
651 |
s = t.getSel();
|
652 |
|
653 |
if (s) {
|
654 |
+
t.explicitRange = r;
|
655 |
s.removeAllRanges();
|
656 |
s.addRange(r);
|
657 |
+
t.selectedRange = s.getRangeAt(0);
|
658 |
}
|
659 |
} else {
|
660 |
// Is W3C Range
|
js/tiny_mce/classes/dom/Sizzle.js
CHANGED
@@ -8,14 +8,26 @@
|
|
8 |
*/
|
9 |
(function(){
|
10 |
|
11 |
-
var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[
|
12 |
done = 0,
|
13 |
toString = Object.prototype.toString,
|
14 |
-
hasDuplicate = false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
|
16 |
var Sizzle = function(selector, context, results, seed) {
|
17 |
results = results || [];
|
18 |
-
|
|
|
|
|
19 |
|
20 |
if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
|
21 |
return [];
|
@@ -25,19 +37,25 @@ var Sizzle = function(selector, context, results, seed) {
|
|
25 |
return results;
|
26 |
}
|
27 |
|
28 |
-
var parts = [], m, set, checkSet,
|
|
|
29 |
|
30 |
// Reset the position of the chunker regexp (start from head)
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
|
|
|
|
|
|
|
|
35 |
|
36 |
-
|
37 |
-
|
38 |
-
|
|
|
39 |
}
|
40 |
-
}
|
41 |
|
42 |
if ( parts.length > 1 && origPOS.exec( selector ) ) {
|
43 |
if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
|
@@ -50,9 +68,10 @@ var Sizzle = function(selector, context, results, seed) {
|
|
50 |
while ( parts.length ) {
|
51 |
selector = parts.shift();
|
52 |
|
53 |
-
if ( Expr.relative[ selector ] )
|
54 |
selector += parts.shift();
|
55 |
-
|
|
|
56 |
set = posProcess( selector, set );
|
57 |
}
|
58 |
}
|
@@ -61,12 +80,12 @@ var Sizzle = function(selector, context, results, seed) {
|
|
61 |
// (but not if it'll be faster if the inner selector is an ID)
|
62 |
if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
|
63 |
Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
|
64 |
-
|
65 |
context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
|
66 |
}
|
67 |
|
68 |
if ( context ) {
|
69 |
-
|
70 |
{ expr: parts.pop(), set: makeArray(seed) } :
|
71 |
Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
|
72 |
set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
|
@@ -78,7 +97,8 @@ var Sizzle = function(selector, context, results, seed) {
|
|
78 |
}
|
79 |
|
80 |
while ( parts.length ) {
|
81 |
-
|
|
|
82 |
|
83 |
if ( !Expr.relative[ cur ] ) {
|
84 |
cur = "";
|
@@ -102,20 +122,20 @@ var Sizzle = function(selector, context, results, seed) {
|
|
102 |
}
|
103 |
|
104 |
if ( !checkSet ) {
|
105 |
-
|
106 |
}
|
107 |
|
108 |
if ( toString.call(checkSet) === "[object Array]" ) {
|
109 |
if ( !prune ) {
|
110 |
results.push.apply( results, checkSet );
|
111 |
} else if ( context && context.nodeType === 1 ) {
|
112 |
-
for (
|
113 |
-
if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
|
114 |
results.push( set[i] );
|
115 |
}
|
116 |
}
|
117 |
} else {
|
118 |
-
for (
|
119 |
if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
|
120 |
results.push( set[i] );
|
121 |
}
|
@@ -135,7 +155,7 @@ var Sizzle = function(selector, context, results, seed) {
|
|
135 |
|
136 |
Sizzle.uniqueSort = function(results){
|
137 |
if ( sortOrder ) {
|
138 |
-
hasDuplicate =
|
139 |
results.sort(sortOrder);
|
140 |
|
141 |
if ( hasDuplicate ) {
|
@@ -146,6 +166,8 @@ Sizzle.uniqueSort = function(results){
|
|
146 |
}
|
147 |
}
|
148 |
}
|
|
|
|
|
149 |
};
|
150 |
|
151 |
Sizzle.matches = function(expr, set){
|
@@ -153,7 +175,7 @@ Sizzle.matches = function(expr, set){
|
|
153 |
};
|
154 |
|
155 |
Sizzle.find = function(expr, context, isXML){
|
156 |
-
var set
|
157 |
|
158 |
if ( !expr ) {
|
159 |
return [];
|
@@ -162,8 +184,9 @@ Sizzle.find = function(expr, context, isXML){
|
|
162 |
for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
|
163 |
var type = Expr.order[i], match;
|
164 |
|
165 |
-
if ( (match = Expr.
|
166 |
-
var left =
|
|
|
167 |
|
168 |
if ( left.substr( left.length - 1 ) !== "\\" ) {
|
169 |
match[1] = (match[1] || "").replace(/\\/g, "");
|
@@ -185,15 +208,21 @@ Sizzle.find = function(expr, context, isXML){
|
|
185 |
|
186 |
Sizzle.filter = function(expr, set, inplace, not){
|
187 |
var old = expr, result = [], curLoop = set, match, anyFound,
|
188 |
-
isXMLFilter = set && set[0] && isXML(set[0]);
|
189 |
|
190 |
while ( expr && set.length ) {
|
191 |
for ( var type in Expr.filter ) {
|
192 |
-
if ( (match = Expr.
|
193 |
-
var filter = Expr.filter[ type ], found, item;
|
194 |
anyFound = false;
|
195 |
|
196 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
result = [];
|
198 |
}
|
199 |
|
@@ -244,9 +273,9 @@ Sizzle.filter = function(expr, set, inplace, not){
|
|
244 |
}
|
245 |
|
246 |
// Improper expression
|
247 |
-
if ( expr
|
248 |
if ( anyFound == null ) {
|
249 |
-
|
250 |
} else {
|
251 |
break;
|
252 |
}
|
@@ -258,18 +287,23 @@ Sizzle.filter = function(expr, set, inplace, not){
|
|
258 |
return curLoop;
|
259 |
};
|
260 |
|
|
|
|
|
|
|
|
|
261 |
var Expr = Sizzle.selectors = {
|
262 |
order: [ "ID", "NAME", "TAG" ],
|
263 |
match: {
|
264 |
-
ID: /#((?:[\w\u00c0-\
|
265 |
-
CLASS: /\.((?:[\w\u00c0-\
|
266 |
-
NAME: /\[name=['"]*((?:[\w\u00c0-\
|
267 |
-
ATTR: /\[\s*((?:[\w\u00c0-\
|
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-\
|
272 |
},
|
|
|
273 |
attrMap: {
|
274 |
"class": "className",
|
275 |
"for": "htmlFor"
|
@@ -280,20 +314,20 @@ var Expr = Sizzle.selectors = {
|
|
280 |
}
|
281 |
},
|
282 |
relative: {
|
283 |
-
"+": function(checkSet, part
|
284 |
var isPartStr = typeof part === "string",
|
285 |
isTag = isPartStr && !/\W/.test(part),
|
286 |
isPartStrNotTag = isPartStr && !isTag;
|
287 |
|
288 |
-
if ( isTag
|
289 |
-
part = part.
|
290 |
}
|
291 |
|
292 |
for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
|
293 |
if ( (elem = checkSet[i]) ) {
|
294 |
while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
|
295 |
|
296 |
-
checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
|
297 |
elem || false :
|
298 |
elem === part;
|
299 |
}
|
@@ -303,22 +337,23 @@ var Expr = Sizzle.selectors = {
|
|
303 |
Sizzle.filter( part, checkSet, true );
|
304 |
}
|
305 |
},
|
306 |
-
">": function(checkSet, part
|
307 |
-
var isPartStr = typeof part === "string"
|
|
|
308 |
|
309 |
if ( isPartStr && !/\W/.test(part) ) {
|
310 |
-
part =
|
311 |
|
312 |
-
for (
|
313 |
-
|
314 |
if ( elem ) {
|
315 |
var parent = elem.parentNode;
|
316 |
-
checkSet[i] = parent.nodeName === part ? parent : false;
|
317 |
}
|
318 |
}
|
319 |
} else {
|
320 |
-
for (
|
321 |
-
|
322 |
if ( elem ) {
|
323 |
checkSet[i] = isPartStr ?
|
324 |
elem.parentNode :
|
@@ -332,20 +367,22 @@ var Expr = Sizzle.selectors = {
|
|
332 |
}
|
333 |
},
|
334 |
"": function(checkSet, part, isXML){
|
335 |
-
var doneName = done++, checkFn = dirCheck;
|
336 |
|
337 |
-
if (
|
338 |
-
|
|
|
339 |
checkFn = dirNodeCheck;
|
340 |
}
|
341 |
|
342 |
checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
|
343 |
},
|
344 |
"~": function(checkSet, part, isXML){
|
345 |
-
var doneName = done++, checkFn = dirCheck;
|
346 |
|
347 |
-
if ( typeof part === "string" &&
|
348 |
-
|
|
|
349 |
checkFn = dirNodeCheck;
|
350 |
}
|
351 |
|
@@ -359,7 +396,7 @@ var Expr = Sizzle.selectors = {
|
|
359 |
return m ? [m] : [];
|
360 |
}
|
361 |
},
|
362 |
-
NAME: function(match, context
|
363 |
if ( typeof context.getElementsByName !== "undefined" ) {
|
364 |
var ret = [], results = context.getElementsByName(match[1]);
|
365 |
|
@@ -386,9 +423,10 @@ var Expr = Sizzle.selectors = {
|
|
386 |
|
387 |
for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
|
388 |
if ( elem ) {
|
389 |
-
if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
|
390 |
-
if ( !inplace )
|
391 |
result.push( elem );
|
|
|
392 |
} else if ( inplace ) {
|
393 |
curLoop[i] = false;
|
394 |
}
|
@@ -401,14 +439,13 @@ var Expr = Sizzle.selectors = {
|
|
401 |
return match[1].replace(/\\/g, "");
|
402 |
},
|
403 |
TAG: function(match, curLoop){
|
404 |
-
|
405 |
-
return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
|
406 |
},
|
407 |
CHILD: function(match){
|
408 |
-
if ( match[1]
|
409 |
// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
|
410 |
var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
|
411 |
-
match[2]
|
412 |
!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
|
413 |
|
414 |
// calculate the numbers (first)n+(last) including if they are negative
|
@@ -437,7 +474,7 @@ var Expr = Sizzle.selectors = {
|
|
437 |
PSEUDO: function(match, curLoop, inplace, result, not){
|
438 |
if ( match[1] === "not" ) {
|
439 |
// If we're dealing with a complex expression, or a simple one
|
440 |
-
if ( match[3]
|
441 |
match[3] = Sizzle(match[3], null, null, curLoop);
|
442 |
} else {
|
443 |
var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
|
@@ -483,7 +520,7 @@ var Expr = Sizzle.selectors = {
|
|
483 |
return !!Sizzle( match[3], elem ).length;
|
484 |
},
|
485 |
header: function(elem){
|
486 |
-
return /h\d/i.test( elem.nodeName );
|
487 |
},
|
488 |
text: function(elem){
|
489 |
return "text" === elem.type;
|
@@ -510,10 +547,10 @@ var Expr = Sizzle.selectors = {
|
|
510 |
return "reset" === elem.type;
|
511 |
},
|
512 |
button: function(elem){
|
513 |
-
return "button" === elem.type || elem.nodeName.
|
514 |
},
|
515 |
input: function(elem){
|
516 |
-
return /input|select|textarea|button/i.test(elem.nodeName);
|
517 |
}
|
518 |
},
|
519 |
setFilters: {
|
@@ -536,10 +573,10 @@ var Expr = Sizzle.selectors = {
|
|
536 |
return i > match[3] - 0;
|
537 |
},
|
538 |
nth: function(elem, i, match){
|
539 |
-
return match[3] - 0
|
540 |
},
|
541 |
eq: function(elem, i, match){
|
542 |
-
return match[3] - 0
|
543 |
}
|
544 |
},
|
545 |
filter: {
|
@@ -549,17 +586,19 @@ var Expr = Sizzle.selectors = {
|
|
549 |
if ( filter ) {
|
550 |
return filter( elem, i, match, array );
|
551 |
} else if ( name === "contains" ) {
|
552 |
-
return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
|
553 |
} else if ( name === "not" ) {
|
554 |
var not = match[3];
|
555 |
|
556 |
-
for ( var
|
557 |
-
if ( not[
|
558 |
return false;
|
559 |
}
|
560 |
}
|
561 |
|
562 |
return true;
|
|
|
|
|
563 |
}
|
564 |
},
|
565 |
CHILD: function(elem, match){
|
@@ -567,20 +606,26 @@ var Expr = Sizzle.selectors = {
|
|
567 |
switch (type) {
|
568 |
case 'only':
|
569 |
case 'first':
|
570 |
-
while (node = node.previousSibling)
|
571 |
-
if ( node.nodeType === 1 )
|
|
|
|
|
|
|
|
|
|
|
572 |
}
|
573 |
-
if ( type == 'first') return true;
|
574 |
node = elem;
|
575 |
case 'last':
|
576 |
-
while (node = node.nextSibling)
|
577 |
-
if ( node.nodeType === 1 )
|
|
|
|
|
578 |
}
|
579 |
return true;
|
580 |
case 'nth':
|
581 |
var first = match[2], last = match[3];
|
582 |
|
583 |
-
if ( first
|
584 |
return true;
|
585 |
}
|
586 |
|
@@ -598,10 +643,10 @@ var Expr = Sizzle.selectors = {
|
|
598 |
}
|
599 |
|
600 |
var diff = elem.nodeIndex - last;
|
601 |
-
if ( first
|
602 |
-
return diff
|
603 |
} else {
|
604 |
-
return ( diff % first
|
605 |
}
|
606 |
}
|
607 |
},
|
@@ -609,7 +654,7 @@ var Expr = Sizzle.selectors = {
|
|
609 |
return elem.nodeType === 1 && elem.getAttribute("id") === match;
|
610 |
},
|
611 |
TAG: function(elem, match){
|
612 |
-
return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
|
613 |
},
|
614 |
CLASS: function(elem, match){
|
615 |
return (" " + (elem.className || elem.getAttribute("class")) + " ")
|
@@ -637,7 +682,7 @@ var Expr = Sizzle.selectors = {
|
|
637 |
!check ?
|
638 |
value && result !== false :
|
639 |
type === "!=" ?
|
640 |
-
value
|
641 |
type === "^=" ?
|
642 |
value.indexOf(check) === 0 :
|
643 |
type === "$=" ?
|
@@ -656,14 +701,18 @@ var Expr = Sizzle.selectors = {
|
|
656 |
}
|
657 |
};
|
658 |
|
659 |
-
var origPOS = Expr.match.POS
|
|
|
|
|
|
|
660 |
|
661 |
for ( var type in Expr.match ) {
|
662 |
-
Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
|
|
|
663 |
}
|
664 |
|
665 |
var makeArray = function(array, results) {
|
666 |
-
array = Array.prototype.slice.call( array );
|
667 |
|
668 |
if ( results ) {
|
669 |
results.push.apply( results, array );
|
@@ -675,23 +724,25 @@ var makeArray = function(array, results) {
|
|
675 |
|
676 |
// Perform a simple check to determine if the browser is capable of
|
677 |
// converting a NodeList to an array using builtin methods.
|
|
|
|
|
678 |
try {
|
679 |
-
Array.prototype.slice.call( document.documentElement.childNodes );
|
680 |
|
681 |
// Provide a fallback method if it does not work
|
682 |
} catch(e){
|
683 |
makeArray = function(array, results) {
|
684 |
-
var ret = results || [];
|
685 |
|
686 |
if ( toString.call(array) === "[object Array]" ) {
|
687 |
Array.prototype.push.apply( ret, array );
|
688 |
} else {
|
689 |
if ( typeof array.length === "number" ) {
|
690 |
-
for ( var
|
691 |
ret.push( array[i] );
|
692 |
}
|
693 |
} else {
|
694 |
-
for (
|
695 |
ret.push( array[i] );
|
696 |
}
|
697 |
}
|
@@ -705,6 +756,13 @@ var sortOrder;
|
|
705 |
|
706 |
if ( document.documentElement.compareDocumentPosition ) {
|
707 |
sortOrder = function( a, b ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
708 |
var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
|
709 |
if ( ret === 0 ) {
|
710 |
hasDuplicate = true;
|
@@ -713,6 +771,13 @@ if ( document.documentElement.compareDocumentPosition ) {
|
|
713 |
};
|
714 |
} else if ( "sourceIndex" in document.documentElement ) {
|
715 |
sortOrder = function( a, b ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
716 |
var ret = a.sourceIndex - b.sourceIndex;
|
717 |
if ( ret === 0 ) {
|
718 |
hasDuplicate = true;
|
@@ -721,6 +786,13 @@ if ( document.documentElement.compareDocumentPosition ) {
|
|
721 |
};
|
722 |
} else if ( document.createRange ) {
|
723 |
sortOrder = function( a, b ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
724 |
var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
|
725 |
aRange.setStart(a, 0);
|
726 |
aRange.setEnd(a, 0);
|
@@ -734,12 +806,32 @@ if ( document.documentElement.compareDocumentPosition ) {
|
|
734 |
};
|
735 |
}
|
736 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
737 |
// Check to see if the browser returns elements by name when
|
738 |
// querying by getElementById (and provide a workaround)
|
739 |
(function(){
|
740 |
// We're going to inject a fake input element with a specified name
|
741 |
var form = document.createElement("div"),
|
742 |
-
id = "script" + (new Date).getTime();
|
743 |
form.innerHTML = "<a name='" + id + "'/>";
|
744 |
|
745 |
// Inject it into the root element, check its status, and remove it quickly
|
@@ -748,7 +840,7 @@ if ( document.documentElement.compareDocumentPosition ) {
|
|
748 |
|
749 |
// The workaround has to do additional checks after a getElementById
|
750 |
// Which slows things down for other browsers (hence the branching)
|
751 |
-
if (
|
752 |
Expr.find.ID = function(match, context, isXML){
|
753 |
if ( typeof context.getElementById !== "undefined" && !isXML ) {
|
754 |
var m = context.getElementById(match[1]);
|
@@ -763,6 +855,7 @@ if ( document.documentElement.compareDocumentPosition ) {
|
|
763 |
}
|
764 |
|
765 |
root.removeChild( form );
|
|
|
766 |
})();
|
767 |
|
768 |
(function(){
|
@@ -803,68 +896,75 @@ if ( document.documentElement.compareDocumentPosition ) {
|
|
803 |
return elem.getAttribute("href", 2);
|
804 |
};
|
805 |
}
|
|
|
|
|
806 |
})();
|
807 |
|
808 |
-
if ( document.querySelectorAll )
|
809 |
-
|
810 |
-
|
|
|
811 |
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
}
|
817 |
-
|
818 |
-
Sizzle = function(query, context, extra, seed){
|
819 |
-
context = context || document;
|
820 |
-
|
821 |
-
// Only use querySelectorAll on non-XML documents
|
822 |
-
// (ID selectors don't work in non-HTML documents)
|
823 |
-
if ( !seed && context.nodeType === 9 && !isXML(context) ) {
|
824 |
-
try {
|
825 |
-
return makeArray( context.querySelectorAll(query), extra );
|
826 |
-
} catch(e){}
|
827 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
828 |
|
829 |
-
|
830 |
-
|
831 |
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
})();
|
836 |
|
837 |
-
|
|
|
|
|
|
|
|
|
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 |
-
|
|
|
843 |
return;
|
|
|
844 |
|
845 |
// Safari caches class attributes, doesn't catch changes (in 3.2)
|
846 |
div.lastChild.className = "e";
|
847 |
|
848 |
-
if ( div.getElementsByClassName("e").length === 1 )
|
849 |
return;
|
850 |
-
|
|
|
851 |
Expr.order.splice(1, 0, "CLASS");
|
852 |
Expr.find.CLASS = function(match, context, isXML) {
|
853 |
if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
|
854 |
return context.getElementsByClassName(match[1]);
|
855 |
}
|
856 |
};
|
|
|
|
|
857 |
})();
|
858 |
|
859 |
function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
|
860 |
-
var sibDir = dir == "previousSibling" && !isXML;
|
861 |
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
|
862 |
var elem = checkSet[i];
|
863 |
if ( elem ) {
|
864 |
-
if ( sibDir && elem.nodeType === 1 ){
|
865 |
-
elem.sizcache = doneName;
|
866 |
-
elem.sizset = i;
|
867 |
-
}
|
868 |
elem = elem[dir];
|
869 |
var match = false;
|
870 |
|
@@ -879,7 +979,7 @@ function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
|
|
879 |
elem.sizset = i;
|
880 |
}
|
881 |
|
882 |
-
if ( elem.nodeName === cur ) {
|
883 |
match = elem;
|
884 |
break;
|
885 |
}
|
@@ -893,14 +993,9 @@ function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
|
|
893 |
}
|
894 |
|
895 |
function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
|
896 |
-
var sibDir = dir == "previousSibling" && !isXML;
|
897 |
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
|
898 |
var elem = checkSet[i];
|
899 |
if ( elem ) {
|
900 |
-
if ( sibDir && elem.nodeType === 1 ) {
|
901 |
-
elem.sizcache = doneName;
|
902 |
-
elem.sizset = i;
|
903 |
-
}
|
904 |
elem = elem[dir];
|
905 |
var match = false;
|
906 |
|
@@ -935,15 +1030,17 @@ function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
|
|
935 |
}
|
936 |
}
|
937 |
|
938 |
-
|
939 |
-
return a.compareDocumentPosition(b) & 16;
|
940 |
} : function(a, b){
|
941 |
return a !== b && (a.contains ? a.contains(b) : true);
|
942 |
};
|
943 |
|
944 |
-
|
945 |
-
|
946 |
-
|
|
|
|
|
947 |
};
|
948 |
|
949 |
var posProcess = function(selector, context){
|
8 |
*/
|
9 |
(function(){
|
10 |
|
11 |
+
var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
|
12 |
done = 0,
|
13 |
toString = Object.prototype.toString,
|
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 |
+
});
|
25 |
|
26 |
var Sizzle = function(selector, context, results, seed) {
|
27 |
results = results || [];
|
28 |
+
context = context || document;
|
29 |
+
|
30 |
+
var origContext = context;
|
31 |
|
32 |
if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
|
33 |
return [];
|
37 |
return results;
|
38 |
}
|
39 |
|
40 |
+
var parts = [], m, set, checkSet, extra, prune = true, contextXML = Sizzle.isXML(context),
|
41 |
+
soFar = selector, ret, cur, pop, i;
|
42 |
|
43 |
// Reset the position of the chunker regexp (start from head)
|
44 |
+
do {
|
45 |
+
chunker.exec("");
|
46 |
+
m = chunker.exec(soFar);
|
47 |
+
|
48 |
+
if ( m ) {
|
49 |
+
soFar = m[3];
|
50 |
+
|
51 |
+
parts.push( m[1] );
|
52 |
|
53 |
+
if ( m[2] ) {
|
54 |
+
extra = m[3];
|
55 |
+
break;
|
56 |
+
}
|
57 |
}
|
58 |
+
} while ( m );
|
59 |
|
60 |
if ( parts.length > 1 && origPOS.exec( selector ) ) {
|
61 |
if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
|
68 |
while ( parts.length ) {
|
69 |
selector = parts.shift();
|
70 |
|
71 |
+
if ( Expr.relative[ selector ] ) {
|
72 |
selector += parts.shift();
|
73 |
+
}
|
74 |
+
|
75 |
set = posProcess( selector, set );
|
76 |
}
|
77 |
}
|
80 |
// (but not if it'll be faster if the inner selector is an ID)
|
81 |
if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
|
82 |
Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
|
83 |
+
ret = Sizzle.find( parts.shift(), context, contextXML );
|
84 |
context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
|
85 |
}
|
86 |
|
87 |
if ( context ) {
|
88 |
+
ret = seed ?
|
89 |
{ expr: parts.pop(), set: makeArray(seed) } :
|
90 |
Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
|
91 |
set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
|
97 |
}
|
98 |
|
99 |
while ( parts.length ) {
|
100 |
+
cur = parts.pop();
|
101 |
+
pop = cur;
|
102 |
|
103 |
if ( !Expr.relative[ cur ] ) {
|
104 |
cur = "";
|
122 |
}
|
123 |
|
124 |
if ( !checkSet ) {
|
125 |
+
Sizzle.error( cur || selector );
|
126 |
}
|
127 |
|
128 |
if ( toString.call(checkSet) === "[object Array]" ) {
|
129 |
if ( !prune ) {
|
130 |
results.push.apply( results, checkSet );
|
131 |
} else if ( context && context.nodeType === 1 ) {
|
132 |
+
for ( i = 0; checkSet[i] != null; i++ ) {
|
133 |
+
if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
|
134 |
results.push( set[i] );
|
135 |
}
|
136 |
}
|
137 |
} else {
|
138 |
+
for ( i = 0; checkSet[i] != null; i++ ) {
|
139 |
if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
|
140 |
results.push( set[i] );
|
141 |
}
|
155 |
|
156 |
Sizzle.uniqueSort = function(results){
|
157 |
if ( sortOrder ) {
|
158 |
+
hasDuplicate = baseHasDuplicate;
|
159 |
results.sort(sortOrder);
|
160 |
|
161 |
if ( hasDuplicate ) {
|
166 |
}
|
167 |
}
|
168 |
}
|
169 |
+
|
170 |
+
return results;
|
171 |
};
|
172 |
|
173 |
Sizzle.matches = function(expr, set){
|
175 |
};
|
176 |
|
177 |
Sizzle.find = function(expr, context, isXML){
|
178 |
+
var set;
|
179 |
|
180 |
if ( !expr ) {
|
181 |
return [];
|
184 |
for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
|
185 |
var type = Expr.order[i], match;
|
186 |
|
187 |
+
if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
|
188 |
+
var left = match[1];
|
189 |
+
match.splice(1,1);
|
190 |
|
191 |
if ( left.substr( left.length - 1 ) !== "\\" ) {
|
192 |
match[1] = (match[1] || "").replace(/\\/g, "");
|
208 |
|
209 |
Sizzle.filter = function(expr, set, inplace, not){
|
210 |
var old = expr, result = [], curLoop = set, match, anyFound,
|
211 |
+
isXMLFilter = set && set[0] && Sizzle.isXML(set[0]);
|
212 |
|
213 |
while ( expr && set.length ) {
|
214 |
for ( var type in Expr.filter ) {
|
215 |
+
if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
|
216 |
+
var filter = Expr.filter[ type ], found, item, left = match[1];
|
217 |
anyFound = false;
|
218 |
|
219 |
+
match.splice(1,1);
|
220 |
+
|
221 |
+
if ( left.substr( left.length - 1 ) === "\\" ) {
|
222 |
+
continue;
|
223 |
+
}
|
224 |
+
|
225 |
+
if ( curLoop === result ) {
|
226 |
result = [];
|
227 |
}
|
228 |
|
273 |
}
|
274 |
|
275 |
// Improper expression
|
276 |
+
if ( expr === old ) {
|
277 |
if ( anyFound == null ) {
|
278 |
+
Sizzle.error( expr );
|
279 |
} else {
|
280 |
break;
|
281 |
}
|
287 |
return curLoop;
|
288 |
};
|
289 |
|
290 |
+
Sizzle.error = function( msg ) {
|
291 |
+
throw "Syntax error, unrecognized expression: " + msg;
|
292 |
+
};
|
293 |
+
|
294 |
var Expr = Sizzle.selectors = {
|
295 |
order: [ "ID", "NAME", "TAG" ],
|
296 |
match: {
|
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\))?/
|
305 |
},
|
306 |
+
leftMatch: {},
|
307 |
attrMap: {
|
308 |
"class": "className",
|
309 |
"for": "htmlFor"
|
314 |
}
|
315 |
},
|
316 |
relative: {
|
317 |
+
"+": function(checkSet, part){
|
318 |
var isPartStr = typeof part === "string",
|
319 |
isTag = isPartStr && !/\W/.test(part),
|
320 |
isPartStrNotTag = isPartStr && !isTag;
|
321 |
|
322 |
+
if ( isTag ) {
|
323 |
+
part = part.toLowerCase();
|
324 |
}
|
325 |
|
326 |
for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
|
327 |
if ( (elem = checkSet[i]) ) {
|
328 |
while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
|
329 |
|
330 |
+
checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
|
331 |
elem || false :
|
332 |
elem === part;
|
333 |
}
|
337 |
Sizzle.filter( part, checkSet, true );
|
338 |
}
|
339 |
},
|
340 |
+
">": function(checkSet, part){
|
341 |
+
var isPartStr = typeof part === "string",
|
342 |
+
elem, i = 0, l = checkSet.length;
|
343 |
|
344 |
if ( isPartStr && !/\W/.test(part) ) {
|
345 |
+
part = part.toLowerCase();
|
346 |
|
347 |
+
for ( ; i < l; i++ ) {
|
348 |
+
elem = checkSet[i];
|
349 |
if ( elem ) {
|
350 |
var parent = elem.parentNode;
|
351 |
+
checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
|
352 |
}
|
353 |
}
|
354 |
} else {
|
355 |
+
for ( ; i < l; i++ ) {
|
356 |
+
elem = checkSet[i];
|
357 |
if ( elem ) {
|
358 |
checkSet[i] = isPartStr ?
|
359 |
elem.parentNode :
|
367 |
}
|
368 |
},
|
369 |
"": function(checkSet, part, isXML){
|
370 |
+
var doneName = done++, checkFn = dirCheck, nodeCheck;
|
371 |
|
372 |
+
if ( typeof part === "string" && !/\W/.test(part) ) {
|
373 |
+
part = part.toLowerCase();
|
374 |
+
nodeCheck = part;
|
375 |
checkFn = dirNodeCheck;
|
376 |
}
|
377 |
|
378 |
checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
|
379 |
},
|
380 |
"~": function(checkSet, part, isXML){
|
381 |
+
var doneName = done++, checkFn = dirCheck, nodeCheck;
|
382 |
|
383 |
+
if ( typeof part === "string" && !/\W/.test(part) ) {
|
384 |
+
part = part.toLowerCase();
|
385 |
+
nodeCheck = part;
|
386 |
checkFn = dirNodeCheck;
|
387 |
}
|
388 |
|
396 |
return m ? [m] : [];
|
397 |
}
|
398 |
},
|
399 |
+
NAME: function(match, context){
|
400 |
if ( typeof context.getElementsByName !== "undefined" ) {
|
401 |
var ret = [], results = context.getElementsByName(match[1]);
|
402 |
|
423 |
|
424 |
for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
|
425 |
if ( elem ) {
|
426 |
+
if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {
|
427 |
+
if ( !inplace ) {
|
428 |
result.push( elem );
|
429 |
+
}
|
430 |
} else if ( inplace ) {
|
431 |
curLoop[i] = false;
|
432 |
}
|
439 |
return match[1].replace(/\\/g, "");
|
440 |
},
|
441 |
TAG: function(match, curLoop){
|
442 |
+
return match[1].toLowerCase();
|
|
|
443 |
},
|
444 |
CHILD: function(match){
|
445 |
+
if ( match[1] === "nth" ) {
|
446 |
// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
|
447 |
var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
|
448 |
+
match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
|
449 |
!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
|
450 |
|
451 |
// calculate the numbers (first)n+(last) including if they are negative
|
474 |
PSEUDO: function(match, curLoop, inplace, result, not){
|
475 |
if ( match[1] === "not" ) {
|
476 |
// If we're dealing with a complex expression, or a simple one
|
477 |
+
if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
|
478 |
match[3] = Sizzle(match[3], null, null, curLoop);
|
479 |
} else {
|
480 |
var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
|
520 |
return !!Sizzle( match[3], elem ).length;
|
521 |
},
|
522 |
header: function(elem){
|
523 |
+
return (/h\d/i).test( elem.nodeName );
|
524 |
},
|
525 |
text: function(elem){
|
526 |
return "text" === elem.type;
|
547 |
return "reset" === elem.type;
|
548 |
},
|
549 |
button: function(elem){
|
550 |
+
return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
|
551 |
},
|
552 |
input: function(elem){
|
553 |
+
return (/input|select|textarea|button/i).test(elem.nodeName);
|
554 |
}
|
555 |
},
|
556 |
setFilters: {
|
573 |
return i > match[3] - 0;
|
574 |
},
|
575 |
nth: function(elem, i, match){
|
576 |
+
return match[3] - 0 === i;
|
577 |
},
|
578 |
eq: function(elem, i, match){
|
579 |
+
return match[3] - 0 === i;
|
580 |
}
|
581 |
},
|
582 |
filter: {
|
586 |
if ( filter ) {
|
587 |
return filter( elem, i, match, array );
|
588 |
} else if ( name === "contains" ) {
|
589 |
+
return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0;
|
590 |
} else if ( name === "not" ) {
|
591 |
var not = match[3];
|
592 |
|
593 |
+
for ( var j = 0, l = not.length; j < l; j++ ) {
|
594 |
+
if ( not[j] === elem ) {
|
595 |
return false;
|
596 |
}
|
597 |
}
|
598 |
|
599 |
return true;
|
600 |
+
} else {
|
601 |
+
Sizzle.error( "Syntax error, unrecognized expression: " + name );
|
602 |
}
|
603 |
},
|
604 |
CHILD: function(elem, match){
|
606 |
switch (type) {
|
607 |
case 'only':
|
608 |
case 'first':
|
609 |
+
while ( (node = node.previousSibling) ) {
|
610 |
+
if ( node.nodeType === 1 ) {
|
611 |
+
return false;
|
612 |
+
}
|
613 |
+
}
|
614 |
+
if ( type === "first" ) {
|
615 |
+
return true;
|
616 |
}
|
|
|
617 |
node = elem;
|
618 |
case 'last':
|
619 |
+
while ( (node = node.nextSibling) ) {
|
620 |
+
if ( node.nodeType === 1 ) {
|
621 |
+
return false;
|
622 |
+
}
|
623 |
}
|
624 |
return true;
|
625 |
case 'nth':
|
626 |
var first = match[2], last = match[3];
|
627 |
|
628 |
+
if ( first === 1 && last === 0 ) {
|
629 |
return true;
|
630 |
}
|
631 |
|
643 |
}
|
644 |
|
645 |
var diff = elem.nodeIndex - last;
|
646 |
+
if ( first === 0 ) {
|
647 |
+
return diff === 0;
|
648 |
} else {
|
649 |
+
return ( diff % first === 0 && diff / first >= 0 );
|
650 |
}
|
651 |
}
|
652 |
},
|
654 |
return elem.nodeType === 1 && elem.getAttribute("id") === match;
|
655 |
},
|
656 |
TAG: function(elem, match){
|
657 |
+
return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
|
658 |
},
|
659 |
CLASS: function(elem, match){
|
660 |
return (" " + (elem.className || elem.getAttribute("class")) + " ")
|
682 |
!check ?
|
683 |
value && result !== false :
|
684 |
type === "!=" ?
|
685 |
+
value !== check :
|
686 |
type === "^=" ?
|
687 |
value.indexOf(check) === 0 :
|
688 |
type === "$=" ?
|
701 |
}
|
702 |
};
|
703 |
|
704 |
+
var origPOS = Expr.match.POS,
|
705 |
+
fescape = function(all, num){
|
706 |
+
return "\\" + (num - 0 + 1);
|
707 |
+
};
|
708 |
|
709 |
for ( var type in Expr.match ) {
|
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) );
|
712 |
}
|
713 |
|
714 |
var makeArray = function(array, results) {
|
715 |
+
array = Array.prototype.slice.call( array, 0 );
|
716 |
|
717 |
if ( results ) {
|
718 |
results.push.apply( results, array );
|
724 |
|
725 |
// Perform a simple check to determine if the browser is capable of
|
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)
|
729 |
try {
|
730 |
+
Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
|
731 |
|
732 |
// Provide a fallback method if it does not work
|
733 |
} catch(e){
|
734 |
makeArray = function(array, results) {
|
735 |
+
var ret = results || [], i = 0;
|
736 |
|
737 |
if ( toString.call(array) === "[object Array]" ) {
|
738 |
Array.prototype.push.apply( ret, array );
|
739 |
} else {
|
740 |
if ( typeof array.length === "number" ) {
|
741 |
+
for ( var l = array.length; i < l; i++ ) {
|
742 |
ret.push( array[i] );
|
743 |
}
|
744 |
} else {
|
745 |
+
for ( ; array[i]; i++ ) {
|
746 |
ret.push( array[i] );
|
747 |
}
|
748 |
}
|
756 |
|
757 |
if ( document.documentElement.compareDocumentPosition ) {
|
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 |
+
|
766 |
var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
|
767 |
if ( ret === 0 ) {
|
768 |
hasDuplicate = true;
|
771 |
};
|
772 |
} else if ( "sourceIndex" in document.documentElement ) {
|
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 |
+
|
781 |
var ret = a.sourceIndex - b.sourceIndex;
|
782 |
if ( ret === 0 ) {
|
783 |
hasDuplicate = true;
|
786 |
};
|
787 |
} else if ( document.createRange ) {
|
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 |
+
|
796 |
var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
|
797 |
aRange.setStart(a, 0);
|
798 |
aRange.setEnd(a, 0);
|
806 |
};
|
807 |
}
|
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[ |