1// SpryDOMUtils.js - version 0.12 - Spry Pre-Release 1.6.1 2// 3// Copyright (c) 2007. Adobe Systems Incorporated. 4// All rights reserved. 5// 6// Redistribution and use in source and binary forms, with or without 7// modification, are permitted provided that the following conditions are met: 8// 9// * Redistributions of source code must retain the above copyright notice, 10// this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above copyright notice, 12// this list of conditions and the following disclaimer in the documentation 13// and/or other materials provided with the distribution. 14// * Neither the name of Adobe Systems Incorporated nor the names of its 15// contributors may be used to endorse or promote products derived from this 16// software without specific prior written permission. 17// 18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28// POSSIBILITY OF SUCH DAMAGE. 29 30(function() { // BeginSpryComponent 31 32if (typeof Spry == "undefined") window.Spry = {}; if (!Spry.Utils) Spry.Utils = {}; 33 34////////////////////////////////////////////////////////////////////// 35// 36// Define Prototype's $() convenience function, but make sure it is 37// namespaced under Spry so that we avoid collisions with other 38// toolkits. 39// 40////////////////////////////////////////////////////////////////////// 41 42Spry.$ = function(element) 43{ 44 if (arguments.length > 1) 45 { 46 for (var i = 0, elements = [], length = arguments.length; i < length; i++) 47 elements.push(Spry.$(arguments[i])); 48 return elements; 49 } 50 if (typeof element == 'string') 51 element = document.getElementById(element); 52 return element; 53}; 54 55////////////////////////////////////////////////////////////////////// 56// 57// DOM Utils 58// 59////////////////////////////////////////////////////////////////////// 60 61Spry.Utils.getAttribute = function(ele, name) 62{ 63 ele = Spry.$(ele); 64 if (!ele || !name) 65 return null; 66 67 // We need to wrap getAttribute with a try/catch because IE will throw 68 // an exception if you call it with a namespace prefixed attribute name 69 // that doesn't exist. 70 71 try { var value = ele.getAttribute(name); } 72 catch (e) { value == undefined; } 73 74 // XXX: Workaround for Safari 2.x and earlier: 75 // 76 // If value is undefined, the attribute didn't exist. Check to see if this is 77 // a namespace prefixed attribute name. If it is, remove the ':' from the name 78 // and try again. This allows us to support spry attributes of the form 79 // "spry:region" and "spryregion". 80 81 if (value == undefined && name.search(/:/) != -1) 82 { 83 try { var value = ele.getAttribute(name.replace(/:/, "")); } 84 catch (e) { value == undefined; } 85 } 86 87 return value; 88}; 89 90Spry.Utils.setAttribute = function(ele, name, value) 91{ 92 ele = Spry.$(ele); 93 if (!ele || !name) 94 return; 95 96 // IE doesn't allow you to set the "class" attribute. You 97 // have to set the className property instead. 98 99 if (name == "class") 100 ele.className = value; 101 else 102 { 103 // I'm probably being a bit paranoid, but given the fact that 104 // getAttribute() throws exceptions when dealing with namespace 105 // prefixed attributes, I'm going to wrap this setAttribute() 106 // call with try/catch just in case ... 107 108 try { ele.setAttribute(name, value); } catch(e) {} 109 110 // XXX: Workaround for Safari 2.x and earlier: 111 // 112 // If this is a namespace prefixed attribute, check to make 113 // sure an attribute was created. This is necessary because some 114 // older versions of Safari (2.x and earlier) drop the namespace 115 // prefixes. If the attribute was munged, try removing the ':' 116 // character from the attribute name and setting the attribute 117 // using the resulting name. The idea here is that even if we 118 // remove the ':' character, Spry.Utils.getAttribute() will still 119 // find the attribute. 120 121 if (name.search(/:/) != -1 && ele.getAttribute(name) == undefined) 122 ele.setAttribute(name.replace(/:/, ""), value); 123 } 124}; 125 126Spry.Utils.removeAttribute = function(ele, name) 127{ 128 ele = Spry.$(ele); 129 if (!ele || !name) 130 return; 131 132 try { ele.removeAttribute(name); } catch(e) {} 133 134 // XXX: Workaround for Safari 2.x and earlier: 135 // 136 // If this is a namespace prefixed attribute, make sure we 137 // also remove any attributes with the same name, but without 138 // the ':' character. 139 140 if (name.search(/:/) != -1) 141 ele.removeAttribute(name.replace(/:/, "")); 142 143 // XXX: Workaround for IE 144 // 145 // IE doesn't allow you to remove the "class" attribute. 146 // It requires you to remove "className" instead, so go 147 // ahead and try to remove that too. 148 149 if (name == "class") 150 ele.removeAttribute("className"); 151}; 152 153Spry.Utils.addClassName = function(ele, className) 154{ 155 ele = Spry.$(ele); 156 if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1)) 157 return; 158 ele.className += (ele.className ? " " : "") + className; 159}; 160 161Spry.Utils.removeClassName = function(ele, className) 162{ 163 ele = Spry.$(ele); 164 if (Spry.Utils.hasClassName(ele, className)) 165 ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), ""); 166}; 167 168Spry.Utils.toggleClassName = function(ele, className) 169{ 170 if (Spry.Utils.hasClassName(ele, className)) 171 Spry.Utils.removeClassName(ele, className); 172 else 173 Spry.Utils.addClassName(ele, className); 174}; 175 176Spry.Utils.hasClassName = function(ele, className) 177{ 178 ele = Spry.$(ele); 179 if (!ele || !className || !ele.className || ele.className.search(new RegExp("\\b" + className + "\\b")) == -1) 180 return false;
181 return true; 182}; 183 184Spry.Utils.camelizeString = function(str) 185{ 186 var cStr = ""; 187 var a = str.split("-"); 188 for (var i = 0; i < a.length; i++) 189 { 190 var s = a[i]; 191 if (s) 192 cStr = cStr ? (cStr + s.charAt(0).toUpperCase() + s.substring(1)) : s; 193 } 194 return cStr; 195}; 196 197Spry.Utils.styleStringToObject = function(styleStr) 198{ 199 var o = {}; 200 if (styleStr) 201 { 202 var pvA = styleStr.split(";"); 203 for (var i = 0; i < pvA.length; i++) 204 { 205 var pv = pvA[i]; 206 if (pv && pv.indexOf(":") != -1) 207 { 208 var nvA = pv.split(":"); 209 var n = nvA[0].replace(/^\s*|\s*$/g, ""); 210 var v = nvA[1].replace(/^\s*|\s*$/g, ""); 211 if (n && v) 212 o[Spry.Utils.camelizeString(n)] = v; 213 } 214 } 215 } 216 return o; 217}; 218 219Spry.Utils.addEventListener = function(element, eventType, handler, capture) 220{ 221 try 222 { 223 if (!Spry.Utils.eventListenerIsBoundToElement(element, eventType, handler, capture)) 224 { 225 element = Spry.$(element); 226 handler = Spry.Utils.bindEventListenerToElement(element, eventType, handler, capture); 227 if (element.addEventListener) 228 element.addEventListener(eventType, handler, capture); 229 else if (element.attachEvent) 230 element.attachEvent("on" + eventType, handler); 231 } 232 } 233 catch (e) {} 234}; 235 236Spry.Utils.removeEventListener = function(element, eventType, handler, capture) 237{ 238 try 239 { 240 element = Spry.$(element); 241 handler = Spry.Utils.unbindEventListenerFromElement(element, eventType, handler, capture); 242 if (element.removeEventListener) 243 element.removeEventListener(eventType, handler, capture); 244 else if (element.detachEvent) 245 element.detachEvent("on" + eventType, handler); 246 } 247 catch (e) {} 248}; 249 250Spry.Utils.eventListenerHash = {}; 251Spry.Utils.nextEventListenerID = 1; 252 253Spry.Utils.getHashForElementAndHandler = function(element, eventType, handler, capture) 254{ 255 256 var hash = null; 257 element = Spry.$(element); 258 if (element) 259 { 260 if (typeof element.spryEventListenerID == "undefined") 261 element.spryEventListenerID = "e" + (Spry.Utils.nextEventListenerID++); 262 if (typeof handler.spryEventHandlerID == "undefined") 263 handler.spryEventHandlerID = "h" + (Spry.Utils.nextEventListenerID++); 264 hash = element.spryEventListenerID + "-" + handler.spryEventHandlerID + "-" + eventType + (capture?"-capture":""); 265 } 266 return hash; 267}; 268 269Spry.Utils.eventListenerIsBoundToElement = function(element, eventType, handler, capture) 270{ 271 element = Spry.$(element); 272 var hash = Spry.Utils.getHashForElementAndHandler(element, eventType, handler, capture); 273 return Spry.Utils.eventListenerHash[hash] != undefined; 274}; 275 276Spry.Utils.bindEventListenerToElement = function(element, eventType, handler, capture) 277{ 278 element = Spry.$(element); 279 var hash = Spry.Utils.getHashForElementAndHandler(element, eventType, handler, capture); 280 if (Spry.Utils.eventListenerHash[hash]) 281 return Spry.Utils.eventListenerHash[hash]; 282 return Spry.Utils.eventListenerHash[hash] = function(e) 283 { 284 e = e || window.event; 285 286 if (!e.preventDefault) e.preventDefault = function() { this.returnValue = false; }; 287 if (!e.stopPropagation) e.stopPropagation = function() { this.cancelBubble = true; }; 288 289 var result = handler.call(element, e); 290 if (result == false) 291 { 292 e.preventDefault(); 293 e.stopPropagation(); 294 } 295 return result; 296 }; 297}; 298 299Spry.Utils.unbindEventListenerFromElement = function(element, eventType, handler, capture) 300{ 301 element = Spry.$(element); 302 var hash = Spry.Utils.getHashForElementAndHandler(element, eventType, handler, capture); 303 if (Spry.Utils.eventListenerHash[hash]) 304 { 305 handler = Spry.Utils.eventListenerHash[hash]; 306 Spry.Utils.eventListenerHash[hash] = undefined; 307 } 308 return handler; 309}; 310 311Spry.Utils.addLoadListener = function(handler) 312{ 313 if (typeof window.addEventListener != 'undefined') 314 window.addEventListener('load', handler, false); 315 else if (typeof document.addEventListener != 'undefined') 316 document.addEventListener('load', handler, false); 317 else if (typeof window.attachEvent != 'undefined') 318 window.attachEvent('onload', handler); 319}; 320 321Spry.Utils.getAncestor = function(ele, selector) 322{ 323 ele = Spry.$(ele); 324 if (ele) 325 { 326 var s = Spry.$$.tokenizeSequence(selector ? selector : "*")[0]; 327 var t = s ? s[0] : null; 328 if (t) 329 { 330 var p = ele.parentNode; 331 while (p) 332 { 333 if (t.match(p)) 334 return p; 335 p = p.parentNode; 336 } 337 } 338 } 339 return null; 340}; 341 342////////////////////////////////////////////////////////////////////// 343// 344// CSS Selector Matching 345// 346////////////////////////////////////////////////////////////////////// 347 348Spry.$$ = function(selectorSequence, rootNode) 349{ 350 var matches = []; 351 Spry.$$.addExtensions(matches); 352 353 // If the first argument to $$() is an object, it 354 // is assumed that all args are either a DOM element 355 // or an array of DOM elements, in which case we 356 // simply append all DOM elements to our special 357 // matches array and return immediately. 358 359 if (typeof arguments[0] == "object") 360 { 361 for (var i = 0; i < arguments.length; i++) 362 { 363 if (arguments[i].constructor == Array) 364 matches.push.apply(matches, arguments[i]); 365 else 366 matches.push(arguments[i]); 367 } 368 return matches; 369 } 370 371 if (!rootNode) 372 rootNode = document; 373 else 374 rootNode = Spry.$(rootNode); 375 376 var sequences = Spry.$$.tokenizeSequence(selectorSequence); 377 378 ++Spry.$$.queryID; 379 380 var nid = 0; 381 var ns = sequences.length; 382 for (var i = 0; i < ns; i++) 383 { 384 var m = Spry.$$.processTokens(sequences[i], rootNode); 385 var nm = m.length; 386 for (var j = 0; j < nm; j++) 387 { 388 var n = m[j]; 389 if (!n.spry$$ID) 390 { 391 n.spry$$ID = ++nid; 392 matches.push(n); 393 } 394 } 395 } 396 397 var nm = matches.length; 398 for (i = 0; i < nm; i++) 399 matches[i].spry$$ID = undefined; 400 401 return matches; 402}; 403 404Spry.$$.cache = {}; 405Spry.$$.queryID = 0; 406 407Spry.$$.Token = function() 408{ 409 this.type = Spry.$$.Token.SELECTOR; 410 this.name = "*"; 411 this.id = ""; 412 this.classes = []; 413 this.attrs = []; 414 415 this.pseudos = []; 416}; 417 418Spry.$$.Token.Attr = function(n, v) 419{ 420 this.name = n; 421 this.value = v ? new RegExp(v) : undefined; 422}; 423 424Spry.$$.Token.PseudoClass = function(pstr) 425{ 426 this.name = pstr.replace(/\(.*/, ""); 427 this.arg = pstr.replace(/^[^\(\)]*\(?\s*|\)\s*$/g, ""); 428 this.func = Spry.$$.pseudoFuncs[this.name]; 429}; 430 431Spry.$$.Token.SELECTOR = 0; 432Spry.$$.Token.COMBINATOR = 1; 433 434Spry.$$.Token.prototype.match = function(ele, nameAlreadyMatches) 435{
436 if (this.type == Spry.$$.Token.COMBINATOR) 437 return false; 438 if (!nameAlreadyMatches && this.name != '*' && this.name != ele.nodeName.toLowerCase()) 439 return false; 440 if (this.id && this.id != ele.id) 441 return false; 442 var classes = this.classes; 443 var len = classes.length; 444 for (var i = 0; i < len; i++) 445 { 446 if (!ele.className || !classes[i].value.test(ele.className)) 447 return false; 448 } 449 450 var attrs = this.attrs; 451 len = attrs.length; 452 for (var i = 0; i < len; i++) 453 { 454 var a = attrs[i]; 455 var an = ele.attributes.getNamedItem(a.name); 456 if (!an || (!a.value && an.nodeValue == undefined) || (a.value && !a.value.test(an.nodeValue))) 457 return false; 458 } 459 460 var ps = this.pseudos; 461 var len = ps.length; 462 for (var i = 0; i < len; i++) 463 { 464 var p = ps[i]; 465 if (p && p.func && !p.func(p.arg, ele, this)) 466 return false; 467 } 468 469 return true; 470}; 471 472Spry.$$.Token.prototype.getNodeNameIfTypeMatches = function(ele) 473{ 474 var nodeName = ele.nodeName.toLowerCase(); 475 if (this.name != '*') 476 { 477 if (this.name != nodeName) 478 return null; 479 return this.name; 480 } 481 return nodeName; 482}; 483 484Spry.$$.escapeRegExpCharsRE = /\/|\.|\*|\+|\(|\)|\[|\]|\{|\}|\\|\|/g; 485 486Spry.$$.tokenizeSequence = function(s) 487{ 488 var cc = Spry.$$.cache[s]; 489 if (cc) return cc; 490 491 // Attribute Selector: /(\[[^\"'~\^\$\*\|\]=]+([~\^\$\*\|]?=\s*('[^']*'|"[^"]*"|[^"'\]]+))?\s*\])/g 492 // Simple Selector: /((:[^\.#:\s,>~\+\[\]]+\(([^\(\)]+|\([^\(\)]*\))*\))|[\.#:]?[^\.#:\s,>~\+\[\]]+)/g 493 // Combinator: /(\s*[\s,>~\+]\s*)/g 494 495 var tokenExpr = /(\[[^\"'~\^\$\*\|\]=]+([~\^\$\*\|]?=\s*('[^']*'|"[^"]*"|[^"'\]]+))?\s*\])|((:[^\.#:\s,>~\+\[\]]+\(([^\(\)]+|\([^\(\)]*\))*\))|[\.#:]?[^\.#:\s,>~\+\[\]]+)|(\s*[\s,>~\+]\s*)/g; 496 497 var tkn = new Spry.$$.Token; 498 var sequence = []; 499 sequence.push(tkn); 500 var tokenSequences = []; 501 tokenSequences.push(sequence); 502 503 s = s.replace(/^\s*|\s*$/, ""); 504 505 var expMatch = tokenExpr.exec(s); 506 while (expMatch) 507 { 508 var tstr = expMatch[0]; 509 var c = tstr.charAt(0); 510 switch (c) 511 { 512 case '.': 513 tkn.classes.push(new Spry.$$.Token.Attr("class", "\\b" + tstr.substr(1) + "\\b")); 514 break; 515 case '#': 516 tkn.id = tstr.substr(1); 517 break; 518 case ':': 519 tkn.pseudos.push(new Spry.$$.Token.PseudoClass(tstr)); 520 break; 521 case '[': 522 var attrComps = tstr.match(/\[([^\"'~\^\$\*\|\]=]+)(([~\^\$\*\|]?=)\s*('[^']*'|"[^"]*"|[^"'\]]+))?\s*\]/); 523 var name = attrComps[1]; 524 var matchType = attrComps[3]; 525 var val = attrComps[4]; 526 if (val) 527 { 528 val = val.replace(/^['"]|['"]$/g, ""); 529 val = val.replace(Spry.$$.escapeRegExpCharsRE, '\\$&'); 530 } 531 532 var matchStr = undefined; 533 534 switch(matchType) 535 { 536 case "=": 537 matchStr = "^" + val + "$"; 538 break; 539 case "^=": 540 matchStr = "^" + val; 541 break; 542 case "$=": 543 matchStr = val + "$"; 544 break; 545 case "~=": 546 case "|=": 547 matchStr = "\\b" + val + "\\b"; 548 break; 549 case "*=": 550 matchStr = val; 551 break; 552 } 553 554 tkn.attrs.push(new Spry.$$.Token.Attr(name, matchStr)); 555 break; 556 default: 557 var combiMatch = tstr.match(/^\s*([\s,~>\+])\s*$/); 558 if (combiMatch) 559 { 560 if (combiMatch[1] == ',') 561 { 562 sequence = new Array; 563 tokenSequences.push(sequence); 564 tkn = new Spry.$$.Token; 565 sequence.push(tkn); 566 } 567 else 568 { 569 tkn = new Spry.$$.Token; 570 tkn.type = Spry.$$.Token.COMBINATOR; 571 tkn.name = combiMatch[1]; 572 sequence.push(tkn); 573 tkn = new Spry.$$.Token(); 574 sequence.push(tkn); 575 } 576 } 577 else 578 tkn.name = tstr.toLowerCase(); 579 break; 580 } 581 expMatch = tokenExpr.exec(s); 582 } 583 584 Spry.$$.cache[s] = tokenSequences; 585 586 return tokenSequences; 587}; 588 589Spry.$$.combinatorFuncs = { 590 // Element Descendant 591 592 " ": function(nodes, token) 593 { 594 var uid = ++Spry.$$.uniqueID; 595 var results = []; 596 var nn = nodes.length; 597 for (var i = 0; i < nn; i++) 598 { 599 var n = nodes[i]; 600 if (uid != n.spry$$uid) 601 { 602 // n.spry$$uid = uid; 603 var ea = nodes[i].getElementsByTagName(token.name); 604 var ne = ea.length; 605 for (var j = 0; j < ne; j++) 606 { 607 var e = ea[j]; 608 609 // If the token matches, add it to our results. We have 610 // to make sure e is an element because IE6 returns the DOCTYPE 611 // tag as a comment when '*' is used in the call to getElementsByTagName(). 612 613 if (e.nodeType == 1 /* Node.ELEMENT_NODE */ && token.match(e, true)) 614 results.push(e); 615 e.spry$$uid = uid; 616 } 617 } 618 } 619 return results; 620 }, 621 622 // Element Child 623 624 ">": function(nodes, token) 625 { 626 var results = []; 627 var nn = nodes.length; 628 for (var i = 0; i < nn; i++) 629 { 630 var n = nodes[i].firstChild; 631 while (n) 632 { 633 if (n.nodeType == 1 /* Node.ELEMENT_NODE */ && token.match(n)) 634 results.push(n); 635 n = n.nextSibling; 636 } 637 } 638 return results; 639 }, 640 641 // Element Immediately Preceded By 642 643 "+": function(nodes, token) 644 { 645 var results = []; 646 var nn = nodes.length; 647 for (var i = 0; i < nn; i++) 648 { 649 var n = nodes[i].nextSibling; 650 while (n && n.nodeType != 1 /* Node.ELEMENT_NODE */) 651 n = n.nextSibling; 652 if (n && token.match(n)) 653 results.push(n); 654 } 655 return results; 656 }, 657 658 // Element Preceded By 659 660 "~": function(nodes, token) 661 { 662 var uid = ++Spry.$$.uniqueID; 663 var results = []; 664 var nn = nodes.length; 665 for (var i = 0; i < nn; i++) 666 { 667 var n = nodes[i].nextSibling; 668 while (n) 669 { 670 if (n.nodeType == 1 /* Node.ELEMENT_NODE */) 671 { 672 if (uid == n.spry$$uid) 673 break; 674 675 if (token.match(n)) 676 { 677 results.push(n); 678 n.spry$$uid = uid; 679 } 680 } 681 n = n.nextSibling; 682 } 683 } 684 return results; 685 } 686}; 687 688Spry.$$.uniqueID = 0; 689 690Spry.$$.pseudoFuncs = { 691 ":first-child": function(arg, node, token) 692 { 693 var n = node.previousSibling; 694 while (n) 695 { 696 if (n.nodeType == 1) return false; // Node.ELEMENT_NODE 697 n = n.previousSibling; 698 } 699 700 return true; 701 }, 702 703 ":last-child": function(arg, node, token) 704 { 705 var n = node.nextSibling; 706 while (n) 707 { 708 if (n.nodeType == 1) // Node.ELEMENT_NODE 709 return false;
710 n = n.nextSibling; 711 } 712 return true; 713 }, 714 715 ":empty": function(arg, node, token) 716 { 717 var n = node.firstChild; 718 while (n) 719 { 720 switch(n.nodeType) 721 { 722 case 1: // Node.ELEMENT_NODE 723 case 3: // Node.TEXT_NODE 724 case 4: // Node.CDATA_NODE 725 case 5: // Node.ENTITY_REFERENCE_NODE 726 return false; 727 } 728 n = n.nextSibling; 729 } 730 return true; 731 }, 732 733 ":nth-child": function(arg, node, token) 734 { 735 return Spry.$$.nthChild(arg, node, token); 736 }, 737 738 ":nth-last-child": function(arg, node, token) 739 { 740 return Spry.$$.nthChild(arg, node, token, true); 741 }, 742 743 ":nth-of-type": function(arg, node, token) 744 { 745 return Spry.$$.nthChild(arg, node, token, false, true); 746 }, 747 748 ":nth-last-of-type": function(arg, node, token) 749 { 750 return Spry.$$.nthChild(arg, node, token, true, true); 751 }, 752 753 ":first-of-type": function(arg, node, token) 754 { 755 var nodeName = token.getNodeNameIfTypeMatches(node); 756 if (!nodeName) return false; 757 758 var n = node.previousSibling; 759 while (n) 760 { 761 if (n.nodeType == 1 && nodeName == n.nodeName.toLowerCase()) return false; // Node.ELEMENT_NODE 762 n = n.previousSibling; 763 } 764 765 return true; 766 }, 767 768 ":last-of-type": function(arg, node, token) 769 { 770 var nodeName = token.getNodeNameIfTypeMatches(node); 771 if (!nodeName) return false; 772 773 var n = node.nextSibling; 774 while (n) 775 { 776 if (n.nodeType == 1 && nodeName == n.nodeName.toLowerCase()) // Node.ELEMENT_NODE 777 return false; 778 n = n.nextSibling; 779 } 780 return true; 781 }, 782 783 ":only-child": function(arg, node, token) 784 { 785 var f = Spry.$$.pseudoFuncs; 786 return f[":first-child"](arg, node, token) && f[":last-child"](arg, node, token); 787 }, 788 789 ":only-of-type": function(arg, node, token) 790 { 791 var f = Spry.$$.pseudoFuncs; 792 return f[":first-of-type"](arg, node, token) && f[":last-of-type"](arg, node, token); 793 }, 794 795 ":not": function(arg, node, token) 796 { 797 var s = Spry.$$.tokenizeSequence(arg)[0]; 798 var t = s ? s[0] : null; 799 return !t || !t.match(node); 800 }, 801 802 ":enabled": function(arg, node, token) 803 { 804 return !node.disabled; 805 }, 806 807 ":disabled": function(arg, node, token) 808 { 809 return node.disabled; 810 }, 811 812 ":checked": function(arg, node, token) 813 { 814 return node.checked; 815 }, 816 817 ":root": function(arg, node, token) 818 { 819 return node.parentNode && node.ownerDocument && node.parentNode == node.ownerDocument; 820 } 821}; 822 823Spry.$$.nthRegExp = /((-|[0-9]+)?n)?([+-]?[0-9]*)/; 824 825Spry.$$.nthCache = { 826 "even": { a: 2, b: 0, mode: 1, invalid: false } 827 , "odd": { a: 2, b: 1, mode: 1, invalid: false } 828 , "2n": { a: 2, b: 0, mode: 1, invalid: false } 829 , "2n+1": { a: 2, b: 1, mode: 1, invalid: false } 830}; 831 832Spry.$$.parseNthChildString = function(str) 833{ 834 var o = Spry.$$.nthCache[str]; 835 if (!o) 836 { 837 var m = str.match(Spry.$$.nthRegExp); 838 var n = m[1]; 839 var a = m[2]; 840 var b = m[3]; 841 842 if (!a) 843 { 844 // An 'a' value was not specified. Was there an 'n' present? 845 // If so, we treat it as an increment of 1, otherwise we're 846 // in no-repeat mode. 847 848 a = n ? 1 : 0; 849 } 850 else if (a == "-") 851 { 852 // The string is using the "-n" short-hand which is 853 // short for -1. 854 855 a = -1; 856 } 857 else 858 { 859 // An integer repeat value for 'a' was specified. Convert 860 // it into number. 861 862 a = parseInt(a, 10); 863 } 864 865 // If a 'b' value was specified, turn it into a number. 866 // If no 'b' value was specified, default to zero. 867 868 b = b ? parseInt(b, 10) : 0; 869 870 // Figure out the mode: 871 // 872 // -1 - repeat backwards 873 // 0 - no repeat 874 // 1 - repeat forwards 875 876 var mode = (a == 0) ? 0 : ((a > 0) ? 1 : -1); 877 var invalid = false; 878 879 // Fix up 'a' and 'b' for proper repeating. 880 881 if (a > 0 && b < 0) 882 { 883 b = b % a; 884 b = ((b=(b%a)) < 0) ? a + b : b; 885 } 886 else if (a < 0) 887 { 888 if (b < 0) 889 invalid = true; 890 else 891 a = Math.abs(a); 892 } 893 894 o = new Object; 895 o.a = a; 896 o.b = b; 897 o.mode = mode; 898 o.invalid = invalid; 899 900 Spry.$$.nthCache[str] = o; 901 } 902 903 return o; 904}; 905 906Spry.$$.nthChild = function(arg, node, token, fromLastSib, matchNodeName) 907{ 908 if (matchNodeName) 909 { 910 var nodeName = token.getNodeNameIfTypeMatches(node); 911 if (!nodeName) return false; 912 } 913 914 var o = Spry.$$.parseNthChildString(arg); 915 916 if (o.invalid) 917 return false;
918 919 var qidProp = "spry$$ncQueryID"; 920 var posProp = "spry$$ncPos"; 921 var countProp = "spry$$ncCount"; 922 if (matchNodeName) 923 { 924 qidProp += nodeName; 925 posProp += nodeName; 926 countProp += nodeName; 927 } 928 929 var parent = node.parentNode; 930 if (parent[qidProp] != Spry.$$.queryID) 931 { 932 var pos = 0; 933 parent[qidProp] = Spry.$$.queryID; 934 var c = parent.firstChild; 935 while (c) 936 { 937 if (c.nodeType == 1 && (!matchNodeName || nodeName == c.nodeName.toLowerCase())) 938 c[posProp] = ++pos; 939 c = c.nextSibling; 940 } 941 parent[countProp] = pos; 942 } 943 944 pos = node[posProp]; 945 if (fromLastSib) 946 pos = parent[countProp] - pos + 1; 947 948/* 949 var sib = fromLastSib ? "nextSibling" : "previousSibling"; 950 951 var pos = 1; 952 var n = node[sib]; 953 while (n) 954 { 955 if (n.nodeType == 1 && (!matchNodeName || nodeName == n.nodeName.toLowerCase())) 956 { 957 if (n == node) break; 958 ++pos; 959 } 960 n = n[sib]; 961 } 962*/ 963 964 if (o.mode == 0) // Exact match 965 return pos == o.b; 966 if (o.mode > 0) // Forward Repeat 967 return (pos < o.b) ? false : (!((pos - o.b) % o.a)); 968 return (pos > o.b) ? false : (!((o.b - pos) % o.a)); // Backward Repeat 969}; 970 971Spry.$$.processTokens = function(tokens, root) 972{ 973 var numTokens = tokens.length; 974 var nodeSet = [ root ]; 975 var combiFunc = null; 976 977 for (var i = 0; i < numTokens && nodeSet.length > 0; i++) 978 { 979 var t = tokens[i]; 980 if (t.type == Spry.$$.Token.SELECTOR) 981 { 982 if (combiFunc) 983 {
984 nodeSet = combiFunc(nodeSet, t); 985 combiFunc = null; 986 } 987 else 988 nodeSet = Spry.$$.getMatchingElements(nodeSet, t); 989 } 990 else // Spry.$$.Token.COMBINATOR 991 combiFunc = Spry.$$.combinatorFuncs[t.name]; 992 } 993 return nodeSet; 994}; 995 996Spry.$$.getMatchingElements = function(nodes, token) 997{ 998 var results = []; 999 if (token.id) 1000 { 1001 n = nodes[0]; 1002 if (n && n.ownerDocument) 1003 { 1004 var e = n.ownerDocument.getElementById(token.id); 1005 if (e) 1006 { 1007 // XXX: We need to make sure that the element 1008 // we found is actually underneath the root 1009 // we were given! 1010 1011 if (token.match(e)) 1012 results.push(e); 1013 } 1014 return results; 1015 } 1016 } 1017 1018 var nn = nodes.length; 1019 for (var i = 0; i < nn; i++) 1020 { 1021 var n = nodes[i]; 1022 // if (token.match(n)) results.push(n); 1023 1024 var ea = n.getElementsByTagName(token.name); 1025 var ne = ea.length; 1026 for (var j = 0; j < ne; j++) 1027 { 1028 var e = ea[j]; 1029 1030 // If the token matches, add it to our results. We have 1031 // to make sure e is an element because IE6 returns the DOCTYPE 1032 // tag as a comment when '*' is used in the call to getElementsByTagName(). 1033 1034 if (e.nodeType == 1 /* Node.ELEMENT_NODE */ && token.match(e, true)) 1035 results.push(e); 1036 } 1037 } 1038 return results; 1039}; 1040 1041/* 1042Spry.$$.dumpSequences = function(sequences) 1043{ 1044 Spry.Debug.trace("<hr />Number of Sequences: " + sequences.length); 1045 for (var i = 0; i < sequences.length; i++) 1046 { 1047 var str = ""; 1048 var s = sequences[i]; 1049 Spry.Debug.trace("<hr />Sequence " + i + " -- Tokens: " + s.length); 1050 for (var j = 0; j < s.length; j++) 1051 { 1052 var t = s[j]; 1053 if (t.type == Spry.$$.Token.SELECTOR) 1054 { 1055 str += " SELECTOR:\n Name: " + t.name + "\n ID: " + t.id + "\n Attrs:\n"; 1056 for (var k = 0; k < t.classes.length; k++) 1057 str += " " + t.classes[k].name + ": " + t.classes[k].value + "\n"; 1058 for (var k = 0; k < t.attrs.length; k++) 1059 str += " " + t.attrs[k].name + ": " + t.attrs[k].value + "\n"; 1060 str += " Pseudos:\n"; 1061 for (var k = 0; k < t.pseudos.length; k++) 1062 str += " " + t.pseudos[k].name + (t.pseudos[k].arg ? "(" + t.pseudos[k].arg + ")" : "") + "\n"; 1063 } 1064 else 1065 { 1066 str += " COMBINATOR:\n Name: '" + t.name + "'\n"; 1067 } 1068 } 1069 Spry.Debug.trace("<pre>" + Spry.Utils.encodeEntities(str) + "</pre>"); 1070 } 1071}; 1072*/ 1073 1074Spry.$$.addExtensions = function(a) 1075{ 1076 for (var f in Spry.$$.Results) 1077 a[f] = Spry.$$.Results[f]; 1078}; 1079 1080Spry.$$.Results = {}; 1081 1082Spry.$$.Results.forEach = function(func) 1083{ 1084 var n = this.length; 1085 for (var i = 0; i < n; i++) 1086 func(this[i]); 1087 return this; 1088}; 1089 1090Spry.$$.Results.setAttribute = function(name, value) 1091{ 1092 return this.forEach(function(n) { Spry.Utils.setAttribute(n, name, value); }); 1093}; 1094 1095Spry.$$.Results.removeAttribute = function(name) 1096{ 1097 return this.forEach(function(n) { Spry.Utils.removeAttribute(n, name); }); 1098}; 1099 1100Spry.$$.Results.addClassName = function(className) 1101{ 1102 return this.forEach(function(n) { Spry.Utils.addClassName(n, className); }); 1103}; 1104 1105Spry.$$.Results.removeClassName = function(className) 1106{ 1107 return this.forEach(function(n) { Spry.Utils.removeClassName(n, className); }); 1108}; 1109 1110Spry.$$.Results.toggleClassName = function(className) 1111{ 1112 return this.forEach(function(n) { Spry.Utils.toggleClassName(n, className); }); 1113}; 1114 1115Spry.$$.Results.addEventListener = function(eventType, handler, capture, bindHandler) 1116{ 1117 return this.forEach(function(n) { Spry.Utils.addEventListener(n, eventType, handler, capture, bindHandler); }); 1118}; 1119 1120Spry.$$.Results.removeEventListener = function(eventType, handler, capture) 1121{ 1122 return this.forEach(function(n) { Spry.Utils.removeEventListener(n, eventType, handler, capture); }); 1123}; 1124 1125Spry.$$.Results.setStyle = function(style) 1126{ 1127 if (style) 1128 { 1129 style = Spry.Utils.styleStringToObject(style); 1130 this.forEach(function(n) 1131 { 1132 for (var p in style) 1133 try { n.style[p] = style[p]; } catch (e) {} 1134 }); 1135 } 1136 return this; 1137}; 1138 1139Spry.$$.Results.setProperty = function(prop, value) 1140{ 1141 if (prop) 1142 { 1143 if (typeof prop == "string") 1144 { 1145 var p = {}; 1146 p[prop] = value; 1147 prop = p; 1148 } 1149 1150 this.forEach(function(n) 1151 { 1152 for (var p in prop) 1153 try { n[p] = prop[p]; } catch (e) {} 1154 }); 1155 } 1156 return this; 1157}; 1158 1159})(); // EndSpryComponent
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.