Mercurial > public > sg101
comparison media/js/tiny_mce/tiny_mce_src.js @ 247:6ed2932901fa
Update tinymce to 3.3.9
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Sat, 18 Sep 2010 19:54:11 +0000 |
parents | 237710206167 |
children |
comparison
equal
deleted
inserted
replaced
246:e4dc0b649fcb | 247:6ed2932901fa |
---|---|
3 undefined; | 3 undefined; |
4 | 4 |
5 var tinymce = { | 5 var tinymce = { |
6 majorVersion : '3', | 6 majorVersion : '3', |
7 | 7 |
8 minorVersion : '3.6', | 8 minorVersion : '3.9', |
9 | 9 |
10 releaseDate : '2010-05-20', | 10 releaseDate : '2010-09-08', |
11 | 11 |
12 _init : function() { | 12 _init : function() { |
13 var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v; | 13 var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v; |
14 | 14 |
15 t.isOpera = win.opera && opera.buildNumber; | 15 t.isOpera = win.opera && opera.buildNumber; |
50 base = v ? v.match(/.*\//)[0] : ''; // Get only directory | 50 base = v ? v.match(/.*\//)[0] : ''; // Get only directory |
51 } | 51 } |
52 } | 52 } |
53 | 53 |
54 function getBase(n) { | 54 function getBase(n) { |
55 if (n.src && /tiny_mce(|_gzip|_jquery|_prototype)(_dev|_src)?.js/.test(n.src)) { | 55 if (n.src && /tiny_mce(|_gzip|_jquery|_prototype|_full)(_dev|_src)?.js/.test(n.src)) { |
56 if (/_(src|dev)\.js/g.test(n.src)) | 56 if (/_(src|dev)\.js/g.test(n.src)) |
57 t.suffix = '_src'; | 57 t.suffix = '_src'; |
58 | 58 |
59 if ((p = n.src.indexOf('?')) != -1) | 59 if ((p = n.src.indexOf('?')) != -1) |
60 t.query = n.src.substring(p + 1); | 60 t.query = n.src.substring(p + 1); |
1576 if (isIE && !t.stdMode) { | 1576 if (isIE && !t.stdMode) { |
1577 n = n.getBoundingClientRect(); | 1577 n = n.getBoundingClientRect(); |
1578 e = t.boxModel ? d.documentElement : d.body; | 1578 e = t.boxModel ? d.documentElement : d.body; |
1579 x = t.getStyle(t.select('html')[0], 'borderWidth'); // Remove border | 1579 x = t.getStyle(t.select('html')[0], 'borderWidth'); // Remove border |
1580 x = (x == 'medium' || t.boxModel && !t.isIE6) && 2 || x; | 1580 x = (x == 'medium' || t.boxModel && !t.isIE6) && 2 || x; |
1581 n.top += t.win.self != t.win.top ? 2 : 0; // IE adds some strange extra cord if used in a frameset | |
1582 | 1581 |
1583 return {x : n.left + e.scrollLeft - x, y : n.top + e.scrollTop - x}; | 1582 return {x : n.left + e.scrollLeft - x, y : n.top + e.scrollTop - x}; |
1584 } | 1583 } |
1585 | 1584 |
1586 r = n; | 1585 r = n; |
3287 checkRng.collapse(start); | 3286 checkRng.collapse(start); |
3288 | 3287 |
3289 // Create marker and insert it at the end of the endpoints parent | 3288 // Create marker and insert it at the end of the endpoints parent |
3290 marker = dom.create('a'); | 3289 marker = dom.create('a'); |
3291 parent = checkRng.parentElement(); | 3290 parent = checkRng.parentElement(); |
3291 | |
3292 // If parent doesn't have any children then set the container to that parent and the index to 0 | |
3293 if (!parent.hasChildNodes()) { | |
3294 domRange[start ? 'setStart' : 'setEnd'](parent, 0); | |
3295 return; | |
3296 } | |
3297 | |
3292 parent.appendChild(marker); | 3298 parent.appendChild(marker); |
3293 checkRng.moveToElementText(marker); | 3299 checkRng.moveToElementText(marker); |
3294 position = ieRange.compareEndPoints(start ? 'StartToStart' : 'EndToEnd', checkRng); | 3300 position = ieRange.compareEndPoints(start ? 'StartToStart' : 'EndToEnd', checkRng); |
3295 if (position > 0) { | 3301 if (position > 0) { |
3296 // The position is after the end of the parent element. | 3302 // The position is after the end of the parent element. |
3363 | 3369 |
3364 return domRange; | 3370 return domRange; |
3365 }; | 3371 }; |
3366 | 3372 |
3367 this.addRange = function(rng) { | 3373 this.addRange = function(rng) { |
3368 var ieRng, ieRng2, doc = selection.dom.doc, body = doc.body, startPos, endPos, sc, so, ec, eo, marker, lastIndex, skipStart, skipEnd; | 3374 var ieRng, ctrlRng, startContainer, startOffset, endContainer, endOffset, doc = selection.dom.doc, body = doc.body; |
3369 | 3375 |
3376 function setEndPoint(start) { | |
3377 var container, offset, marker, tmpRng, nodes; | |
3378 | |
3379 marker = dom.create('a'); | |
3380 container = start ? startContainer : endContainer; | |
3381 offset = start ? startOffset : endOffset; | |
3382 tmpRng = ieRng.duplicate(); | |
3383 | |
3384 if (container == doc) { | |
3385 container = body; | |
3386 offset = 0; | |
3387 } | |
3388 | |
3389 if (container.nodeType == 3) { | |
3390 container.parentNode.insertBefore(marker, container); | |
3391 tmpRng.moveToElementText(marker); | |
3392 tmpRng.moveStart('character', offset); | |
3393 dom.remove(marker); | |
3394 ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng); | |
3395 } else { | |
3396 nodes = container.childNodes; | |
3397 | |
3398 if (nodes.length) { | |
3399 if (offset >= nodes.length) { | |
3400 dom.insertAfter(marker, nodes[nodes.length - 1]); | |
3401 } else { | |
3402 container.insertBefore(marker, nodes[offset]); | |
3403 } | |
3404 | |
3405 tmpRng.moveToElementText(marker); | |
3406 } else { | |
3407 // Empty node selection for example <div>|</div> | |
3408 marker = doc.createTextNode(invisibleChar); | |
3409 container.appendChild(marker); | |
3410 tmpRng.moveToElementText(marker.parentNode); | |
3411 tmpRng.collapse(TRUE); | |
3412 } | |
3413 | |
3414 ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng); | |
3415 dom.remove(marker); | |
3416 } | |
3417 } | |
3418 | |
3419 // Destroy cached range | |
3370 this.destroy(); | 3420 this.destroy(); |
3371 | 3421 |
3372 // Setup some shorter versions | 3422 // Setup some shorter versions |
3373 sc = rng.startContainer; | 3423 startContainer = rng.startContainer; |
3374 so = rng.startOffset; | 3424 startOffset = rng.startOffset; |
3375 ec = rng.endContainer; | 3425 endContainer = rng.endContainer; |
3376 eo = rng.endOffset; | 3426 endOffset = rng.endOffset; |
3377 ieRng = body.createTextRange(); | 3427 ieRng = body.createTextRange(); |
3378 | 3428 |
3379 // If document selection move caret to first node in document | 3429 // If single element selection then try making a control selection out of it |
3380 if (sc == doc || ec == doc) { | 3430 if (startContainer == endContainer && startContainer.nodeType == 1 && startOffset == endOffset - 1) { |
3381 ieRng = body.createTextRange(); | 3431 if (startOffset == endOffset - 1) { |
3382 ieRng.collapse(); | 3432 try { |
3383 ieRng.select(); | 3433 ctrlRng = body.createControlRange(); |
3384 return; | 3434 ctrlRng.addElement(startContainer.childNodes[startOffset]); |
3385 } | 3435 ctrlRng.select(); |
3386 | 3436 ctrlRng.scrollIntoView(); |
3387 // If child index resolve it | 3437 return; |
3388 if (sc.nodeType == 1 && sc.hasChildNodes()) { | 3438 } catch (ex) { |
3389 lastIndex = sc.childNodes.length - 1; | 3439 // Ignore |
3390 | |
3391 // Index is higher that the child count then we need to jump over the start container | |
3392 if (so > lastIndex) { | |
3393 skipStart = 1; | |
3394 sc = sc.childNodes[lastIndex]; | |
3395 } else | |
3396 sc = sc.childNodes[so]; | |
3397 | |
3398 // Child was text node then move offset to start of it | |
3399 if (sc.nodeType == 3) | |
3400 so = 0; | |
3401 } | |
3402 | |
3403 // If child index resolve it | |
3404 if (ec.nodeType == 1 && ec.hasChildNodes()) { | |
3405 lastIndex = ec.childNodes.length - 1; | |
3406 | |
3407 if (eo == 0) { | |
3408 skipEnd = 1; | |
3409 ec = ec.childNodes[0]; | |
3410 } else { | |
3411 ec = ec.childNodes[Math.min(lastIndex, eo - 1)]; | |
3412 | |
3413 // Child was text node then move offset to end of text node | |
3414 if (ec.nodeType == 3) | |
3415 eo = ec.nodeValue.length; | |
3416 } | |
3417 } | |
3418 | |
3419 // Single element selection | |
3420 if (sc == ec && sc.nodeType == 1) { | |
3421 // Make control selection for some elements | |
3422 if (/^(IMG|TABLE)$/.test(sc.nodeName) && so != eo) { | |
3423 ieRng = body.createControlRange(); | |
3424 ieRng.addElement(sc); | |
3425 } else { | |
3426 ieRng = body.createTextRange(); | |
3427 | |
3428 // Padd empty elements with invisible character | |
3429 if (!sc.hasChildNodes() && sc.canHaveHTML) | |
3430 sc.innerHTML = invisibleChar; | |
3431 | |
3432 // Select element contents | |
3433 ieRng.moveToElementText(sc); | |
3434 | |
3435 // If it's only containing a padding remove it so the caret remains | |
3436 if (sc.innerHTML == invisibleChar) { | |
3437 ieRng.collapse(TRUE); | |
3438 sc.removeChild(sc.firstChild); | |
3439 } | 3440 } |
3440 } | 3441 } |
3441 | 3442 } |
3442 if (so == eo) | 3443 |
3443 ieRng.collapse(eo <= rng.endContainer.childNodes.length - 1); | 3444 // Set start/end point of selection |
3444 | 3445 setEndPoint(true); |
3445 ieRng.select(); | 3446 setEndPoint(); |
3446 ieRng.scrollIntoView(); | 3447 |
3447 return; | 3448 // Select the new range and scroll it into view |
3448 } | |
3449 | |
3450 // Create range and marker | |
3451 ieRng = body.createTextRange(); | |
3452 marker = doc.createElement('span'); | |
3453 marker.innerHTML = ' '; | |
3454 | |
3455 // Set start of range to startContainer/startOffset | |
3456 if (sc.nodeType == 3) { | |
3457 // Insert marker after/before startContainer | |
3458 if (skipStart) | |
3459 dom.insertAfter(marker, sc); | |
3460 else | |
3461 sc.parentNode.insertBefore(marker, sc); | |
3462 | |
3463 // Select marker the caret to offset position | |
3464 ieRng.moveToElementText(marker); | |
3465 marker.parentNode.removeChild(marker); | |
3466 ieRng.move('character', so); | |
3467 } else { | |
3468 ieRng.moveToElementText(sc); | |
3469 | |
3470 if (skipStart) | |
3471 ieRng.collapse(FALSE); | |
3472 } | |
3473 | |
3474 // If same text container then we can do a more simple move | |
3475 if (sc == ec && sc.nodeType == 3) { | |
3476 try { | |
3477 ieRng.moveEnd('character', eo - so); | |
3478 ieRng.select(); | |
3479 ieRng.scrollIntoView(); | |
3480 } catch (ex) { | |
3481 // Some times a Runtime error of the 800a025e type gets thrown | |
3482 // especially when the caret is placed before a table. | |
3483 // This is a somewhat strange location for the caret. | |
3484 // TODO: Find a better solution for this would possible require a rewrite of the setRng method | |
3485 } | |
3486 | |
3487 return; | |
3488 } | |
3489 | |
3490 // Set end of range to endContainer/endOffset | |
3491 ieRng2 = body.createTextRange(); | |
3492 if (ec.nodeType == 3) { | |
3493 // Insert marker after/before startContainer | |
3494 ec.parentNode.insertBefore(marker, ec); | |
3495 | |
3496 // Move selection to end marker and move caret to end offset | |
3497 ieRng2.moveToElementText(marker); | |
3498 marker.parentNode.removeChild(marker); | |
3499 ieRng2.move('character', eo); | |
3500 ieRng.setEndPoint('EndToStart', ieRng2); | |
3501 } else { | |
3502 ieRng2.moveToElementText(ec); | |
3503 ieRng2.collapse(!!skipEnd); | |
3504 ieRng.setEndPoint('EndToEnd', ieRng2); | |
3505 } | |
3506 | |
3507 ieRng.select(); | 3449 ieRng.select(); |
3508 ieRng.scrollIntoView(); | 3450 ieRng.scrollIntoView(); |
3509 }; | 3451 }; |
3510 | 3452 |
3511 this.getRangeAt = function() { | 3453 this.getRangeAt = function() { |
3621 * Released under the MIT, BSD, and GPL Licenses. | 3563 * Released under the MIT, BSD, and GPL Licenses. |
3622 * More information: http://sizzlejs.com/ | 3564 * More information: http://sizzlejs.com/ |
3623 */ | 3565 */ |
3624 (function(){ | 3566 (function(){ |
3625 | 3567 |
3626 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g, | 3568 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, |
3627 done = 0, | 3569 done = 0, |
3628 toString = Object.prototype.toString, | 3570 toString = Object.prototype.toString, |
3629 hasDuplicate = false; | 3571 hasDuplicate = false, |
3572 baseHasDuplicate = true; | |
3573 | |
3574 // Here we check if the JavaScript engine is using some sort of | |
3575 // optimization where it does not always call our comparision | |
3576 // function. If that is the case, discard the hasDuplicate value. | |
3577 // Thus far that includes Google Chrome. | |
3578 [0, 0].sort(function(){ | |
3579 baseHasDuplicate = false; | |
3580 return 0; | |
3581 }); | |
3630 | 3582 |
3631 var Sizzle = function(selector, context, results, seed) { | 3583 var Sizzle = function(selector, context, results, seed) { |
3632 results = results || []; | 3584 results = results || []; |
3633 var origContext = context = context || document; | 3585 context = context || document; |
3586 | |
3587 var origContext = context; | |
3634 | 3588 |
3635 if ( context.nodeType !== 1 && context.nodeType !== 9 ) { | 3589 if ( context.nodeType !== 1 && context.nodeType !== 9 ) { |
3636 return []; | 3590 return []; |
3637 } | 3591 } |
3638 | 3592 |
3639 if ( !selector || typeof selector !== "string" ) { | 3593 if ( !selector || typeof selector !== "string" ) { |
3640 return results; | 3594 return results; |
3641 } | 3595 } |
3642 | 3596 |
3643 var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context); | 3597 var parts = [], m, set, checkSet, extra, prune = true, contextXML = Sizzle.isXML(context), |
3598 soFar = selector, ret, cur, pop, i; | |
3644 | 3599 |
3645 // Reset the position of the chunker regexp (start from head) | 3600 // Reset the position of the chunker regexp (start from head) |
3646 chunker.lastIndex = 0; | 3601 do { |
3647 | 3602 chunker.exec(""); |
3648 while ( (m = chunker.exec(selector)) !== null ) { | 3603 m = chunker.exec(soFar); |
3649 parts.push( m[1] ); | 3604 |
3605 if ( m ) { | |
3606 soFar = m[3]; | |
3650 | 3607 |
3651 if ( m[2] ) { | 3608 parts.push( m[1] ); |
3652 extra = RegExp.rightContext; | 3609 |
3653 break; | 3610 if ( m[2] ) { |
3611 extra = m[3]; | |
3612 break; | |
3613 } | |
3654 } | 3614 } |
3655 } | 3615 } while ( m ); |
3656 | 3616 |
3657 if ( parts.length > 1 && origPOS.exec( selector ) ) { | 3617 if ( parts.length > 1 && origPOS.exec( selector ) ) { |
3658 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { | 3618 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { |
3659 set = posProcess( parts[0] + parts[1], context ); | 3619 set = posProcess( parts[0] + parts[1], context ); |
3660 } else { | 3620 } else { |
3663 Sizzle( parts.shift(), context ); | 3623 Sizzle( parts.shift(), context ); |
3664 | 3624 |
3665 while ( parts.length ) { | 3625 while ( parts.length ) { |
3666 selector = parts.shift(); | 3626 selector = parts.shift(); |
3667 | 3627 |
3668 if ( Expr.relative[ selector ] ) | 3628 if ( Expr.relative[ selector ] ) { |
3669 selector += parts.shift(); | 3629 selector += parts.shift(); |
3670 | 3630 } |
3631 | |
3671 set = posProcess( selector, set ); | 3632 set = posProcess( selector, set ); |
3672 } | 3633 } |
3673 } | 3634 } |
3674 } else { | 3635 } else { |
3675 // Take a shortcut and set the context if the root selector is an ID | 3636 // Take a shortcut and set the context if the root selector is an ID |
3676 // (but not if it'll be faster if the inner selector is an ID) | 3637 // (but not if it'll be faster if the inner selector is an ID) |
3677 if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && | 3638 if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && |
3678 Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { | 3639 Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { |
3679 var ret = Sizzle.find( parts.shift(), context, contextXML ); | 3640 ret = Sizzle.find( parts.shift(), context, contextXML ); |
3680 context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; | 3641 context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; |
3681 } | 3642 } |
3682 | 3643 |
3683 if ( context ) { | 3644 if ( context ) { |
3684 var ret = seed ? | 3645 ret = seed ? |
3685 { expr: parts.pop(), set: makeArray(seed) } : | 3646 { expr: parts.pop(), set: makeArray(seed) } : |
3686 Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); | 3647 Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); |
3687 set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; | 3648 set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; |
3688 | 3649 |
3689 if ( parts.length > 0 ) { | 3650 if ( parts.length > 0 ) { |
3691 } else { | 3652 } else { |
3692 prune = false; | 3653 prune = false; |
3693 } | 3654 } |
3694 | 3655 |
3695 while ( parts.length ) { | 3656 while ( parts.length ) { |
3696 var cur = parts.pop(), pop = cur; | 3657 cur = parts.pop(); |
3658 pop = cur; | |
3697 | 3659 |
3698 if ( !Expr.relative[ cur ] ) { | 3660 if ( !Expr.relative[ cur ] ) { |
3699 cur = ""; | 3661 cur = ""; |
3700 } else { | 3662 } else { |
3701 pop = parts.pop(); | 3663 pop = parts.pop(); |
3715 if ( !checkSet ) { | 3677 if ( !checkSet ) { |
3716 checkSet = set; | 3678 checkSet = set; |
3717 } | 3679 } |
3718 | 3680 |
3719 if ( !checkSet ) { | 3681 if ( !checkSet ) { |
3720 throw "Syntax error, unrecognized expression: " + (cur || selector); | 3682 Sizzle.error( cur || selector ); |
3721 } | 3683 } |
3722 | 3684 |
3723 if ( toString.call(checkSet) === "[object Array]" ) { | 3685 if ( toString.call(checkSet) === "[object Array]" ) { |
3724 if ( !prune ) { | 3686 if ( !prune ) { |
3725 results.push.apply( results, checkSet ); | 3687 results.push.apply( results, checkSet ); |
3726 } else if ( context && context.nodeType === 1 ) { | 3688 } else if ( context && context.nodeType === 1 ) { |
3727 for ( var i = 0; checkSet[i] != null; i++ ) { | 3689 for ( i = 0; checkSet[i] != null; i++ ) { |
3728 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { | 3690 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { |
3729 results.push( set[i] ); | 3691 results.push( set[i] ); |
3730 } | 3692 } |
3731 } | 3693 } |
3732 } else { | 3694 } else { |
3733 for ( var i = 0; checkSet[i] != null; i++ ) { | 3695 for ( i = 0; checkSet[i] != null; i++ ) { |
3734 if ( checkSet[i] && checkSet[i].nodeType === 1 ) { | 3696 if ( checkSet[i] && checkSet[i].nodeType === 1 ) { |
3735 results.push( set[i] ); | 3697 results.push( set[i] ); |
3736 } | 3698 } |
3737 } | 3699 } |
3738 } | 3700 } |
3748 return results; | 3710 return results; |
3749 }; | 3711 }; |
3750 | 3712 |
3751 Sizzle.uniqueSort = function(results){ | 3713 Sizzle.uniqueSort = function(results){ |
3752 if ( sortOrder ) { | 3714 if ( sortOrder ) { |
3753 hasDuplicate = false; | 3715 hasDuplicate = baseHasDuplicate; |
3754 results.sort(sortOrder); | 3716 results.sort(sortOrder); |
3755 | 3717 |
3756 if ( hasDuplicate ) { | 3718 if ( hasDuplicate ) { |
3757 for ( var i = 1; i < results.length; i++ ) { | 3719 for ( var i = 1; i < results.length; i++ ) { |
3758 if ( results[i] === results[i-1] ) { | 3720 if ( results[i] === results[i-1] ) { |
3759 results.splice(i--, 1); | 3721 results.splice(i--, 1); |
3760 } | 3722 } |
3761 } | 3723 } |
3762 } | 3724 } |
3763 } | 3725 } |
3726 | |
3727 return results; | |
3764 }; | 3728 }; |
3765 | 3729 |
3766 Sizzle.matches = function(expr, set){ | 3730 Sizzle.matches = function(expr, set){ |
3767 return Sizzle(expr, null, null, set); | 3731 return Sizzle(expr, null, null, set); |
3768 }; | 3732 }; |
3769 | 3733 |
3770 Sizzle.find = function(expr, context, isXML){ | 3734 Sizzle.find = function(expr, context, isXML){ |
3771 var set, match; | 3735 var set; |
3772 | 3736 |
3773 if ( !expr ) { | 3737 if ( !expr ) { |
3774 return []; | 3738 return []; |
3775 } | 3739 } |
3776 | 3740 |
3777 for ( var i = 0, l = Expr.order.length; i < l; i++ ) { | 3741 for ( var i = 0, l = Expr.order.length; i < l; i++ ) { |
3778 var type = Expr.order[i], match; | 3742 var type = Expr.order[i], match; |
3779 | 3743 |
3780 if ( (match = Expr.match[ type ].exec( expr )) ) { | 3744 if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { |
3781 var left = RegExp.leftContext; | 3745 var left = match[1]; |
3746 match.splice(1,1); | |
3782 | 3747 |
3783 if ( left.substr( left.length - 1 ) !== "\\" ) { | 3748 if ( left.substr( left.length - 1 ) !== "\\" ) { |
3784 match[1] = (match[1] || "").replace(/\\/g, ""); | 3749 match[1] = (match[1] || "").replace(/\\/g, ""); |
3785 set = Expr.find[ type ]( match, context, isXML ); | 3750 set = Expr.find[ type ]( match, context, isXML ); |
3786 if ( set != null ) { | 3751 if ( set != null ) { |
3798 return {set: set, expr: expr}; | 3763 return {set: set, expr: expr}; |
3799 }; | 3764 }; |
3800 | 3765 |
3801 Sizzle.filter = function(expr, set, inplace, not){ | 3766 Sizzle.filter = function(expr, set, inplace, not){ |
3802 var old = expr, result = [], curLoop = set, match, anyFound, | 3767 var old = expr, result = [], curLoop = set, match, anyFound, |
3803 isXMLFilter = set && set[0] && isXML(set[0]); | 3768 isXMLFilter = set && set[0] && Sizzle.isXML(set[0]); |
3804 | 3769 |
3805 while ( expr && set.length ) { | 3770 while ( expr && set.length ) { |
3806 for ( var type in Expr.filter ) { | 3771 for ( var type in Expr.filter ) { |
3807 if ( (match = Expr.match[ type ].exec( expr )) != null ) { | 3772 if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { |
3808 var filter = Expr.filter[ type ], found, item; | 3773 var filter = Expr.filter[ type ], found, item, left = match[1]; |
3809 anyFound = false; | 3774 anyFound = false; |
3810 | 3775 |
3811 if ( curLoop == result ) { | 3776 match.splice(1,1); |
3777 | |
3778 if ( left.substr( left.length - 1 ) === "\\" ) { | |
3779 continue; | |
3780 } | |
3781 | |
3782 if ( curLoop === result ) { | |
3812 result = []; | 3783 result = []; |
3813 } | 3784 } |
3814 | 3785 |
3815 if ( Expr.preFilter[ type ] ) { | 3786 if ( Expr.preFilter[ type ] ) { |
3816 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); | 3787 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); |
3857 } | 3828 } |
3858 } | 3829 } |
3859 } | 3830 } |
3860 | 3831 |
3861 // Improper expression | 3832 // Improper expression |
3862 if ( expr == old ) { | 3833 if ( expr === old ) { |
3863 if ( anyFound == null ) { | 3834 if ( anyFound == null ) { |
3864 throw "Syntax error, unrecognized expression: " + expr; | 3835 Sizzle.error( expr ); |
3865 } else { | 3836 } else { |
3866 break; | 3837 break; |
3867 } | 3838 } |
3868 } | 3839 } |
3869 | 3840 |
3870 old = expr; | 3841 old = expr; |
3871 } | 3842 } |
3872 | 3843 |
3873 return curLoop; | 3844 return curLoop; |
3845 }; | |
3846 | |
3847 Sizzle.error = function( msg ) { | |
3848 throw "Syntax error, unrecognized expression: " + msg; | |
3874 }; | 3849 }; |
3875 | 3850 |
3876 var Expr = Sizzle.selectors = { | 3851 var Expr = Sizzle.selectors = { |
3877 order: [ "ID", "NAME", "TAG" ], | 3852 order: [ "ID", "NAME", "TAG" ], |
3878 match: { | 3853 match: { |
3879 ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, | 3854 ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, |
3880 CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, | 3855 CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, |
3881 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/, | 3856 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, |
3882 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, | 3857 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, |
3883 TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/, | 3858 TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, |
3884 CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, | 3859 CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/, |
3885 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, | 3860 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, |
3886 PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/ | 3861 PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ |
3887 }, | 3862 }, |
3863 leftMatch: {}, | |
3888 attrMap: { | 3864 attrMap: { |
3889 "class": "className", | 3865 "class": "className", |
3890 "for": "htmlFor" | 3866 "for": "htmlFor" |
3891 }, | 3867 }, |
3892 attrHandle: { | 3868 attrHandle: { |
3893 href: function(elem){ | 3869 href: function(elem){ |
3894 return elem.getAttribute("href"); | 3870 return elem.getAttribute("href"); |
3895 } | 3871 } |
3896 }, | 3872 }, |
3897 relative: { | 3873 relative: { |
3898 "+": function(checkSet, part, isXML){ | 3874 "+": function(checkSet, part){ |
3899 var isPartStr = typeof part === "string", | 3875 var isPartStr = typeof part === "string", |
3900 isTag = isPartStr && !/\W/.test(part), | 3876 isTag = isPartStr && !/\W/.test(part), |
3901 isPartStrNotTag = isPartStr && !isTag; | 3877 isPartStrNotTag = isPartStr && !isTag; |
3902 | 3878 |
3903 if ( isTag && !isXML ) { | 3879 if ( isTag ) { |
3904 part = part.toUpperCase(); | 3880 part = part.toLowerCase(); |
3905 } | 3881 } |
3906 | 3882 |
3907 for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { | 3883 for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { |
3908 if ( (elem = checkSet[i]) ) { | 3884 if ( (elem = checkSet[i]) ) { |
3909 while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} | 3885 while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} |
3910 | 3886 |
3911 checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ? | 3887 checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? |
3912 elem || false : | 3888 elem || false : |
3913 elem === part; | 3889 elem === part; |
3914 } | 3890 } |
3915 } | 3891 } |
3916 | 3892 |
3917 if ( isPartStrNotTag ) { | 3893 if ( isPartStrNotTag ) { |
3918 Sizzle.filter( part, checkSet, true ); | 3894 Sizzle.filter( part, checkSet, true ); |
3919 } | 3895 } |
3920 }, | 3896 }, |
3921 ">": function(checkSet, part, isXML){ | 3897 ">": function(checkSet, part){ |
3922 var isPartStr = typeof part === "string"; | 3898 var isPartStr = typeof part === "string", |
3899 elem, i = 0, l = checkSet.length; | |
3923 | 3900 |
3924 if ( isPartStr && !/\W/.test(part) ) { | 3901 if ( isPartStr && !/\W/.test(part) ) { |
3925 part = isXML ? part : part.toUpperCase(); | 3902 part = part.toLowerCase(); |
3926 | 3903 |
3927 for ( var i = 0, l = checkSet.length; i < l; i++ ) { | 3904 for ( ; i < l; i++ ) { |
3928 var elem = checkSet[i]; | 3905 elem = checkSet[i]; |
3929 if ( elem ) { | 3906 if ( elem ) { |
3930 var parent = elem.parentNode; | 3907 var parent = elem.parentNode; |
3931 checkSet[i] = parent.nodeName === part ? parent : false; | 3908 checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; |
3932 } | 3909 } |
3933 } | 3910 } |
3934 } else { | 3911 } else { |
3935 for ( var i = 0, l = checkSet.length; i < l; i++ ) { | 3912 for ( ; i < l; i++ ) { |
3936 var elem = checkSet[i]; | 3913 elem = checkSet[i]; |
3937 if ( elem ) { | 3914 if ( elem ) { |
3938 checkSet[i] = isPartStr ? | 3915 checkSet[i] = isPartStr ? |
3939 elem.parentNode : | 3916 elem.parentNode : |
3940 elem.parentNode === part; | 3917 elem.parentNode === part; |
3941 } | 3918 } |
3945 Sizzle.filter( part, checkSet, true ); | 3922 Sizzle.filter( part, checkSet, true ); |
3946 } | 3923 } |
3947 } | 3924 } |
3948 }, | 3925 }, |
3949 "": function(checkSet, part, isXML){ | 3926 "": function(checkSet, part, isXML){ |
3950 var doneName = done++, checkFn = dirCheck; | 3927 var doneName = done++, checkFn = dirCheck, nodeCheck; |
3951 | 3928 |
3952 if ( !part.match(/\W/) ) { | 3929 if ( typeof part === "string" && !/\W/.test(part) ) { |
3953 var nodeCheck = part = isXML ? part : part.toUpperCase(); | 3930 part = part.toLowerCase(); |
3931 nodeCheck = part; | |
3954 checkFn = dirNodeCheck; | 3932 checkFn = dirNodeCheck; |
3955 } | 3933 } |
3956 | 3934 |
3957 checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); | 3935 checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); |
3958 }, | 3936 }, |
3959 "~": function(checkSet, part, isXML){ | 3937 "~": function(checkSet, part, isXML){ |
3960 var doneName = done++, checkFn = dirCheck; | 3938 var doneName = done++, checkFn = dirCheck, nodeCheck; |
3961 | 3939 |
3962 if ( typeof part === "string" && !part.match(/\W/) ) { | 3940 if ( typeof part === "string" && !/\W/.test(part) ) { |
3963 var nodeCheck = part = isXML ? part : part.toUpperCase(); | 3941 part = part.toLowerCase(); |
3942 nodeCheck = part; | |
3964 checkFn = dirNodeCheck; | 3943 checkFn = dirNodeCheck; |
3965 } | 3944 } |
3966 | 3945 |
3967 checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); | 3946 checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); |
3968 } | 3947 } |
3972 if ( typeof context.getElementById !== "undefined" && !isXML ) { | 3951 if ( typeof context.getElementById !== "undefined" && !isXML ) { |
3973 var m = context.getElementById(match[1]); | 3952 var m = context.getElementById(match[1]); |
3974 return m ? [m] : []; | 3953 return m ? [m] : []; |
3975 } | 3954 } |
3976 }, | 3955 }, |
3977 NAME: function(match, context, isXML){ | 3956 NAME: function(match, context){ |
3978 if ( typeof context.getElementsByName !== "undefined" ) { | 3957 if ( typeof context.getElementsByName !== "undefined" ) { |
3979 var ret = [], results = context.getElementsByName(match[1]); | 3958 var ret = [], results = context.getElementsByName(match[1]); |
3980 | 3959 |
3981 for ( var i = 0, l = results.length; i < l; i++ ) { | 3960 for ( var i = 0, l = results.length; i < l; i++ ) { |
3982 if ( results[i].getAttribute("name") === match[1] ) { | 3961 if ( results[i].getAttribute("name") === match[1] ) { |
3999 return match; | 3978 return match; |
4000 } | 3979 } |
4001 | 3980 |
4002 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { | 3981 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { |
4003 if ( elem ) { | 3982 if ( elem ) { |
4004 if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) { | 3983 if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) { |
4005 if ( !inplace ) | 3984 if ( !inplace ) { |
4006 result.push( elem ); | 3985 result.push( elem ); |
3986 } | |
4007 } else if ( inplace ) { | 3987 } else if ( inplace ) { |
4008 curLoop[i] = false; | 3988 curLoop[i] = false; |
4009 } | 3989 } |
4010 } | 3990 } |
4011 } | 3991 } |
4014 }, | 3994 }, |
4015 ID: function(match){ | 3995 ID: function(match){ |
4016 return match[1].replace(/\\/g, ""); | 3996 return match[1].replace(/\\/g, ""); |
4017 }, | 3997 }, |
4018 TAG: function(match, curLoop){ | 3998 TAG: function(match, curLoop){ |
4019 for ( var i = 0; curLoop[i] === false; i++ ){} | 3999 return match[1].toLowerCase(); |
4020 return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase(); | |
4021 }, | 4000 }, |
4022 CHILD: function(match){ | 4001 CHILD: function(match){ |
4023 if ( match[1] == "nth" ) { | 4002 if ( match[1] === "nth" ) { |
4024 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' | 4003 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' |
4025 var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( | 4004 var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( |
4026 match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" || | 4005 match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || |
4027 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); | 4006 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); |
4028 | 4007 |
4029 // calculate the numbers (first)n+(last) including if they are negative | 4008 // calculate the numbers (first)n+(last) including if they are negative |
4030 match[2] = (test[1] + (test[2] || 1)) - 0; | 4009 match[2] = (test[1] + (test[2] || 1)) - 0; |
4031 match[3] = test[3] - 0; | 4010 match[3] = test[3] - 0; |
4050 return match; | 4029 return match; |
4051 }, | 4030 }, |
4052 PSEUDO: function(match, curLoop, inplace, result, not){ | 4031 PSEUDO: function(match, curLoop, inplace, result, not){ |
4053 if ( match[1] === "not" ) { | 4032 if ( match[1] === "not" ) { |
4054 // If we're dealing with a complex expression, or a simple one | 4033 // If we're dealing with a complex expression, or a simple one |
4055 if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) { | 4034 if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { |
4056 match[3] = Sizzle(match[3], null, null, curLoop); | 4035 match[3] = Sizzle(match[3], null, null, curLoop); |
4057 } else { | 4036 } else { |
4058 var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); | 4037 var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); |
4059 if ( !inplace ) { | 4038 if ( !inplace ) { |
4060 result.push.apply( result, ret ); | 4039 result.push.apply( result, ret ); |
4096 }, | 4075 }, |
4097 has: function(elem, i, match){ | 4076 has: function(elem, i, match){ |
4098 return !!Sizzle( match[3], elem ).length; | 4077 return !!Sizzle( match[3], elem ).length; |
4099 }, | 4078 }, |
4100 header: function(elem){ | 4079 header: function(elem){ |
4101 return /h\d/i.test( elem.nodeName ); | 4080 return (/h\d/i).test( elem.nodeName ); |
4102 }, | 4081 }, |
4103 text: function(elem){ | 4082 text: function(elem){ |
4104 return "text" === elem.type; | 4083 return "text" === elem.type; |
4105 }, | 4084 }, |
4106 radio: function(elem){ | 4085 radio: function(elem){ |
4123 }, | 4102 }, |
4124 reset: function(elem){ | 4103 reset: function(elem){ |
4125 return "reset" === elem.type; | 4104 return "reset" === elem.type; |
4126 }, | 4105 }, |
4127 button: function(elem){ | 4106 button: function(elem){ |
4128 return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON"; | 4107 return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; |
4129 }, | 4108 }, |
4130 input: function(elem){ | 4109 input: function(elem){ |
4131 return /input|select|textarea|button/i.test(elem.nodeName); | 4110 return (/input|select|textarea|button/i).test(elem.nodeName); |
4132 } | 4111 } |
4133 }, | 4112 }, |
4134 setFilters: { | 4113 setFilters: { |
4135 first: function(elem, i){ | 4114 first: function(elem, i){ |
4136 return i === 0; | 4115 return i === 0; |
4149 }, | 4128 }, |
4150 gt: function(elem, i, match){ | 4129 gt: function(elem, i, match){ |
4151 return i > match[3] - 0; | 4130 return i > match[3] - 0; |
4152 }, | 4131 }, |
4153 nth: function(elem, i, match){ | 4132 nth: function(elem, i, match){ |
4154 return match[3] - 0 == i; | 4133 return match[3] - 0 === i; |
4155 }, | 4134 }, |
4156 eq: function(elem, i, match){ | 4135 eq: function(elem, i, match){ |
4157 return match[3] - 0 == i; | 4136 return match[3] - 0 === i; |
4158 } | 4137 } |
4159 }, | 4138 }, |
4160 filter: { | 4139 filter: { |
4161 PSEUDO: function(elem, match, i, array){ | 4140 PSEUDO: function(elem, match, i, array){ |
4162 var name = match[1], filter = Expr.filters[ name ]; | 4141 var name = match[1], filter = Expr.filters[ name ]; |
4163 | 4142 |
4164 if ( filter ) { | 4143 if ( filter ) { |
4165 return filter( elem, i, match, array ); | 4144 return filter( elem, i, match, array ); |
4166 } else if ( name === "contains" ) { | 4145 } else if ( name === "contains" ) { |
4167 return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0; | 4146 return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; |
4168 } else if ( name === "not" ) { | 4147 } else if ( name === "not" ) { |
4169 var not = match[3]; | 4148 var not = match[3]; |
4170 | 4149 |
4171 for ( var i = 0, l = not.length; i < l; i++ ) { | 4150 for ( var j = 0, l = not.length; j < l; j++ ) { |
4172 if ( not[i] === elem ) { | 4151 if ( not[j] === elem ) { |
4173 return false; | 4152 return false; |
4174 } | 4153 } |
4175 } | 4154 } |
4176 | 4155 |
4177 return true; | 4156 return true; |
4157 } else { | |
4158 Sizzle.error( "Syntax error, unrecognized expression: " + name ); | |
4178 } | 4159 } |
4179 }, | 4160 }, |
4180 CHILD: function(elem, match){ | 4161 CHILD: function(elem, match){ |
4181 var type = match[1], node = elem; | 4162 var type = match[1], node = elem; |
4182 switch (type) { | 4163 switch (type) { |
4183 case 'only': | 4164 case 'only': |
4184 case 'first': | 4165 case 'first': |
4185 while (node = node.previousSibling) { | 4166 while ( (node = node.previousSibling) ) { |
4186 if ( node.nodeType === 1 ) return false; | 4167 if ( node.nodeType === 1 ) { |
4168 return false; | |
4169 } | |
4187 } | 4170 } |
4188 if ( type == 'first') return true; | 4171 if ( type === "first" ) { |
4172 return true; | |
4173 } | |
4189 node = elem; | 4174 node = elem; |
4190 case 'last': | 4175 case 'last': |
4191 while (node = node.nextSibling) { | 4176 while ( (node = node.nextSibling) ) { |
4192 if ( node.nodeType === 1 ) return false; | 4177 if ( node.nodeType === 1 ) { |
4178 return false; | |
4179 } | |
4193 } | 4180 } |
4194 return true; | 4181 return true; |
4195 case 'nth': | 4182 case 'nth': |
4196 var first = match[2], last = match[3]; | 4183 var first = match[2], last = match[3]; |
4197 | 4184 |
4198 if ( first == 1 && last == 0 ) { | 4185 if ( first === 1 && last === 0 ) { |
4199 return true; | 4186 return true; |
4200 } | 4187 } |
4201 | 4188 |
4202 var doneName = match[0], | 4189 var doneName = match[0], |
4203 parent = elem.parentNode; | 4190 parent = elem.parentNode; |
4211 } | 4198 } |
4212 parent.sizcache = doneName; | 4199 parent.sizcache = doneName; |
4213 } | 4200 } |
4214 | 4201 |
4215 var diff = elem.nodeIndex - last; | 4202 var diff = elem.nodeIndex - last; |
4216 if ( first == 0 ) { | 4203 if ( first === 0 ) { |
4217 return diff == 0; | 4204 return diff === 0; |
4218 } else { | 4205 } else { |
4219 return ( diff % first == 0 && diff / first >= 0 ); | 4206 return ( diff % first === 0 && diff / first >= 0 ); |
4220 } | 4207 } |
4221 } | 4208 } |
4222 }, | 4209 }, |
4223 ID: function(elem, match){ | 4210 ID: function(elem, match){ |
4224 return elem.nodeType === 1 && elem.getAttribute("id") === match; | 4211 return elem.nodeType === 1 && elem.getAttribute("id") === match; |
4225 }, | 4212 }, |
4226 TAG: function(elem, match){ | 4213 TAG: function(elem, match){ |
4227 return (match === "*" && elem.nodeType === 1) || elem.nodeName === match; | 4214 return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; |
4228 }, | 4215 }, |
4229 CLASS: function(elem, match){ | 4216 CLASS: function(elem, match){ |
4230 return (" " + (elem.className || elem.getAttribute("class")) + " ") | 4217 return (" " + (elem.className || elem.getAttribute("class")) + " ") |
4231 .indexOf( match ) > -1; | 4218 .indexOf( match ) > -1; |
4232 }, | 4219 }, |
4250 type === "~=" ? | 4237 type === "~=" ? |
4251 (" " + value + " ").indexOf(check) >= 0 : | 4238 (" " + value + " ").indexOf(check) >= 0 : |
4252 !check ? | 4239 !check ? |
4253 value && result !== false : | 4240 value && result !== false : |
4254 type === "!=" ? | 4241 type === "!=" ? |
4255 value != check : | 4242 value !== check : |
4256 type === "^=" ? | 4243 type === "^=" ? |
4257 value.indexOf(check) === 0 : | 4244 value.indexOf(check) === 0 : |
4258 type === "$=" ? | 4245 type === "$=" ? |
4259 value.substr(value.length - check.length) === check : | 4246 value.substr(value.length - check.length) === check : |
4260 type === "|=" ? | 4247 type === "|=" ? |
4269 } | 4256 } |
4270 } | 4257 } |
4271 } | 4258 } |
4272 }; | 4259 }; |
4273 | 4260 |
4274 var origPOS = Expr.match.POS; | 4261 var origPOS = Expr.match.POS, |
4262 fescape = function(all, num){ | |
4263 return "\\" + (num - 0 + 1); | |
4264 }; | |
4275 | 4265 |
4276 for ( var type in Expr.match ) { | 4266 for ( var type in Expr.match ) { |
4277 Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); | 4267 Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); |
4268 Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); | |
4278 } | 4269 } |
4279 | 4270 |
4280 var makeArray = function(array, results) { | 4271 var makeArray = function(array, results) { |
4281 array = Array.prototype.slice.call( array ); | 4272 array = Array.prototype.slice.call( array, 0 ); |
4282 | 4273 |
4283 if ( results ) { | 4274 if ( results ) { |
4284 results.push.apply( results, array ); | 4275 results.push.apply( results, array ); |
4285 return results; | 4276 return results; |
4286 } | 4277 } |
4288 return array; | 4279 return array; |
4289 }; | 4280 }; |
4290 | 4281 |
4291 // Perform a simple check to determine if the browser is capable of | 4282 // Perform a simple check to determine if the browser is capable of |
4292 // converting a NodeList to an array using builtin methods. | 4283 // converting a NodeList to an array using builtin methods. |
4284 // Also verifies that the returned array holds DOM nodes | |
4285 // (which is not the case in the Blackberry browser) | |
4293 try { | 4286 try { |
4294 Array.prototype.slice.call( document.documentElement.childNodes ); | 4287 Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; |
4295 | 4288 |
4296 // Provide a fallback method if it does not work | 4289 // Provide a fallback method if it does not work |
4297 } catch(e){ | 4290 } catch(e){ |
4298 makeArray = function(array, results) { | 4291 makeArray = function(array, results) { |
4299 var ret = results || []; | 4292 var ret = results || [], i = 0; |
4300 | 4293 |
4301 if ( toString.call(array) === "[object Array]" ) { | 4294 if ( toString.call(array) === "[object Array]" ) { |
4302 Array.prototype.push.apply( ret, array ); | 4295 Array.prototype.push.apply( ret, array ); |
4303 } else { | 4296 } else { |
4304 if ( typeof array.length === "number" ) { | 4297 if ( typeof array.length === "number" ) { |
4305 for ( var i = 0, l = array.length; i < l; i++ ) { | 4298 for ( var l = array.length; i < l; i++ ) { |
4306 ret.push( array[i] ); | 4299 ret.push( array[i] ); |
4307 } | 4300 } |
4308 } else { | 4301 } else { |
4309 for ( var i = 0; array[i]; i++ ) { | 4302 for ( ; array[i]; i++ ) { |
4310 ret.push( array[i] ); | 4303 ret.push( array[i] ); |
4311 } | 4304 } |
4312 } | 4305 } |
4313 } | 4306 } |
4314 | 4307 |
4318 | 4311 |
4319 var sortOrder; | 4312 var sortOrder; |
4320 | 4313 |
4321 if ( document.documentElement.compareDocumentPosition ) { | 4314 if ( document.documentElement.compareDocumentPosition ) { |
4322 sortOrder = function( a, b ) { | 4315 sortOrder = function( a, b ) { |
4316 if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { | |
4317 if ( a == b ) { | |
4318 hasDuplicate = true; | |
4319 } | |
4320 return a.compareDocumentPosition ? -1 : 1; | |
4321 } | |
4322 | |
4323 var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; | 4323 var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; |
4324 if ( ret === 0 ) { | 4324 if ( ret === 0 ) { |
4325 hasDuplicate = true; | 4325 hasDuplicate = true; |
4326 } | 4326 } |
4327 return ret; | 4327 return ret; |
4328 }; | 4328 }; |
4329 } else if ( "sourceIndex" in document.documentElement ) { | 4329 } else if ( "sourceIndex" in document.documentElement ) { |
4330 sortOrder = function( a, b ) { | 4330 sortOrder = function( a, b ) { |
4331 if ( !a.sourceIndex || !b.sourceIndex ) { | |
4332 if ( a == b ) { | |
4333 hasDuplicate = true; | |
4334 } | |
4335 return a.sourceIndex ? -1 : 1; | |
4336 } | |
4337 | |
4331 var ret = a.sourceIndex - b.sourceIndex; | 4338 var ret = a.sourceIndex - b.sourceIndex; |
4332 if ( ret === 0 ) { | 4339 if ( ret === 0 ) { |
4333 hasDuplicate = true; | 4340 hasDuplicate = true; |
4334 } | 4341 } |
4335 return ret; | 4342 return ret; |
4336 }; | 4343 }; |
4337 } else if ( document.createRange ) { | 4344 } else if ( document.createRange ) { |
4338 sortOrder = function( a, b ) { | 4345 sortOrder = function( a, b ) { |
4346 if ( !a.ownerDocument || !b.ownerDocument ) { | |
4347 if ( a == b ) { | |
4348 hasDuplicate = true; | |
4349 } | |
4350 return a.ownerDocument ? -1 : 1; | |
4351 } | |
4352 | |
4339 var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); | 4353 var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); |
4340 aRange.setStart(a, 0); | 4354 aRange.setStart(a, 0); |
4341 aRange.setEnd(a, 0); | 4355 aRange.setEnd(a, 0); |
4342 bRange.setStart(b, 0); | 4356 bRange.setStart(b, 0); |
4343 bRange.setEnd(b, 0); | 4357 bRange.setEnd(b, 0); |
4347 } | 4361 } |
4348 return ret; | 4362 return ret; |
4349 }; | 4363 }; |
4350 } | 4364 } |
4351 | 4365 |
4366 // Utility function for retreiving the text value of an array of DOM nodes | |
4367 Sizzle.getText = function( elems ) { | |
4368 var ret = "", elem; | |
4369 | |
4370 for ( var i = 0; elems[i]; i++ ) { | |
4371 elem = elems[i]; | |
4372 | |
4373 // Get the text from text nodes and CDATA nodes | |
4374 if ( elem.nodeType === 3 || elem.nodeType === 4 ) { | |
4375 ret += elem.nodeValue; | |
4376 | |
4377 // Traverse everything else, except comment nodes | |
4378 } else if ( elem.nodeType !== 8 ) { | |
4379 ret += Sizzle.getText( elem.childNodes ); | |
4380 } | |
4381 } | |
4382 | |
4383 return ret; | |
4384 }; | |
4385 | |
4352 // Check to see if the browser returns elements by name when | 4386 // Check to see if the browser returns elements by name when |
4353 // querying by getElementById (and provide a workaround) | 4387 // querying by getElementById (and provide a workaround) |
4354 (function(){ | 4388 (function(){ |
4355 // We're going to inject a fake input element with a specified name | 4389 // We're going to inject a fake input element with a specified name |
4356 var form = document.createElement("div"), | 4390 var form = document.createElement("div"), |
4357 id = "script" + (new Date).getTime(); | 4391 id = "script" + (new Date()).getTime(); |
4358 form.innerHTML = "<a name='" + id + "'/>"; | 4392 form.innerHTML = "<a name='" + id + "'/>"; |
4359 | 4393 |
4360 // Inject it into the root element, check its status, and remove it quickly | 4394 // Inject it into the root element, check its status, and remove it quickly |
4361 var root = document.documentElement; | 4395 var root = document.documentElement; |
4362 root.insertBefore( form, root.firstChild ); | 4396 root.insertBefore( form, root.firstChild ); |
4363 | 4397 |
4364 // The workaround has to do additional checks after a getElementById | 4398 // The workaround has to do additional checks after a getElementById |
4365 // Which slows things down for other browsers (hence the branching) | 4399 // Which slows things down for other browsers (hence the branching) |
4366 if ( !!document.getElementById( id ) ) { | 4400 if ( document.getElementById( id ) ) { |
4367 Expr.find.ID = function(match, context, isXML){ | 4401 Expr.find.ID = function(match, context, isXML){ |
4368 if ( typeof context.getElementById !== "undefined" && !isXML ) { | 4402 if ( typeof context.getElementById !== "undefined" && !isXML ) { |
4369 var m = context.getElementById(match[1]); | 4403 var m = context.getElementById(match[1]); |
4370 return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; | 4404 return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; |
4371 } | 4405 } |
4376 return elem.nodeType === 1 && node && node.nodeValue === match; | 4410 return elem.nodeType === 1 && node && node.nodeValue === match; |
4377 }; | 4411 }; |
4378 } | 4412 } |
4379 | 4413 |
4380 root.removeChild( form ); | 4414 root.removeChild( form ); |
4415 root = form = null; // release memory in IE | |
4381 })(); | 4416 })(); |
4382 | 4417 |
4383 (function(){ | 4418 (function(){ |
4384 // Check to see if the browser returns only elements | 4419 // Check to see if the browser returns only elements |
4385 // when doing getElementsByTagName("*") | 4420 // when doing getElementsByTagName("*") |
4416 div.firstChild.getAttribute("href") !== "#" ) { | 4451 div.firstChild.getAttribute("href") !== "#" ) { |
4417 Expr.attrHandle.href = function(elem){ | 4452 Expr.attrHandle.href = function(elem){ |
4418 return elem.getAttribute("href", 2); | 4453 return elem.getAttribute("href", 2); |
4419 }; | 4454 }; |
4420 } | 4455 } |
4456 | |
4457 div = null; // release memory in IE | |
4421 })(); | 4458 })(); |
4422 | 4459 |
4423 if ( document.querySelectorAll ) (function(){ | 4460 if ( document.querySelectorAll ) { |
4424 var oldSizzle = Sizzle, div = document.createElement("div"); | 4461 (function(){ |
4425 div.innerHTML = "<p class='TEST'></p>"; | 4462 var oldSizzle = Sizzle, div = document.createElement("div"); |
4426 | 4463 div.innerHTML = "<p class='TEST'></p>"; |
4427 // Safari can't handle uppercase or unicode characters when | 4464 |
4428 // in quirks mode. | 4465 // Safari can't handle uppercase or unicode characters when |
4429 if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { | 4466 // in quirks mode. |
4467 if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { | |
4468 return; | |
4469 } | |
4470 | |
4471 Sizzle = function(query, context, extra, seed){ | |
4472 context = context || document; | |
4473 | |
4474 // Only use querySelectorAll on non-XML documents | |
4475 // (ID selectors don't work in non-HTML documents) | |
4476 if ( !seed && context.nodeType === 9 && !Sizzle.isXML(context) ) { | |
4477 try { | |
4478 return makeArray( context.querySelectorAll(query), extra ); | |
4479 } catch(e){} | |
4480 } | |
4481 | |
4482 return oldSizzle(query, context, extra, seed); | |
4483 }; | |
4484 | |
4485 for ( var prop in oldSizzle ) { | |
4486 Sizzle[ prop ] = oldSizzle[ prop ]; | |
4487 } | |
4488 | |
4489 div = null; // release memory in IE | |
4490 })(); | |
4491 } | |
4492 | |
4493 (function(){ | |
4494 var div = document.createElement("div"); | |
4495 | |
4496 div.innerHTML = "<div class='test e'></div><div class='test'></div>"; | |
4497 | |
4498 // Opera can't find a second classname (in 9.6) | |
4499 // Also, make sure that getElementsByClassName actually exists | |
4500 if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { | |
4501 return; | |
4502 } | |
4503 | |
4504 // Safari caches class attributes, doesn't catch changes (in 3.2) | |
4505 div.lastChild.className = "e"; | |
4506 | |
4507 if ( div.getElementsByClassName("e").length === 1 ) { | |
4430 return; | 4508 return; |
4431 } | 4509 } |
4432 | 4510 |
4433 Sizzle = function(query, context, extra, seed){ | |
4434 context = context || document; | |
4435 | |
4436 // Only use querySelectorAll on non-XML documents | |
4437 // (ID selectors don't work in non-HTML documents) | |
4438 if ( !seed && context.nodeType === 9 && !isXML(context) ) { | |
4439 try { | |
4440 return makeArray( context.querySelectorAll(query), extra ); | |
4441 } catch(e){} | |
4442 } | |
4443 | |
4444 return oldSizzle(query, context, extra, seed); | |
4445 }; | |
4446 | |
4447 for ( var prop in oldSizzle ) { | |
4448 Sizzle[ prop ] = oldSizzle[ prop ]; | |
4449 } | |
4450 })(); | |
4451 | |
4452 if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){ | |
4453 var div = document.createElement("div"); | |
4454 div.innerHTML = "<div class='test e'></div><div class='test'></div>"; | |
4455 | |
4456 // Opera can't find a second classname (in 9.6) | |
4457 if ( div.getElementsByClassName("e").length === 0 ) | |
4458 return; | |
4459 | |
4460 // Safari caches class attributes, doesn't catch changes (in 3.2) | |
4461 div.lastChild.className = "e"; | |
4462 | |
4463 if ( div.getElementsByClassName("e").length === 1 ) | |
4464 return; | |
4465 | |
4466 Expr.order.splice(1, 0, "CLASS"); | 4511 Expr.order.splice(1, 0, "CLASS"); |
4467 Expr.find.CLASS = function(match, context, isXML) { | 4512 Expr.find.CLASS = function(match, context, isXML) { |
4468 if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { | 4513 if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { |
4469 return context.getElementsByClassName(match[1]); | 4514 return context.getElementsByClassName(match[1]); |
4470 } | 4515 } |
4471 }; | 4516 }; |
4517 | |
4518 div = null; // release memory in IE | |
4472 })(); | 4519 })(); |
4473 | 4520 |
4474 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { | 4521 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { |
4475 var sibDir = dir == "previousSibling" && !isXML; | |
4476 for ( var i = 0, l = checkSet.length; i < l; i++ ) { | 4522 for ( var i = 0, l = checkSet.length; i < l; i++ ) { |
4477 var elem = checkSet[i]; | 4523 var elem = checkSet[i]; |
4478 if ( elem ) { | 4524 if ( elem ) { |
4479 if ( sibDir && elem.nodeType === 1 ){ | |
4480 elem.sizcache = doneName; | |
4481 elem.sizset = i; | |
4482 } | |
4483 elem = elem[dir]; | 4525 elem = elem[dir]; |
4484 var match = false; | 4526 var match = false; |
4485 | 4527 |
4486 while ( elem ) { | 4528 while ( elem ) { |
4487 if ( elem.sizcache === doneName ) { | 4529 if ( elem.sizcache === doneName ) { |
4492 if ( elem.nodeType === 1 && !isXML ){ | 4534 if ( elem.nodeType === 1 && !isXML ){ |
4493 elem.sizcache = doneName; | 4535 elem.sizcache = doneName; |
4494 elem.sizset = i; | 4536 elem.sizset = i; |
4495 } | 4537 } |
4496 | 4538 |
4497 if ( elem.nodeName === cur ) { | 4539 if ( elem.nodeName.toLowerCase() === cur ) { |
4498 match = elem; | 4540 match = elem; |
4499 break; | 4541 break; |
4500 } | 4542 } |
4501 | 4543 |
4502 elem = elem[dir]; | 4544 elem = elem[dir]; |
4506 } | 4548 } |
4507 } | 4549 } |
4508 } | 4550 } |
4509 | 4551 |
4510 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { | 4552 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { |
4511 var sibDir = dir == "previousSibling" && !isXML; | |
4512 for ( var i = 0, l = checkSet.length; i < l; i++ ) { | 4553 for ( var i = 0, l = checkSet.length; i < l; i++ ) { |
4513 var elem = checkSet[i]; | 4554 var elem = checkSet[i]; |
4514 if ( elem ) { | 4555 if ( elem ) { |
4515 if ( sibDir && elem.nodeType === 1 ) { | |
4516 elem.sizcache = doneName; | |
4517 elem.sizset = i; | |
4518 } | |
4519 elem = elem[dir]; | 4556 elem = elem[dir]; |
4520 var match = false; | 4557 var match = false; |
4521 | 4558 |
4522 while ( elem ) { | 4559 while ( elem ) { |
4523 if ( elem.sizcache === doneName ) { | 4560 if ( elem.sizcache === doneName ) { |
4548 checkSet[i] = match; | 4585 checkSet[i] = match; |
4549 } | 4586 } |
4550 } | 4587 } |
4551 } | 4588 } |
4552 | 4589 |
4553 var contains = document.compareDocumentPosition ? function(a, b){ | 4590 Sizzle.contains = document.compareDocumentPosition ? function(a, b){ |
4554 return a.compareDocumentPosition(b) & 16; | 4591 return !!(a.compareDocumentPosition(b) & 16); |
4555 } : function(a, b){ | 4592 } : function(a, b){ |
4556 return a !== b && (a.contains ? a.contains(b) : true); | 4593 return a !== b && (a.contains ? a.contains(b) : true); |
4557 }; | 4594 }; |
4558 | 4595 |
4559 var isXML = function(elem){ | 4596 Sizzle.isXML = function(elem){ |
4560 return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || | 4597 // documentElement is verified for cases where it doesn't yet exist |
4561 !!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML"; | 4598 // (such as loading iframes in IE - #4833) |
4599 var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; | |
4600 return documentElement ? documentElement.nodeName !== "HTML" : false; | |
4562 }; | 4601 }; |
4563 | 4602 |
4564 var posProcess = function(selector, context){ | 4603 var posProcess = function(selector, context){ |
4565 var tmpSet = [], later = "", match, | 4604 var tmpSet = [], later = "", match, |
4566 root = context.nodeType ? [context] : context; | 4605 root = context.nodeType ? [context] : context; |
5104 // Dispatch set content event | 5143 // Dispatch set content event |
5105 t.onSetContent.dispatch(t, s); | 5144 t.onSetContent.dispatch(t, s); |
5106 }, | 5145 }, |
5107 | 5146 |
5108 getStart : function() { | 5147 getStart : function() { |
5109 var t = this, r = t.getRng(), e; | 5148 var rng = this.getRng(), startElement, parentElement, checkRng, node; |
5110 | 5149 |
5111 if (r.duplicate || r.item) { | 5150 if (rng.duplicate || rng.item) { |
5112 if (r.item) | 5151 // Control selection, return first item |
5113 return r.item(0); | 5152 if (rng.item) |
5114 | 5153 return rng.item(0); |
5115 r = r.duplicate(); | 5154 |
5116 r.collapse(1); | 5155 // Get start element |
5117 e = r.parentElement(); | 5156 checkRng = rng.duplicate(); |
5118 | 5157 checkRng.collapse(1); |
5119 if (e && e.nodeName == 'BODY') | 5158 startElement = checkRng.parentElement(); |
5120 return e.firstChild || e; | 5159 |
5121 | 5160 // Check if range parent is inside the start element, then return the inner parent element |
5122 return e; | 5161 // This will fix issues when a single element is selected, IE would otherwise return the wrong start element |
5162 parentElement = node = rng.parentElement(); | |
5163 while (node = node.parentNode) { | |
5164 if (node == startElement) { | |
5165 startElement = parentElement; | |
5166 break; | |
5167 } | |
5168 } | |
5169 | |
5170 // If start element is body element try to move to the first child if it exists | |
5171 if (startElement && startElement.nodeName == 'BODY') | |
5172 return startElement.firstChild || startElement; | |
5173 | |
5174 return startElement; | |
5123 } else { | 5175 } else { |
5124 e = r.startContainer; | 5176 startElement = rng.startContainer; |
5125 | 5177 |
5126 if (e.nodeType == 1 && e.hasChildNodes()) | 5178 if (startElement.nodeType == 1 && startElement.hasChildNodes()) |
5127 e = e.childNodes[Math.min(e.childNodes.length - 1, r.startOffset)]; | 5179 startElement = startElement.childNodes[Math.min(startElement.childNodes.length - 1, rng.startOffset)]; |
5128 | 5180 |
5129 if (e && e.nodeType == 3) | 5181 if (startElement && startElement.nodeType == 3) |
5130 return e.parentNode; | 5182 return startElement.parentNode; |
5131 | 5183 |
5132 return e; | 5184 return startElement; |
5133 } | 5185 } |
5134 }, | 5186 }, |
5135 | 5187 |
5136 getEnd : function() { | 5188 getEnd : function() { |
5137 var t = this, r = t.getRng(), e, eo; | 5189 var t = this, r = t.getRng(), e, eo; |
5285 if (bookmark.start) { | 5337 if (bookmark.start) { |
5286 rng = dom.createRng(); | 5338 rng = dom.createRng(); |
5287 root = dom.getRoot(); | 5339 root = dom.getRoot(); |
5288 | 5340 |
5289 function setEndPoint(start) { | 5341 function setEndPoint(start) { |
5290 var point = bookmark[start ? 'start' : 'end'], i, node, offset; | 5342 var point = bookmark[start ? 'start' : 'end'], i, node, offset, children; |
5291 | 5343 |
5292 if (point) { | 5344 if (point) { |
5293 // Find container node | 5345 // Find container node |
5294 for (node = root, i = point.length - 1; i >= 1; i--) | 5346 for (node = root, i = point.length - 1; i >= 1; i--) { |
5295 node = node.childNodes[point[i]]; | 5347 children = node.childNodes; |
5348 | |
5349 if (children.length) | |
5350 node = children[point[i]]; | |
5351 } | |
5296 | 5352 |
5297 // Set offset within container node | 5353 // Set offset within container node |
5298 if (start) | 5354 if (start) |
5299 rng.setStart(node, point[0]); | 5355 rng.setStart(node, point[0]); |
5300 else | 5356 else |
5315 | 5371 |
5316 if (suffix == 'start') { | 5372 if (suffix == 'start') { |
5317 if (!keep) { | 5373 if (!keep) { |
5318 idx = dom.nodeIndex(marker); | 5374 idx = dom.nodeIndex(marker); |
5319 } else { | 5375 } else { |
5320 node = marker; | 5376 node = marker.firstChild; |
5321 idx = 1; | 5377 idx = 1; |
5322 } | 5378 } |
5323 | 5379 |
5324 startContainer = endContainer = node; | 5380 startContainer = endContainer = node; |
5325 startOffset = endOffset = idx; | 5381 startOffset = endOffset = idx; |
5326 } else { | 5382 } else { |
5327 if (!keep) { | 5383 if (!keep) { |
5328 idx = dom.nodeIndex(marker); | 5384 idx = dom.nodeIndex(marker); |
5329 } else { | 5385 } else { |
5330 node = marker; | 5386 node = marker.firstChild; |
5331 idx = 1; | 5387 idx = 1; |
5332 } | 5388 } |
5333 | 5389 |
5334 endContainer = node; | 5390 endContainer = node; |
5335 endOffset = idx; | 5391 endOffset = idx; |
5366 } | 5422 } |
5367 } | 5423 } |
5368 } | 5424 } |
5369 }; | 5425 }; |
5370 | 5426 |
5427 function addBogus(node) { | |
5428 // Adds a bogus BR element for empty block elements | |
5429 // on non IE browsers just to have a place to put the caret | |
5430 if (!isIE && dom.isBlock(node) && !node.innerHTML) | |
5431 node.innerHTML = '<br _mce_bogus="1" />'; | |
5432 | |
5433 return node; | |
5434 }; | |
5435 | |
5371 // Restore start/end points | 5436 // Restore start/end points |
5372 restoreEndPoint('start'); | 5437 restoreEndPoint('start'); |
5373 restoreEndPoint('end'); | 5438 restoreEndPoint('end'); |
5374 | 5439 |
5375 rng = dom.createRng(); | 5440 if (startContainer) { |
5376 rng.setStart(startContainer, startOffset); | 5441 rng = dom.createRng(); |
5377 rng.setEnd(endContainer, endOffset); | 5442 rng.setStart(addBogus(startContainer), startOffset); |
5378 t.setRng(rng); | 5443 rng.setEnd(addBogus(endContainer), endOffset); |
5444 t.setRng(rng); | |
5445 } | |
5379 } else if (bookmark.name) { | 5446 } else if (bookmark.name) { |
5380 t.select(dom.select(bookmark.name)[bookmark.index]); | 5447 t.select(dom.select(bookmark.name)[bookmark.index]); |
5381 } else if (bookmark.rng) | 5448 } else if (bookmark.rng) |
5382 t.setRng(bookmark.rng); | 5449 t.setRng(bookmark.rng); |
5383 } | 5450 } |
6339 | 6406 |
6340 o.content = h; | 6407 o.content = h; |
6341 }, | 6408 }, |
6342 | 6409 |
6343 _serializeNode : function(n, inner) { | 6410 _serializeNode : function(n, inner) { |
6344 var t = this, s = t.settings, w = t.writer, hc, el, cn, i, l, a, at, no, v, nn, ru, ar, iv, closed, keep, type; | 6411 var t = this, s = t.settings, w = t.writer, hc, el, cn, i, l, a, at, no, v, nn, ru, ar, iv, closed, keep, type, scopeName; |
6345 | 6412 |
6346 if (!s.node_filter || s.node_filter(n)) { | 6413 if (!s.node_filter || s.node_filter(n)) { |
6347 switch (n.nodeType) { | 6414 switch (n.nodeType) { |
6348 case 1: // Element | 6415 case 1: // Element |
6349 if (n.hasAttribute ? n.hasAttribute('_mce_bogus') : n.getAttribute('_mce_bogus')) | 6416 if (n.hasAttribute ? n.hasAttribute('_mce_bogus') : n.getAttribute('_mce_bogus')) |
6363 keep = 1; | 6430 keep = 1; |
6364 } | 6431 } |
6365 | 6432 |
6366 // Add correct prefix on IE | 6433 // Add correct prefix on IE |
6367 if (isIE) { | 6434 if (isIE) { |
6368 if (n.scopeName !== 'HTML' && n.scopeName !== 'html') | 6435 scopeName = n.scopeName; |
6369 nn = n.scopeName + ':' + nn; | 6436 if (scopeName && scopeName !== 'HTML' && scopeName !== 'html') |
6437 nn = scopeName + ':' + nn; | |
6370 } | 6438 } |
6371 | 6439 |
6372 // Remove mce prefix on IE needed for the abbr element | 6440 // Remove mce prefix on IE needed for the abbr element |
6373 if (nn.indexOf('mce:') === 0) | 6441 if (nn.indexOf('mce:') === 0) |
6374 nn = nn.substring(4); | 6442 nn = nn.substring(4); |
8087 | 8155 |
8088 postRender : function() { | 8156 postRender : function() { |
8089 var t = this, cp = t.classPrefix; | 8157 var t = this, cp = t.classPrefix; |
8090 | 8158 |
8091 Event.add(t.id, 'click', t.showMenu, t); | 8159 Event.add(t.id, 'click', t.showMenu, t); |
8092 Event.add(t.id + '_text', 'focus', function(e) { | 8160 Event.add(t.id + '_text', 'focus', function() { |
8093 if (!t._focused) { | 8161 if (!t._focused) { |
8094 t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) { | 8162 t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) { |
8095 var idx = -1, v, kc = e.keyCode; | 8163 var idx = -1, v, kc = e.keyCode; |
8096 | 8164 |
8097 // Find current index | 8165 // Find current index |
8665 | 8733 |
8666 (function(tinymce) { | 8734 (function(tinymce) { |
8667 var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each; | 8735 var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each; |
8668 | 8736 |
8669 tinymce.create('tinymce.AddOnManager', { | 8737 tinymce.create('tinymce.AddOnManager', { |
8670 items : [], | 8738 AddOnManager : function() { |
8671 urls : {}, | 8739 var self = this; |
8672 lookup : {}, | 8740 |
8673 | 8741 self.items = []; |
8674 onAdd : new Dispatcher(this), | 8742 self.urls = {}; |
8743 self.lookup = {}; | |
8744 self.onAdd = new Dispatcher(self); | |
8745 }, | |
8675 | 8746 |
8676 get : function(n) { | 8747 get : function(n) { |
8677 return this.lookup[n]; | 8748 return this.lookup[n]; |
8678 }, | 8749 }, |
8679 | 8750 |
8700 | 8771 |
8701 if (u.indexOf('/') != 0 && u.indexOf('://') == -1) | 8772 if (u.indexOf('/') != 0 && u.indexOf('://') == -1) |
8702 u = tinymce.baseURL + '/' + u; | 8773 u = tinymce.baseURL + '/' + u; |
8703 | 8774 |
8704 t.urls[n] = u.substring(0, u.lastIndexOf('/')); | 8775 t.urls[n] = u.substring(0, u.lastIndexOf('/')); |
8705 tinymce.ScriptLoader.add(u, cb, s); | 8776 |
8777 if (!t.lookup[n]) | |
8778 tinymce.ScriptLoader.add(u, cb, s); | |
8706 } | 8779 } |
8707 }); | 8780 }); |
8708 | 8781 |
8709 // Create plugin and theme managers | 8782 // Create plugin and theme managers |
8710 tinymce.PluginManager = new tinymce.AddOnManager(); | 8783 tinymce.PluginManager = new tinymce.AddOnManager(); |
10634 }); | 10707 }); |
10635 } | 10708 } |
10636 | 10709 |
10637 // Add node change handlers | 10710 // Add node change handlers |
10638 t.onMouseUp.add(t.nodeChanged); | 10711 t.onMouseUp.add(t.nodeChanged); |
10639 t.onClick.add(t.nodeChanged); | 10712 //t.onClick.add(t.nodeChanged); |
10640 t.onKeyUp.add(function(ed, e) { | 10713 t.onKeyUp.add(function(ed, e) { |
10641 var c = e.keyCode; | 10714 var c = e.keyCode; |
10642 | 10715 |
10643 if ((c >= 33 && c <= 36) || (c >= 37 && c <= 40) || c == 13 || c == 45 || c == 46 || c == 8 || (tinymce.isMac && (c == 91 || c == 93)) || e.ctrlKey) | 10716 if ((c >= 33 && c <= 36) || (c >= 37 && c <= 40) || c == 13 || c == 45 || c == 46 || c == 8 || (tinymce.isMac && (c == 91 || c == 93)) || e.ctrlKey) |
10644 t.nodeChanged(); | 10717 t.nodeChanged(); |
10808 if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45 || e.ctrlKey) | 10881 if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45 || e.ctrlKey) |
10809 addUndo(); | 10882 addUndo(); |
10810 }); | 10883 }); |
10811 | 10884 |
10812 t.onKeyDown.add(function(ed, e) { | 10885 t.onKeyDown.add(function(ed, e) { |
10886 var rng, parent, bookmark; | |
10887 | |
10888 // IE has a really odd bug where the DOM might include an node that doesn't have | |
10889 // a proper structure. If you try to access nodeValue it would throw an illegal value exception. | |
10890 // This seems to only happen when you delete contents and it seems to be avoidable if you refresh the element | |
10891 // after you delete contents from it. See: #3008923 | |
10892 if (isIE && e.keyCode == 46) { | |
10893 rng = t.selection.getRng(); | |
10894 | |
10895 if (rng.parentElement) { | |
10896 parent = rng.parentElement(); | |
10897 | |
10898 // Select next word when ctrl key is used in combo with delete | |
10899 if (e.ctrlKey) { | |
10900 rng.moveEnd('word', 1); | |
10901 rng.select(); | |
10902 } | |
10903 | |
10904 // Delete contents | |
10905 t.selection.getSel().clear(); | |
10906 | |
10907 // Check if we are within the same parent | |
10908 if (rng.parentElement() == parent) { | |
10909 bookmark = t.selection.getBookmark(); | |
10910 | |
10911 try { | |
10912 // Update the HTML and hopefully it will remove the artifacts | |
10913 parent.innerHTML = parent.innerHTML; | |
10914 } catch (ex) { | |
10915 // And since it's IE it can sometimes produce an unknown runtime error | |
10916 } | |
10917 | |
10918 // Restore the caret position | |
10919 t.selection.moveToBookmark(bookmark); | |
10920 } | |
10921 | |
10922 // Block the default delete behavior since it might be broken | |
10923 e.preventDefault(); | |
10924 return; | |
10925 } | |
10926 } | |
10927 | |
10813 // Is caracter positon keys | 10928 // Is caracter positon keys |
10814 if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) { | 10929 if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) { |
10815 if (t.undoManager.typing) | 10930 if (t.undoManager.typing) |
10816 addUndo(); | 10931 addUndo(); |
10817 | 10932 |
11095 mceBlockQuote : function(command) { | 11210 mceBlockQuote : function(command) { |
11096 toggleFormat('blockquote'); | 11211 toggleFormat('blockquote'); |
11097 }, | 11212 }, |
11098 | 11213 |
11099 FormatBlock : function(command, ui, value) { | 11214 FormatBlock : function(command, ui, value) { |
11100 return toggleFormat(value); | 11215 return toggleFormat(value || 'p'); |
11101 }, | 11216 }, |
11102 | 11217 |
11103 mceCleanup : function() { | 11218 mceCleanup : function() { |
11104 storeSelection(); | 11219 var bookmark = selection.getBookmark(); |
11220 | |
11105 editor.setContent(editor.getContent({cleanup : TRUE}), {cleanup : TRUE}); | 11221 editor.setContent(editor.getContent({cleanup : TRUE}), {cleanup : TRUE}); |
11106 restoreSelection(); | 11222 |
11223 selection.moveToBookmark(bookmark); | |
11107 }, | 11224 }, |
11108 | 11225 |
11109 mceRemoveNode : function(command, ui, value) { | 11226 mceRemoveNode : function(command, ui, value) { |
11110 var node = value || selection.getNode(); | 11227 var node = value || selection.getNode(); |
11111 | 11228 |
11136 selection.setContent(value); | 11253 selection.setContent(value); |
11137 }, | 11254 }, |
11138 | 11255 |
11139 mceInsertRawHTML : function(command, ui, value) { | 11256 mceInsertRawHTML : function(command, ui, value) { |
11140 selection.setContent('tiny_mce_marker'); | 11257 selection.setContent('tiny_mce_marker'); |
11141 editor.setContent(editor.getContent().replace(/tiny_mce_marker/g, value)); | 11258 editor.setContent(editor.getContent().replace(/tiny_mce_marker/g, function() { return value })); |
11142 }, | 11259 }, |
11143 | 11260 |
11144 mceSetContent : function(command, ui, value) { | 11261 mceSetContent : function(command, ui, value) { |
11145 editor.setContent(value); | 11262 editor.setContent(value); |
11146 }, | 11263 }, |
11218 editor.dom.remove(link, TRUE); | 11335 editor.dom.remove(link, TRUE); |
11219 } | 11336 } |
11220 }, | 11337 }, |
11221 | 11338 |
11222 selectAll : function() { | 11339 selectAll : function() { |
11223 var root = dom.getRoot(); | 11340 var root = dom.getRoot(), rng = dom.createRng(); |
11224 var rng = dom.createRng(); | 11341 |
11225 rng.setStart(root, 0); | 11342 rng.setStart(root, 0); |
11226 rng.setEnd(root, root.childNodes.length); | 11343 rng.setEnd(root, root.childNodes.length); |
11344 | |
11227 editor.selection.setRng(rng); | 11345 editor.selection.setRng(rng); |
11228 } | 11346 } |
11229 }); | 11347 }); |
11230 | 11348 |
11231 // Add queryCommandState overrides | 11349 // Add queryCommandState overrides |
11414 each = tinymce.each, | 11532 each = tinymce.each, |
11415 extend = tinymce.extend, | 11533 extend = tinymce.extend, |
11416 TRUE = true, | 11534 TRUE = true, |
11417 FALSE = false; | 11535 FALSE = false; |
11418 | 11536 |
11537 function cloneFormats(node) { | |
11538 var clone, temp, inner; | |
11539 | |
11540 do { | |
11541 if (/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(node.nodeName)) { | |
11542 if (clone) { | |
11543 temp = node.cloneNode(false); | |
11544 temp.appendChild(clone); | |
11545 clone = temp; | |
11546 } else { | |
11547 clone = inner = node.cloneNode(false); | |
11548 } | |
11549 | |
11550 clone.removeAttribute('id'); | |
11551 } | |
11552 } while (node = node.parentNode); | |
11553 | |
11554 if (clone) | |
11555 return {wrapper : clone, inner : inner}; | |
11556 }; | |
11557 | |
11419 // Checks if the selection/caret is at the end of the specified block element | 11558 // Checks if the selection/caret is at the end of the specified block element |
11420 function isAtEnd(rng, par) { | 11559 function isAtEnd(rng, par) { |
11421 var rng2 = par.ownerDocument.createRange(); | 11560 var rng2 = par.ownerDocument.createRange(); |
11422 | 11561 |
11423 rng2.setStart(rng.endContainer, rng.endOffset); | 11562 rng2.setStart(rng.endContainer, rng.endOffset); |
11522 } | 11661 } |
11523 }); | 11662 }); |
11524 } | 11663 } |
11525 } | 11664 } |
11526 | 11665 |
11527 if (!isIE && s.force_p_newlines) { | 11666 if (s.force_p_newlines) { |
11528 ed.onKeyPress.add(function(ed, e) { | 11667 if (!isIE) { |
11529 if (e.keyCode == 13 && !e.shiftKey && !t.insertPara(e)) | 11668 ed.onKeyPress.add(function(ed, e) { |
11530 Event.cancel(e); | 11669 if (e.keyCode == 13 && !e.shiftKey && !t.insertPara(e)) |
11531 }); | 11670 Event.cancel(e); |
11671 }); | |
11672 } else { | |
11673 // Ungly hack to for IE to preserve the formatting when you press | |
11674 // enter at the end of a block element with formatted contents | |
11675 // This logic overrides the browsers default logic with | |
11676 // custom logic that enables us to control the output | |
11677 tinymce.addUnload(function() { | |
11678 t._previousFormats = 0; // Fix IE leak | |
11679 }); | |
11680 | |
11681 ed.onKeyPress.add(function(ed, e) { | |
11682 t._previousFormats = 0; | |
11683 | |
11684 // Clone the current formats, this will later be applied to the new block contents | |
11685 if (e.keyCode == 13 && !e.shiftKey && ed.selection.isCollapsed() && s.keep_styles) | |
11686 t._previousFormats = cloneFormats(ed.selection.getStart()); | |
11687 }); | |
11688 | |
11689 ed.onKeyUp.add(function(ed, e) { | |
11690 // Let IE break the element and the wrap the new caret location in the previous formats | |
11691 if (e.keyCode == 13 && !e.shiftKey) { | |
11692 var parent = ed.selection.getStart(), fmt = t._previousFormats; | |
11693 | |
11694 // Parent is an empty block | |
11695 if (!parent.hasChildNodes() && fmt) { | |
11696 parent = dom.getParent(parent, dom.isBlock); | |
11697 | |
11698 if (parent && parent.nodeName != 'LI') { | |
11699 parent.innerHTML = ''; | |
11700 | |
11701 if (t._previousFormats) { | |
11702 parent.appendChild(fmt.wrapper); | |
11703 fmt.inner.innerHTML = '\uFEFF'; | |
11704 } else | |
11705 parent.innerHTML = '\uFEFF'; | |
11706 | |
11707 selection.select(parent, 1); | |
11708 ed.getDoc().execCommand('Delete', false, null); | |
11709 t._previousFormats = 0; | |
11710 } | |
11711 } | |
11712 } | |
11713 }); | |
11714 } | |
11532 | 11715 |
11533 if (isGecko) { | 11716 if (isGecko) { |
11534 ed.onKeyDown.add(function(ed, e) { | 11717 ed.onKeyDown.add(function(ed, e) { |
11535 if ((e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) | 11718 if ((e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) |
11536 t.backspaceDelete(e, e.keyCode == 8); | 11719 t.backspaceDelete(e, e.keyCode == 8); |
12028 | 12211 |
12029 return FALSE; | 12212 return FALSE; |
12030 }, | 12213 }, |
12031 | 12214 |
12032 backspaceDelete : function(e, bs) { | 12215 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; | 12216 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; |
12217 | |
12218 // Delete when caret is behind a element doesn't work correctly on Gecko see #3011651 | |
12219 if (!bs && r.collapsed && sc.nodeType == 1 && r.startOffset == sc.childNodes.length) { | |
12220 walker = new tinymce.dom.TreeWalker(sc.lastChild, sc); | |
12221 | |
12222 // Walk the dom backwards until we find a text node | |
12223 for (n = sc.lastChild; n; n = walker.prev()) { | |
12224 if (n.nodeType == 3) { | |
12225 r.setStart(n, n.nodeValue.length); | |
12226 r.collapse(true); | |
12227 se.setRng(r); | |
12228 return; | |
12229 } | |
12230 } | |
12231 } | |
12034 | 12232 |
12035 // The caret sometimes gets stuck in Gecko if you delete empty paragraphs | 12233 // The caret sometimes gets stuck in Gecko if you delete empty paragraphs |
12036 // This workaround removes the element by hand and moves the caret to the previous element | 12234 // This workaround removes the element by hand and moves the caret to the previous element |
12037 if (sc && ed.dom.isBlock(sc) && !/^(TD|TH)$/.test(sc.nodeName) && bs) { | 12235 if (sc && ed.dom.isBlock(sc) && !/^(TD|TH)$/.test(sc.nodeName) && bs) { |
12038 if (sc.childNodes.length == 0 || (sc.childNodes.length == 1 && sc.firstChild.nodeName == 'BR')) { | 12236 if (sc.childNodes.length == 0 || (sc.childNodes.length == 1 && sc.firstChild.nodeName == 'BR')) { |
12059 | 12257 |
12060 return Event.cancel(e); | 12258 return Event.cancel(e); |
12061 } | 12259 } |
12062 } | 12260 } |
12063 } | 12261 } |
12064 | |
12065 // Gecko generates BR elements here and there, we don't like those so lets remove them | |
12066 function handler(e) { | |
12067 var pr; | |
12068 | |
12069 e = e.target; | |
12070 | |
12071 // A new BR was created in a block element, remove it | |
12072 if (e && e.parentNode && e.nodeName == 'BR' && (n = t.getParentBlock(e))) { | |
12073 pr = e.previousSibling; | |
12074 | |
12075 Event.remove(b, 'DOMNodeInserted', handler); | |
12076 | |
12077 // Is there whitespace at the end of the node before then we might need the pesky BR | |
12078 // to place the caret at a correct location see bug: #2013943 | |
12079 if (pr && pr.nodeType == 3 && /\s+$/.test(pr.nodeValue)) | |
12080 return; | |
12081 | |
12082 // Only remove BR elements that got inserted in the middle of the text | |
12083 if (e.previousSibling || e.nextSibling) | |
12084 ed.dom.remove(e); | |
12085 } | |
12086 }; | |
12087 | |
12088 // Listen for new nodes | |
12089 Event._add(b, 'DOMNodeInserted', handler); | |
12090 | |
12091 // Remove listener | |
12092 window.setTimeout(function() { | |
12093 Event._remove(b, 'DOMNodeInserted', handler); | |
12094 }, 1); | |
12095 } | 12262 } |
12096 }); | 12263 }); |
12097 })(tinymce); | 12264 })(tinymce); |
12098 | 12265 |
12099 (function(tinymce) { | 12266 (function(tinymce) { |
12706 walker, node; | 12873 walker, node; |
12707 | 12874 |
12708 // Move startContainer/startOffset in to a suitable node | 12875 // Move startContainer/startOffset in to a suitable node |
12709 if (container.nodeType == 1 || container.nodeValue === "") { | 12876 if (container.nodeType == 1 || container.nodeValue === "") { |
12710 container = container.nodeType == 1 ? container.childNodes[offset] : container; | 12877 container = container.nodeType == 1 ? container.childNodes[offset] : container; |
12711 walker = new TreeWalker(container, container.parentNode); | 12878 |
12712 for (node = walker.current(); node; node = walker.next()) { | 12879 // Might fail if the offset is behind the last element in it's container |
12713 if (node.nodeType == 3 && !isBlock(node.parentNode) && !isWhiteSpaceNode(node)) { | 12880 if (container) { |
12714 rng.setStart(node, 0); | 12881 walker = new TreeWalker(container, container.parentNode); |
12715 break; | 12882 for (node = walker.current(); node; node = walker.next()) { |
12883 if (node.nodeType == 3 && !isWhiteSpaceNode(node)) { | |
12884 rng.setStart(node, 0); | |
12885 break; | |
12886 } | |
12716 } | 12887 } |
12717 } | 12888 } |
12718 } | 12889 } |
12719 | 12890 |
12720 return rng; | 12891 return rng; |
12916 rng = dom.createRng(); | 13087 rng = dom.createRng(); |
12917 | 13088 |
12918 rng.setStartBefore(node); | 13089 rng.setStartBefore(node); |
12919 rng.setEndAfter(node); | 13090 rng.setEndAfter(node); |
12920 | 13091 |
12921 applyRngStyle(rng); | 13092 applyRngStyle(expandRng(rng, formatList)); |
12922 } else { | 13093 } else { |
12923 if (!selection.isCollapsed() || !format.inline) { | 13094 if (!selection.isCollapsed() || !format.inline) { |
12924 // Apply formatting to selection | 13095 // Apply formatting to selection |
12925 bookmark = selection.getBookmark(); | 13096 bookmark = selection.getBookmark(); |
12926 applyRngStyle(expandRng(selection.getRng(TRUE), formatList)); | 13097 applyRngStyle(expandRng(selection.getRng(TRUE), formatList)); |
12934 } | 13105 } |
12935 }; | 13106 }; |
12936 | 13107 |
12937 function remove(name, vars, node) { | 13108 function remove(name, vars, node) { |
12938 var formatList = get(name), format = formatList[0], bookmark, i, rng; | 13109 var formatList = get(name), format = formatList[0], bookmark, i, rng; |
13110 | |
13111 function moveStart(rng) { | |
13112 var container = rng.startContainer, | |
13113 offset = rng.startOffset, | |
13114 walker, node, nodes, tmpNode; | |
13115 | |
13116 // Convert text node into index if possible | |
13117 if (container.nodeType == 3 && offset >= container.nodeValue.length - 1) { | |
13118 container = container.parentNode; | |
13119 offset = nodeIndex(container) + 1; | |
13120 } | |
13121 | |
13122 // Move startContainer/startOffset in to a suitable node | |
13123 if (container.nodeType == 1) { | |
13124 nodes = container.childNodes; | |
13125 container = nodes[Math.min(offset, nodes.length - 1)]; | |
13126 walker = new TreeWalker(container); | |
13127 | |
13128 // If offset is at end of the parent node walk to the next one | |
13129 if (offset > nodes.length - 1) | |
13130 walker.next(); | |
13131 | |
13132 for (node = walker.current(); node; node = walker.next()) { | |
13133 if (node.nodeType == 3 && !isWhiteSpaceNode(node)) { | |
13134 // IE has a "neat" feature where it moves the start node into the closest element | |
13135 // we can avoid this by inserting an element before it and then remove it after we set the selection | |
13136 tmpNode = dom.create('a', null, INVISIBLE_CHAR); | |
13137 node.parentNode.insertBefore(tmpNode, node); | |
13138 | |
13139 // Set selection and remove tmpNode | |
13140 rng.setStart(node, 0); | |
13141 selection.setRng(rng); | |
13142 dom.remove(tmpNode); | |
13143 | |
13144 return; | |
13145 } | |
13146 } | |
13147 } | |
13148 }; | |
12939 | 13149 |
12940 // Merges the styles for each node | 13150 // Merges the styles for each node |
12941 function process(node) { | 13151 function process(node) { |
12942 var children, i, l; | 13152 var children, i, l; |
12943 | 13153 |
13088 | 13298 |
13089 if (!selection.isCollapsed() || !format.inline) { | 13299 if (!selection.isCollapsed() || !format.inline) { |
13090 bookmark = selection.getBookmark(); | 13300 bookmark = selection.getBookmark(); |
13091 removeRngStyle(selection.getRng(TRUE)); | 13301 removeRngStyle(selection.getRng(TRUE)); |
13092 selection.moveToBookmark(bookmark); | 13302 selection.moveToBookmark(bookmark); |
13303 | |
13304 // Check if start element still has formatting then we are at: "<b>text|</b>text" and need to move the start into the next text node | |
13305 if (match(name, vars, selection.getStart())) { | |
13306 moveStart(selection.getRng(true)); | |
13307 } | |
13308 | |
13093 ed.nodeChanged(); | 13309 ed.nodeChanged(); |
13094 } else | 13310 } else |
13095 performCaretAction('remove', name, vars); | 13311 performCaretAction('remove', name, vars); |
13096 }; | 13312 }; |
13097 | 13313 |
13342 | 13558 |
13343 return value; | 13559 return value; |
13344 }; | 13560 }; |
13345 | 13561 |
13346 function isWhiteSpaceNode(node) { | 13562 function isWhiteSpaceNode(node) { |
13347 return node && node.nodeType === 3 && /^\s*$/.test(node.nodeValue); | 13563 return node && node.nodeType === 3 && /^([\s\r\n]+|)$/.test(node.nodeValue); |
13348 }; | 13564 }; |
13349 | 13565 |
13350 function wrap(node, name, attrs) { | 13566 function wrap(node, name, attrs) { |
13351 var wrapper = dom.create(name, attrs); | 13567 var wrapper = dom.create(name, attrs); |
13352 | 13568 |
13880 | 14096 |
13881 // Look for marker | 14097 // Look for marker |
13882 if (isCaretNode(node)) { | 14098 if (isCaretNode(node)) { |
13883 textNode = node.firstChild; | 14099 textNode = node.firstChild; |
13884 | 14100 |
13885 perform(node); | 14101 if (textNode) { |
13886 | 14102 perform(node); |
13887 rng = dom.createRng(); | 14103 |
13888 rng.setStart(textNode, textNode.nodeValue.length); | 14104 rng = dom.createRng(); |
13889 rng.setEnd(textNode, textNode.nodeValue.length); | 14105 rng.setStart(textNode, textNode.nodeValue.length); |
13890 selection.setRng(rng); | 14106 rng.setEnd(textNode, textNode.nodeValue.length); |
13891 ed.nodeChanged(); | 14107 selection.setRng(rng); |
14108 ed.nodeChanged(); | |
14109 } else | |
14110 dom.remove(node); | |
13892 } | 14111 } |
13893 }); | 14112 }); |
13894 | 14113 |
13895 // Always unbind and clear pending styles on keyup | 14114 // Always unbind and clear pending styles on keyup |
13896 if (e.type == 'keyup' || e.type == 'mouseup') | 14115 if (e.type == 'keyup' || e.type == 'mouseup') |
13909 | 14128 |
13910 if (settings.inline_styles) { | 14129 if (settings.inline_styles) { |
13911 fontSizes = tinymce.explode(settings.font_size_style_values); | 14130 fontSizes = tinymce.explode(settings.font_size_style_values); |
13912 | 14131 |
13913 function replaceWithSpan(node, styles) { | 14132 function replaceWithSpan(node, styles) { |
13914 dom.replace(dom.create('span', { | 14133 tinymce.each(styles, function(value, name) { |
13915 style : styles | 14134 if (value) |
13916 }), node, 1); | 14135 dom.setStyle(node, name, value); |
14136 }); | |
14137 | |
14138 dom.rename(node, 'span'); | |
13917 }; | 14139 }; |
13918 | 14140 |
13919 filters = { | 14141 filters = { |
13920 font : function(dom, node) { | 14142 font : function(dom, node) { |
13921 replaceWithSpan(node, { | 14143 replaceWithSpan(node, { |