PageSourceSearch

https://www.utsuwayayuuyuu.com/assets/js/SpryDOMUtils.js

js utsuwayayuuyuu.com collected 2026-10-04 13:26:42 UTC 28,004 bytes, 1,159 lines download raw bytes

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.