PageSourceSearch

https://strangepaths.com/wp-includes/js/prototype.js

js strangepaths.com collected 2026-10-02 11:01:08 UTC 51,859 bytes, 2,008 lines download raw bytes

1/*	Prototype JavaScript framework, version 1.5.0_rc0
2 *	(c) 2005 Sam Stephenson <[email protected]>
3 *
4 *	Prototype is freely distributable under the terms of an MIT-style license.
5 *	For details, see the Prototype web site: http://prototype.conio.net/
6 *
7/*--------------------------------------------------------------------------*/
8
9var Prototype = {
10	Version: '1.5.0_rc0',
11	ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
12
13	emptyFunction: function() {},
14	K: function(x) {return x}
15}
16
17var Class = {
18	create: function() {
19		return function() {
20			this.initialize.apply(this, arguments);
21		}
22	}
23}
24
25var Abstract = new Object();
26
27Object.extend = function(destination, source) {
28	for (var property in source) {
29		destination[property] = source[property];
30	}
31	return destination;
32}
33
34Object.inspect = function(object) {
35	try {
36		if (object == undefined) return 'undefined';
37		if (object == null) return 'null';
38		return object.inspect ? object.inspect() : object.toString();
39	} catch (e) {
40		if (e instanceof RangeError) return '...';
41		throw e;
42	}
43}
44
45Function.prototype.bind = function() {
46	var __method = this, args = $A(arguments), object = args.shift();
47	return function() {
48		return __method.apply(object, args.concat($A(arguments)));
49	}
50}
51
52Function.prototype.bindAsEventListener = function(object) {
53	var __method = this;
54	return function(event) {
55		return __method.call(object, event || window.event);
56	}
57}
58
59Object.extend(Number.prototype, {
60	toColorPart: function() {
61		var digits = this.toString(16);
62		if (this < 16) return '0' + digits;
63		return digits;
64	},
65
66	succ: function() {
67		return this + 1;
68	},
69
70	times: function(iterator) {
71		$R(0, this, true).each(iterator);
72		return this;
73	}
74});
75
76var Try = {
77	these: function() {
78		var returnValue;
79
80		for (var i = 0; i < arguments.length; i++) {
81			var lambda = arguments[i];
82			try {
83				returnValue = lambda();
84				break;
85			} catch (e) {}
86		}
87
88		return returnValue;
89	}
90}
91
92/*--------------------------------------------------------------------------*/
93
94var PeriodicalExecuter = Class.create();
95PeriodicalExecuter.prototype = {
96	initialize: function(callback, frequency) {
97		this.callback = callback;
98		this.frequency = frequency;
99		this.currentlyExecuting = false;
100
101		this.registerCallback();
102	},
103
104	registerCallback: function() {
105		setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
106	},
107
108	onTimerEvent: function() {
109		if (!this.currentlyExecuting) {
110			try {
111				this.currentlyExecuting = true;
112				this.callback();
113			} finally {
114				this.currentlyExecuting = false;
115			}
116		}
117	}
118}
119Object.extend(String.prototype, {
120	gsub: function(pattern, replacement) {
121		var result = '', source = this, match;
122		replacement = arguments.callee.prepareReplacement(replacement);
123
124		while (source.length > 0) {
125			if (match = source.match(pattern)) {
126				result += source.slice(0, match.index);
127				result += (replacement(match) || '').toString();
128				source	= source.slice(match.index + match[0].length);
129			} else {
130				result += source, source = '';
131			}
132		}
133		return result;
134	},
135
136	sub: function(pattern, replacement, count) {
137		replacement = this.gsub.prepareReplacement(replacement);
138		count = count === undefined ? 1 : count;
139
140		return this.gsub(pattern, function(match) {
141			if (--count < 0) return match[0];
142			return replacement(match);
143		});
144	},
145
146	scan: function(pattern, iterator) {
147		this.gsub(pattern, iterator);
148		return this;
149	},
150
151	truncate: function(length, truncation) {
152		length = length || 30;
153		truncation = truncation === undefined ? '...' : truncation;
154		return this.length > length ?
155			this.slice(0, length - truncation.length) + truncation : this;
156	},
157
158	strip: function() {
159		return this.replace(/^\s+/, '').replace(/\s+$/, '');
160	},
161
162	stripTags: function() {
163		return this.replace(/<\/?[^>]+>/gi, '');
164	},
165
166	stripScripts: function() {
167		return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
168	},
169
170	extractScripts: function() {
171		var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
172		var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
173		return (this.match(matchAll) || []).map(function(scriptTag) {
174			return (scriptTag.match(matchOne) || ['', ''])[1];
175		});
176	},
177
178	evalScripts: function() {
179		return this.extractScripts().map(function(script) { return eval(script) });
180	},
181
182	escapeHTML: function() {
183		var div = document.createElement('div');
184		var text = document.createTextNode(this);
185		div.appendChild(text);
186		return div.innerHTML;
187	},
188
189	unescapeHTML: function() {
190		var div = document.createElement('div');
191		div.innerHTML = this.stripTags();
192		return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
193	},
194
195	toQueryParams: function() {
196		var pairs = this.match(/^\??(.*)$/)[1].split('&');
197		return pairs.inject({}, function(params, pairString) {
198			var pair = pairString.split('=');
199			params[pair[0]] = pair[1];
200			return params;
201		});
202	},
203
204	toArray: function() {
205		return this.split('');
206	},
207
208	camelize: function() {
209		var oStringList = this.split('-');
210		if (oStringList.length == 1) return oStringList[0];
211
212		var camelizedString = this.indexOf('-') == 0
213			? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
214			: oStringList[0];
215
216		for (var i = 1, len = oStringList.length; i < len; i++) {
217			var s = oStringList[i];
218			camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
219		}
220
221		return camelizedString;
222	},
223
224	inspect: function() {
225		return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'";
226	}
227});
228
229String.prototype.gsub.prepareReplacement = function(replacement) {
230	if (typeof replacement == 'function') return replacement;
231	var template = new Template(replacement);
232	return function(match) { return template.evaluate(match) };
233}
234
235String.prototype.parseQuery = String.prototype.toQueryParams;
236
237var Template = Class.create();
238Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
239Template.prototype = {
240	initialize: function(template, pattern) {
241		this.template = template.toString();
242		this.pattern	= pattern || Template.Pattern;
243	},
244
245	evaluate: function(object) {
246		return this.template.gsub(this.pattern, function(match) {
247			var before = match[1];
248			if (before == '\\') return match[2];
249			return before + (object[match[3]] || '').toString();
250		});
251	}
252}
253
254var $break		= new Object();
255var $continue = new Object();
256
257var Enumerable = {
258	each: function(iterator) {
259		var index = 0;
260		try {
261			this._each(function(value) {
262				try {
263					iterator(value, index++);
264				} catch (e) {
265					if (e != $continue) throw e;
266				}
267			});
268		} catch (e) {
269			if (e != $break) throw e;
270		}
271	},
272
273	all: function(iterator) {
274		var result = true;
275		this.each(function(value, index) {
276			result = result && !!(iterator || Prototype.K)(value, index);
277			if (!result) throw $break;
278		});
279		return result;
280	},
281
282	any: function(iterator) {
283		var result = true;
284		this.each(function(value, index) {
285			if (result = !!(iterator || Prototype.K)(value, index))
286				throw $break;
287		});
288		return result;
289	},
290
291	collect: function(iterator) {
292		var results = [];
293		this.each(function(value, index) {
294			results.push(iterator(value, index));
295		});
296		return results;
297	},
298
299	detect: function (iterator) {
300		var result;
301		this.each(function(value, index) {
302			if (iterator(value, index)) {
303				result = value;
304				throw $break;
305			}
306		});
307		return result;
308	},
309
310	findAll: function(iterator) {
311		var results = [];
312		this.each(function(value, index) {
313			if (iterator(value, index))
314				results.push(value);
315		});
316		return results;
317	},
318
319	grep: function(pattern, iterator) {
320		var results = [];
321		this.each(function(value, index) {
322			var stringValue = value.toString();
323			if (stringValue.match(pattern))
324				results.push((iterator || Prototype.K)(value, index));
325		})
326		return results;
327	},
328
329	include: function(object) {
330		var found = false;
331		this.each(function(value) {
332			if (value == object) {
333				found = true;
334				throw $break;
335			}
336		});
337		return found;
338	},
339
340	inject: function(memo, iterator) {
341		this.each(function(value, index) {
342			memo = iterator(memo, value, index);
343		});
344		return memo;
345	},
346
347	invoke: function(method) {
348		var args = $A(arguments).slice(1);
349		return this.collect(function(value) {
350			return value[method].apply(value, args);
351		});
352	},
353
354	max: function(iterator) {
355		var result;
356		this.each(function(value, index) {
357			value = (iterator || Prototype.K)(value, index);
358			if (result == undefined || value >= result)
359				result = value;
360		});
361		return result;
362	},
363
364	min: function(iterator) {
365		var result;
366		this.each(function(value, index) {
367			value = (iterator || Prototype.K)(value, index);
368			if (result == undefined || value < result)
369				result = value;
370		});
371		return result;
372	},
373
374	partition: function(iterator) {
375		var trues = [], falses = [];
376		this.each(function(value, index) {
377			((iterator || Prototype.K)(value, index) ?
378				trues : falses).push(value);
379		});
380		return [trues, falses];
381	},
382
383	pluck: function(property) {
384		var results = [];
385		this.each(function(value, index) {
386			results.push(value[property]);
387		});
388		return results;
389	},
390
391	reject: function(iterator) {
392		var results = [];
393		this.each(function(value, index) {
394			if (!iterator(value, index))
395				results.push(value);
396		});
397		return results;
398	},
399
400	sortBy: function(iterator) {
401		return this.collect(function(value, index) {
402			return {value: value, criteria: iterator(value, index)};
403		}).sort(function(left, right) {
404			var a = left.criteria, b = right.criteria;
405			return a < b ? -1 : a > b ? 1 : 0;
406		}).pluck('value');
407	},
408
409	toArray: function() {
410		return this.collect(Prototype.K);
411	},
412
413	zip: function() {
414		var iterator = Prototype.K, args = $A(arguments);
415		if (typeof args.last() == 'function')
416			iterator = args.pop();
417
418		var collections = [this].concat(args).map($A);
419		return this.map(function(value, index) {
420			return iterator(collections.pluck(index));
421		});
422	},
423
424	inspect: function() {
425		return '#<Enumerable:' + this.toArray().inspect() + '>';
426	}
427}
428
429Object.extend(Enumerable, {
430	map:		 Enumerable.collect,
431	find:		Enumerable.detect,
432	select:	Enumerable.findAll,
433	member:	Enumerable.include,
434	entries: Enumerable.toArray
435});
436var $A = Array.from = function(iterable) {
437	if (!iterable) return [];
438	if (iterable.toArray) {
439		return iterable.toArray();
440	} else {
441		var results = [];
442		for (var i = 0; i < iterable.length; i++)
443			results.push(iterable[i]);
444		return results;
445	}
446}
447
448Object.extend(Array.prototype, Enumerable);
449
450if (!Array.prototype._reverse)
451	Array.prototype._reverse = Array.prototype.reverse;
452
453Object.extend(Array.prototype, {
454	_each: function(iterator) {
455		for (var i = 0; i < this.length; i++)
456			iterator(this[i]);
457	},
458
459	clear: function() {
460		this.length = 0;
461		return this;
462	},
463
464	first: function() {
465		return this[0];
466	},
467
468	last: function() {
469		return this[this.length - 1];
470	},
471
472	compact: function() {
473		return this.select(function(value) {
474			return value != undefined || value != null;
475		});
476	},
477
478	flatten: function() {
479		return this.inject([], function(array, value) {
480			return array.concat(value && value.constructor == Array ?
481				value.flatten() : [value]);
482		});
483	},
484
485	without: function() {
486		var values = $A(arguments);
487		return this.select(function(value) {
488			return !values.include(value);
489		});
490	},
491
492	indexOf: function(object) {
493		for (var i = 0; i < this.length; i++)
494			if (this[i] == object) return i;
495		return -1;
496	},
497
498	reverse: function(inline) {
499		return (inline !== false ? this : this.toArray())._reverse();
500	},
501
502	inspect: function() {
503		return '[' + this.map(Object.inspect).join(', ') + ']';
504	}
505});
506var Hash = {
507	_each: function(iterator) {
508		for (var key in this) {
509			var value = this[key];
510			if (typeof value == 'function') continue;
511
512			var pair = [key, value];
513			pair.key = key;
514			pair.value = value;
515			iterator(pair);
516		}
517	},
518
519	keys: function() {
520		return this.pluck('key');
521	},
522
523	values: function() {
524		return this.pluck('value');
525	},
526
527	merge: function(hash) {
528		return $H(hash).inject($H(this), function(mergedHash, pair) {
529			mergedHash[pair.key] = pair.value;
530			return mergedHash;
531		});
532	},
533
534	toQueryString: function() {
535		return this.map(function(pair) {
536			return pair.map(encodeURIComponent).join('=');
537		}).join('&');
538	},
539
540	inspect: function() {
541		return '#<Hash:{' + this.map(function(pair) {
542			return pair.map(Object.inspect).join(': ');
543		}).join(', ') + '}>';
544	}
545}
546
547function $H(object) {
548	var hash = Object.extend({}, object || {});
549	Object.extend(hash, Enumerable);
550	Object.extend(hash, Hash);
551	return hash;
552}
553ObjectRange = Class.create();
554Object.extend(ObjectRange.prototype, Enumerable);
555Object.extend(ObjectRange.prototype, {
556	initialize: function(start, end, exclusive) {
557		this.start = start;
558		this.end = end;
559		this.exclusive = exclusive;
560	},
561
562	_each: function(iterator) {
563		var value = this.start;
564		do {
565			iterator(value);
566			value = value.succ();
567		} while (this.include(value));
568	},
569
570	include: function(value) {
571		if (value < this.start)
572			return false;
573		if (this.exclusive)
574			return value < this.end;
575		return value <= this.end;
576	}
577});
578
579var $R = function(start, end, exclusive) {
580	return new ObjectRange(start, end, exclusive);
581}
582
583var Ajax = {
584	getTransport: function() {
585		return Try.these(
586			function() {return new XMLHttpRequest()},
587			function() {return new ActiveXObject('Msxml2.XMLHTTP')},
588			function() {return new ActiveXObject('Microsoft.XMLHTTP')}
589		) || false;
590	},
591
592	activeRequestCount: 0
593}
594
595Ajax.Responders = {
596	responders: [],
597
598	_each: function(iterator) {
599		this.responders._each(iterator);
600	},
601
602	register: function(responderToAdd) {
603		if (!this.include(responderToAdd))
604			this.responders.push(responderToAdd);
605	},
606
607	unregister: function(responderToRemove) {
608		this.responders = this.responders.without(responderToRemove);
609	},
610
611	dispatch: function(callback, request, transport, json) {
612		this.each(function(responder) {
613			if (responder[callback] && typeof responder[callback] == 'function') {
614				try {
615					responder[callback].apply(responder, [request, transport, json]);
616				} catch (e) {}
617			}
618		});
619	}
620};
621
622Object.extend(Ajax.Responders, Enumerable);
623
624Ajax.Responders.register({
625	onCreate: function() {
626		Ajax.activeRequestCount++;
627	},
628
629	onComplete: function() {
630		Ajax.activeRequestCount--;
631	}
632});
633
634Ajax.Base = function() {};
635Ajax.Base.prototype = {
636	setOptions: function(options) {
637		this.options = {
638			method:			 'post',
639			asynchronous: true,
640			contentType:	'application/x-www-form-urlencoded',
641			parameters:	 ''
642		}
643		Object.extend(this.options, options || {});
644	},
645
646	responseIsSuccess: function() {
647		return this.transport.status == undefined
648				|| this.transport.status == 0
649				|| (this.transport.status >= 200 && this.transport.status < 300);
650	},
651
652	responseIsFailure: function() {
653		return !this.responseIsSuccess();
654	}
655}
656
657Ajax.Request = Class.create();
658Ajax.Request.Events =
659	['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
660
661Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
662	initialize: function(url, options) {
663		this.transport = Ajax.getTransport();
664		this.setOptions(options);
665		this.request(url);
666	},
667
668	request: function(url) {
669		var parameters = this.options.parameters || '';
670		if (parameters.length > 0) parameters += '&_=';
671
672		try {
673			this.url = url;
674			if (this.options.method == 'get' && parameters.length > 0)
675				this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
676
677			Ajax.Responders.dispatch('onCreate', this, this.transport);
678
679			this.transport.open(this.options.method, this.url,
680				this.options.asynchronous);
681
682			if (this.options.asynchronous) {
683				this.transport.onreadystatechange = this.onStateChange.bind(this);
684				setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
685			}
686
687			this.setRequestHeaders();
688
689			var body = this.options.postBody ? this.options.postBody : parameters;
690			this.transport.send(this.options.method == 'post' ? body : null);
691
692		} catch (e) {
693			this.dispatchException(e);
694		}
695	},
696
697	setRequestHeaders: function() {
698		var requestHeaders =
699			['X-Requested-With', 'XMLHttpRequest',
700			 'X-Prototype-Version', Prototype.Version,
701			 'Accept', 'text/javascript, text/html, application/xml, text/xml, */*'];
702
703		if (this.options.method == 'post') {
704			requestHeaders.push('Content-type', this.options.contentType);
705
706			/* Force "Connection: close" for Mozilla browsers to work around
707			 * a bug where XMLHttpReqeuest sends an incorrect Content-length
708			 * header. See Mozilla Bugzilla #246651.
709			 */
710			if (this.transport.overrideMimeType)
711				requestHeaders.push('Connection', 'close');
712		}
713
714		if (this.options.requestHeaders)
715			requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
716
717		for (var i = 0; i < requestHeaders.length; i += 2)
718			this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
719	},
720
721	onStateChange: function() {
722		var readyState = this.transport.readyState;
723		if (readyState != 1)
724			this.respondToReadyState(this.transport.readyState);
725	},
726
727	header: function(name) {
728		try {
729			return this.transport.getResponseHeader(name);
730		} catch (e) {}
731	},
732
733	evalJSON: function() {
734		try {
735			return eval('(' + this.header('X-JSON') + ')');
736		} catch (e) {}
737	},
738
739	evalResponse: function() {
740		try {
741			return eval(this.transport.responseText);
742		} catch (e) {
743			this.dispatchException(e);
744		}
745	},
746
747	respondToReadyState: function(readyState) {
748		var event = Ajax.Request.Events[readyState];
749		var transport = this.transport, json = this.evalJSON();
750
751		if (event == 'Complete') {
752			try {
753				(this.options['on' + this.transport.status]
754				 || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
755				 || Prototype.emptyFunction)(transport, json);
756			} catch (e) {
757				this.dispatchException(e);
758			}
759
760			if ((this.header('Content-type') || '').match(/^text\/javascript/i))
761				this.evalResponse();
762		}
763
764		try {
765			(this.options['on' + event] || Prototype.emptyFunction)(transport, json);
766			Ajax.Responders.dispatch('on' + event, this, transport, json);
767		} catch (e) {
768			this.dispatchException(e);
769		}
770
771		/* Avoid memory leak in MSIE: clean up the oncomplete event handler */
772		if (event == 'Complete')
773			this.transport.onreadystatechange = Prototype.emptyFunction;
774	},
775
776	dispatchException: function(exception) {
777		(this.options.onException || Prototype.emptyFunction)(this, exception);
778		Ajax.Responders.dispatch('onException', this, exception);
779	}
780});
781
782Ajax.Updater = Class.create();
783
784Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
785	initialize: function(container, url, options) {
786		this.containers = {
787			success: container.success ? $(container.success) : $(container),
788			failure: container.failure ? $(container.failure) :
789				(container.success ? null : $(container))
790		}
791
792		this.transport = Ajax.getTransport();
793		this.setOptions(options);
794
795		var onComplete = this.options.onComplete || Prototype.emptyFunction;
796		this.options.onComplete = (function(transport, object) {
797			this.updateContent();
798			onComplete(transport, object);
799		}).bind(this);
800
801		this.request(url);
802	},
803
804	updateContent: function() {
805		var receiver = this.responseIsSuccess() ?
806			this.containers.success : this.containers.failure;
807		var response = this.transport.responseText;
808
809		if (!this.options.evalScripts)
810			response = response.stripScripts();
811
812		if (receiver) {
813			if (this.options.insertion) {
814				new this.options.insertion(receiver, response);
815			} else {
816				Element.update(receiver, response);
817			}
818		}
819
820		if (this.responseIsSuccess()) {
821			if (this.onComplete)
822				setTimeout(this.onComplete.bind(this), 10);
823		}
824	}
825});
826
827Ajax.PeriodicalUpdater = Class.create();
828Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
829	initialize: function(container, url, options) {
830		this.setOptions(options);
831		this.onComplete = this.options.onComplete;
832
833		this.frequency = (this.options.frequency || 2);
834		this.decay = (this.options.decay || 1);
835
836		this.updater = {};
837		this.container = container;
838		this.url = url;
839
840		this.start();
841	},
842
843	start: function() {
844		this.options.onComplete = this.updateComplete.bind(this);
845		this.onTimerEvent();
846	},
847
848	stop: function() {
849		this.updater.onComplete = undefined;
850		clearTimeout(this.timer);
851		(this.onComplete || Prototype.emptyFunction).apply(this, arguments);
852	},
853
854	updateComplete: function(request) {
855		if (this.options.decay) {
856			this.decay = (request.responseText == this.lastText ?
857				this.decay * this.options.decay : 1);
858
859			this.lastText = request.responseText;
860		}
861		this.timer = setTimeout(this.onTimerEvent.bind(this),
862			this.decay * this.frequency * 1000);
863	},
864
865	onTimerEvent: function() {
866		this.updater = new Ajax.Updater(this.container, this.url, this.options);
867	}
868});
869function $() {
870	var results = [], element;
871	for (var i = 0; i < arguments.length; i++) {
872		element = arguments[i];
873		if (typeof element == 'string')
874			element = document.getElementById(element);
875		results.push(Element.extend(element));
876	}
877	return results.length < 2 ? results[0] : results;
878}
879
880document.getElementsByClassName = function(className, parentElement) {
881	var children = ($(parentElement) || document.body).getElementsByTagName('*');
882	return $A(children).inject([], function(elements, child) {
883		if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
884			elements.push(Element.extend(child));
885		return elements;
886	});
887}
888
889/*--------------------------------------------------------------------------*/
890
891if (!window.Element)
892	var Element = new Object();
893
894Element.extend = function(element) {
895	if (!element) return;
896	if (_nativeExtensions) return element;
897
898	if (!element._extended && element.tagName && element != window) {
899		var methods = Element.Methods, cache = Element.extend.cache;
900		for (property in methods) {
901			var value = methods[property];
902			if (typeof value == 'function')
903				element[property] = cache.findOrStore(value);
904		}
905	}
906
907	element._extended = true;
908	return element;
909}
910
911Element.extend.cache = {
912	findOrStore: function(value) {
913		return this[value] = this[value] || function() {
914			return value.apply(null, [this].concat($A(arguments)));
915		}
916	}
917}
918
919Element.Methods = {
920	visible: function(element) {
921		return $(element).style.display != 'none';
922	},
923
924	toggle: function() {
925		for (var i = 0; i < arguments.length; i++) {
926			var element = $(arguments[i]);
927			Element[Element.visible(element) ? 'hide' : 'show'](element);
928		}
929	},
930
931	hide: function() {
932		for (var i = 0; i < arguments.length; i++) {
933			var element = $(arguments[i]);
934			element.style.display = 'none';
935		}
936	},
937
938	show: function() {
939		for (var i = 0; i < arguments.length; i++) {
940			var element = $(arguments[i]);
941			element.style.display = '';
942		}
943	},
944
945	remove: function(element) {
946		element = $(element);
947		element.parentNode.removeChild(element);
948	},
949
950	update: function(element, html) {
951		$(element).innerHTML = html.stripScripts();
952		setTimeout(function() {html.evalScripts()}, 10);
953	},
954
955	replace: function(element, html) {
956		element = $(element);
957		if (element.outerHTML) {
958			element.outerHTML = html.stripScripts();
959		} else {
960			var range = element.ownerDocument.createRange();
961			range.selectNodeContents(element);
962			element.parentNode.replaceChild(
963				range.createContextualFragment(html.stripScripts()), element);
964		}
965		setTimeout(function() {html.evalScripts()}, 10);
966	},
967
968	getHeight: function(element) {
969		element = $(element);
970		return element.offsetHeight;
971	},
972
973	classNames: function(element) {
974		return new Element.ClassNames(element);
975	},
976
977	hasClassName: function(element, className) {
978		if (!(element = $(element))) return;
979		return Element.classNames(element).include(className);
980	},
981
982	addClassName: function(element, className) {
983		if (!(element = $(element))) return;
984		return Element.classNames(element).add(className);
985	},
986
987	removeClassName: function(element, className) {
988		if (!(element = $(element))) return;
989		return Element.classNames(element).remove(className);
990	},
991
992	// removes whitespace-only text node children
993	cleanWhitespace: function(element) {
994		element = $(element);
995		for (var i = 0; i < element.childNodes.length; i++) {
996			var node = element.childNodes[i];
997			if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
998				Element.remove(node);
999		}
1000	},
1001
1002	empty: function(element) {
1003		return $(element).innerHTML.match(/^\s*$/);
1004	},
1005
1006	childOf: function(element, ancestor) {
1007		element = $(element), ancestor = $(ancestor);
1008		while (element = element.parentNode)
1009			if (element == ancestor) return true;
1010		return false;
1011	},
1012
1013	scrollTo: function(element) {
1014		element = $(element);
1015		var x = element.x ? element.x : element.offsetLeft,
1016				y = element.y ? element.y : element.offsetTop;
1017		window.scrollTo(x, y);
1018	},
1019
1020	getStyle: function(element, style) {
1021		element = $(element);
1022		var value = element.style[style.camelize()];
1023		if (!value) {
1024			if (document.defaultView && document.defaultView.getComputedStyle) {
1025				var css = document.defaultView.getComputedStyle(element, null);
1026				value = css ? css.getPropertyValue(style) : null;
1027			} else if (element.currentStyle) {
1028				value = element.currentStyle[style.camelize()];
1029			}
1030		}
1031
1032		if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
1033			if (Element.getStyle(element, 'position') == 'static') value = 'auto';
1034
1035		return value == 'auto' ? null : value;
1036	},
1037
1038	setStyle: function(element, style) {
1039		element = $(element);
1040		for (var name in style)
1041			element.style[name.camelize()] = style[name];
1042	},
1043
1044	getDimensions: function(element) {
1045		element = $(element);
1046		if (Element.getStyle(element, 'display') != 'none')
1047			return {width: element.offsetWidth, height: element.offsetHeight};
1048
1049		// All *Width and *Height properties give 0 on elements with display none,
1050		// so enable the element temporarily
1051		var els = element.style;
1052		var originalVisibility = els.visibility;
1053		var originalPosition = els.position;
1054		els.visibility = 'hidden';
1055		els.position = 'absolute';
1056		els.display = '';
1057		var originalWidth = element.clientWidth;
1058		var originalHeight = element.clientHeight;
1059		els.display = 'none';
1060		els.position = originalPosition;
1061		els.visibility = originalVisibility;
1062		return {width: originalWidth, height: originalHeight};
1063	},
1064
1065	makePositioned: function(element) {
1066		element = $(element);
1067		var pos = Element.getStyle(element, 'position');
1068		if (pos == 'static' || !pos) {
1069			element._madePositioned = true;
1070			element.style.position = 'relative';
1071			// Opera returns the offset relative to the positioning context, when an
1072			// element is position relative but top and left have not been defined
1073			if (window.opera) {
1074				element.style.top = 0;
1075				element.style.left = 0;
1076			}
1077		}
1078	},
1079
1080	undoPositioned: function(element) {
1081		element = $(element);
1082		if (element._madePositioned) {
1083			element._madePositioned = undefined;
1084			element.style.position =
1085				element.style.top =
1086				element.style.left =
1087				element.style.bottom =
1088				element.style.right = '';
1089		}
1090	},
1091
1092	makeClipping: function(element) {
1093		element = $(element);
1094		if (element._overflow) return;
1095		element._overflow = element.style.overflow;
1096		if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
1097			element.style.overflow = 'hidden';
1098	},
1099
1100	undoClipping: function(element) {
1101		element = $(element);
1102		if (element._overflow) return;
1103		element.style.overflow = element._overflow;
1104		element._overflow = undefined;
1105	}
1106}
1107
1108Object.extend(Element, Element.Methods);
1109
1110var _nativeExtensions = false;
1111
1112if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
1113	var HTMLElement = {}
1114	HTMLElement.prototype = document.createElement('div').__proto__;
1115}
1116
1117Element.addMethods = function(methods) {
1118	Object.extend(Element.Methods, methods || {});
1119
1120	if(typeof HTMLElement != 'undefined') {
1121		var methods = Element.Methods, cache = Element.extend.cache;
1122		for (property in methods) {
1123			var value = methods[property];
1124			if (typeof value == 'function')
1125				HTMLElement.prototype[property] = cache.findOrStore(value);
1126		}
1127		_nativeExtensions = true;
1128	}
1129}
1130
1131Element.addMethods();
1132
1133var Toggle = new Object();
1134Toggle.display = Element.toggle;
1135
1136/*--------------------------------------------------------------------------*/
1137
1138Abstract.Insertion = function(adjacency) {
1139	this.adjacency = adjacency;
1140}
1141
1142Abstract.Insertion.prototype = {
1143	initialize: function(element, content) {
1144		this.element = $(element);
1145		this.content = content.stripScripts();
1146
1147		if (this.adjacency && this.element.insertAdjacentHTML) {
1148			try {
1149				this.element.insertAdjacentHTML(this.adjacency, this.content);
1150			} catch (e) {
1151				var tagName = this.element.tagName.toLowerCase();
1152				if (tagName == 'tbody' || tagName == 'tr') {
1153					this.insertContent(this.contentFromAnonymousTable());
1154				} else {
1155					throw e;
1156				}
1157			}
1158		} else {
1159			this.range = this.element.ownerDocument.createRange();
1160			if (this.initializeRange) this.initializeRange();
1161			this.insertContent([this.range.createContextualFragment(this.content)]);
1162		}
1163
1164		setTimeout(function() {content.evalScripts()}, 10);
1165	},
1166
1167	contentFromAnonymousTable: function() {
1168		var div = document.createElement('div');
1169		div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
1170		return $A(div.childNodes[0].childNodes[0].childNodes);
1171	}
1172}
1173
1174var Insertion = new Object();
1175
1176Insertion.Before = Class.create();
1177Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
1178	initializeRange: function() {
1179		this.range.setStartBefore(this.element);
1180	},
1181
1182	insertContent: function(fragments) {
1183		fragments.each((function(fragment) {
1184			this.element.parentNode.insertBefore(fragment, this.element);
1185		}).bind(this));
1186	}
1187});
1188
1189Insertion.Top = Class.create();
1190Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
1191	initializeRange: function() {
1192		this.range.selectNodeContents(this.element);
1193		this.range.collapse(true);
1194	},
1195
1196	insertContent: function(fragments) {
1197		fragments.reverse(false).each((function(fragment) {
1198			this.element.insertBefore(fragment, this.element.firstChild);
1199		}).bind(this));
1200	}
1201});
1202
1203Insertion.Bottom = Class.create();
1204Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
1205	initializeRange: function() {
1206		this.range.selectNodeContents(this.element);
1207		this.range.collapse(this.element);
1208	},
1209
1210	insertContent: function(fragments) {
1211		fragments.each((function(fragment) {
1212			this.element.appendChild(fragment);
1213		}).bind(this));
1214	}
1215});
1216
1217Insertion.After = Class.create();
1218Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
1219	initializeRange: function() {
1220		this.range.setStartAfter(this.element);
1221	},
1222
1223	insertContent: function(fragments) {
1224		fragments.each((function(fragment) {
1225			this.element.parentNode.insertBefore(fragment,
1226				this.element.nextSibling);
1227		}).bind(this));
1228	}
1229});
1230
1231/*--------------------------------------------------------------------------*/
1232
1233Element.ClassNames = Class.create();
1234Element.ClassNames.prototype = {
1235	initialize: function(element) {
1236		this.element = $(element);
1237	},
1238
1239	_each: function(iterator) {
1240		this.element.className.split(/\s+/).select(function(name) {
1241			return name.length > 0;
1242		})._each(iterator);
1243	},
1244
1245	set: function(className) {
1246		this.element.className = className;
1247	},
1248
1249	add: function(classNameToAdd) {
1250		if (this.include(classNameToAdd)) return;
1251		this.set(this.toArray().concat(classNameToAdd).join(' '));
1252	},
1253
1254	remove: function(classNameToRemove) {
1255		if (!this.include(classNameToRemove)) return;
1256		this.set(this.select(function(className) {
1257			return className != classNameToRemove;
1258		}).join(' '));
1259	},
1260
1261	toString: function() {
1262		return this.toArray().join(' ');
1263	}
1264}
1265
1266Object.extend(Element.ClassNames.prototype, Enumerable);
1267var Selector = Class.create();
1268Selector.prototype = {
1269	initialize: function(expression) {
1270		this.params = {classNames: []};
1271		this.expression = expression.toString().strip();
1272		this.parseExpression();
1273		this.compileMatcher();
1274	},
1275
1276	parseExpression: function() {
1277		function abort(message) { throw 'Parse error in selector: ' + message; }
1278
1279		if (this.expression == '')	abort('empty expression');
1280
1281		var params = this.params, expr = this.expression, match, modifier, clause, rest;
1282		while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
1283			params.attributes = params.attributes || [];
1284			params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
1285			expr = match[1];
1286		}
1287
1288		if (expr == '*') return this.params.wildcard = true;
1289
1290		while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
1291			modifier = match[1], clause = match[2], rest = match[3];
1292			switch (modifier) {
1293				case '#':			 params.id = clause; break;
1294				case '.':			 params.classNames.push(clause); break;
1295				case '':
1296				case undefined: params.tagName = clause.toUpperCase(); break;
1297				default:				abort(expr.inspect());
1298			}
1299			expr = rest;
1300		}
1301
1302		if (expr.length > 0) abort(expr.inspect());
1303	},
1304
1305	buildMatchExpression: function() {
1306		var params = this.params, conditions = [], clause;
1307
1308		if (params.wildcard)
1309			conditions.push('true');
1310		if (clause = params.id)
1311			conditions.push('element.id == ' + clause.inspect());
1312		if (clause = params.tagName)
1313			conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
1314		if ((clause = params.classNames).length > 0)
1315			for (var i = 0; i < clause.length; i++)
1316				conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')');
1317		if (clause = params.attributes) {
1318			clause.each(function(attribute) {
1319				var value = 'element.getAttribute(' + attribute.name.inspect() + ')';
1320				var splitValueBy = function(delimiter) {
1321					return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
1322				}
1323
1324				switch (attribute.operator) {
1325					case '=':			 conditions.push(value + ' == ' + attribute.value.inspect()); break;
1326					case '~=':			conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
1327					case '|=':			conditions.push(
1328														splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
1329													); break;
1330					case '!=':			conditions.push(value + ' != ' + attribute.value.inspect()); break;
1331					case '':
1332					case undefined: conditions.push(value + ' != null'); break;
1333					default:				throw 'Unknown operator ' + attribute.operator + ' in selector';
1334				}
1335			});
1336		}
1337
1338		return conditions.join(' && ');
1339	},
1340
1341	compileMatcher: function() {
1342		this.match = new Function('element', 'if (!element.tagName) return false; \
1343			return ' + this.buildMatchExpression());
1344	},
1345
1346	findElements: function(scope) {
1347		var element;
1348
1349		if (element = $(this.params.id))
1350			if (this.match(element))
1351				if (!scope || Element.childOf(element, scope))
1352					return [element];
1353
1354		scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
1355
1356		var results = [];
1357		for (var i = 0; i < scope.length; i++)
1358			if (this.match(element = scope[i]))
1359				results.push(Element.extend(element));
1360
1361		return results;
1362	},
1363
1364	toString: function() {
1365		return this.expression;
1366	}
1367}
1368
1369function $$() {
1370	return $A(arguments).map(function(expression) {
1371		return expression.strip().split(/\s+/).inject([null], function(results, expr) {
1372			var selector = new Selector(expr);
1373			return results.map(selector.findElements.bind(selector)).flatten();
1374		});
1375	}).flatten();
1376}
1377var Field = {
1378	clear: function() {
1379		for (var i = 0; i < arguments.length; i++)
1380			$(arguments[i]).value = '';
1381	},
1382
1383	focus: function(element) {
1384		$(element).focus();
1385	},
1386
1387	present: function() {
1388		for (var i = 0; i < arguments.length; i++)
1389			if ($(arguments[i]).value == '') return false;
1390		return true;
1391	},
1392
1393	select: function(element) {
1394		$(element).select();
1395	},
1396
1397	activate: function(element) {
1398		element = $(element);
1399		element.focus();
1400		if (element.select)
1401			element.select();
1402	}
1403}
1404
1405/*--------------------------------------------------------------------------*/
1406
1407var Form = {
1408	serialize: function(form) {
1409		var elements = Form.getElements($(form));
1410		var queryComponents = new Array();
1411
1412		for (var i = 0; i < elements.length; i++) {
1413			var queryComponent = Form.Element.serialize(elements[i]);
1414			if (queryComponent)
1415				queryComponents.push(queryComponent);
1416		}
1417
1418		return queryComponents.join('&');
1419	},
1420
1421	getElements: function(form) {
1422		form = $(form);
1423		var elements = new Array();
1424
1425		for (var tagName in Form.Element.Serializers) {
1426			var tagElements = form.getElementsByTagName(tagName);
1427			for (var j = 0; j < tagElements.length; j++)
1428				elements.push(tagElements[j]);
1429		}
1430		return elements;
1431	},
1432
1433	getInputs: function(form, typeName, name) {
1434		form = $(form);
1435		var inputs = form.getElementsByTagName('input');
1436
1437		if (!typeName && !name)
1438			return inputs;
1439
1440		var matchingInputs = new Array();
1441		for (var i = 0; i < inputs.length; i++) {
1442			var input = inputs[i];
1443			if ((typeName && input.type != typeName) ||
1444					(name && input.name != name))
1445				continue;
1446			matchingInputs.push(input);
1447		}
1448
1449		return matchingInputs;
1450	},
1451
1452	disable: function(form) {
1453		var elements = Form.getElements(form);
1454		for (var i = 0; i < elements.length; i++) {
1455			var element = elements[i];
1456			element.blur();
1457			element.disabled = 'true';
1458		}
1459	},
1460
1461	enable: function(form) {
1462		var elements = Form.getElements(form);
1463		for (var i = 0; i < elements.length; i++) {
1464			var element = elements[i];
1465			element.disabled = '';
1466		}
1467	},
1468
1469	findFirstElement: function(form) {
1470		return Form.getElements(form).find(function(element) {
1471			return element.type != 'hidden' && !element.disabled &&
1472				['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
1473		});
1474	},
1475
1476	focusFirstElement: function(form) {
1477		Field.activate(Form.findFirstElement(form));
1478	},
1479
1480	reset: function(form) {
1481		$(form).reset();
1482	}
1483}
1484
1485Form.Element = {
1486	serialize: function(element) {
1487		element = $(element);
1488		var method = element.tagName.toLowerCase();
1489		var parameter = Form.Element.Serializers[method](element);
1490
1491		if (parameter) {
1492			var key = encodeURIComponent(parameter[0]);
1493			if (key.length == 0) return;
1494
1495			if (parameter[1].constructor != Array)
1496				parameter[1] = [parameter[1]];
1497
1498			return parameter[1].map(function(value) {
1499				return key + '=' + encodeURIComponent(value);
1500			}).join('&');
1501		}
1502	},
1503
1504	getValue: function(element) {
1505		element = $(element);
1506		var method = element.tagName.toLowerCase();
1507		var parameter = Form.Element.Serializers[method](element);
1508
1509		if (parameter)
1510			return parameter[1];
1511	}
1512}
1513
1514Form.Element.Serializers = {
1515	input: function(element) {
1516		switch (element.type.toLowerCase()) {
1517			case 'submit':
1518			case 'hidden':
1519			case 'password':
1520			case 'text':
1521				return Form.Element.Serializers.textarea(element);
1522			case 'checkbox':
1523			case 'radio':
1524				return Form.Element.Serializers.inputSelector(element);
1525		}
1526		return false;
1527	},
1528
1529	inputSelector: function(element) {
1530		if (element.checked)
1531			return [element.name, element.value];
1532	},
1533
1534	textarea: function(element) {
1535		return [element.name, element.value];
1536	},
1537
1538	select: function(element) {
1539		return Form.Element.Serializers[element.type == 'select-one' ?
1540			'selectOne' : 'selectMany'](element);
1541	},
1542
1543	selectOne: function(element) {
1544		var value = '', opt, index = element.selectedIndex;
1545		if (index >= 0) {
1546			opt = element.options[index];
1547			value = opt.value || opt.text;
1548		}
1549		return [element.name, value];
1550	},
1551
1552	selectMany: function(element) {
1553		var value = [];
1554		for (var i = 0; i < element.length; i++) {
1555			var opt = element.options[i];
1556			if (opt.selected)
1557				value.push(opt.value || opt.text);
1558		}
1559		return [element.name, value];
1560	}
1561}
1562
1563/*--------------------------------------------------------------------------*/
1564
1565var $F = Form.Element.getValue;
1566
1567/*--------------------------------------------------------------------------*/
1568
1569Abstract.TimedObserver = function() {}
1570Abstract.TimedObserver.prototype = {
1571	initialize: function(element, frequency, callback) {
1572		this.frequency = frequency;
1573		this.element	 = $(element);
1574		this.callback	= callback;
1575
1576		this.lastValue = this.getValue();
1577		this.registerCallback();
1578	},
1579
1580	registerCallback: function() {
1581		setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
1582	},
1583
1584	onTimerEvent: function() {
1585		var value = this.getValue();
1586		if (this.lastValue != value) {
1587			this.callback(this.element, value);
1588			this.lastValue = value;
1589		}
1590	}
1591}
1592
1593Form.Element.Observer = Class.create();
1594Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
1595	getValue: function() {
1596		return Form.Element.getValue(this.element);
1597	}
1598});
1599
1600Form.Observer = Class.create();
1601Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
1602	getValue: function() {
1603		return Form.serialize(this.element);
1604	}
1605});
1606
1607/*--------------------------------------------------------------------------*/
1608
1609Abstract.EventObserver = function() {}
1610Abstract.EventObserver.prototype = {
1611	initialize: function(element, callback) {
1612		this.element	= $(element);
1613		this.callback = callback;
1614
1615		this.lastValue = this.getValue();
1616		if (this.element.tagName.toLowerCase() == 'form')
1617			this.registerFormCallbacks();
1618		else
1619			this.registerCallback(this.element);
1620	},
1621
1622	onElementEvent: function() {
1623		var value = this.getValue();
1624		if (this.lastValue != value) {
1625			this.callback(this.element, value);
1626			this.lastValue = value;
1627		}
1628	},
1629
1630	registerFormCallbacks: function() {
1631		var elements = Form.getElements(this.element);
1632		for (var i = 0; i < elements.length; i++)
1633			this.registerCallback(elements[i]);
1634	},
1635
1636	registerCallback: function(element) {
1637		if (element.type) {
1638			switch (element.type.toLowerCase()) {
1639				case 'checkbox':
1640				case 'radio':
1641					Event.observe(element, 'click', this.onElementEvent.bind(this));
1642					break;
1643				case 'password':
1644				case 'text':
1645				case 'textarea':
1646				case 'select-one':
1647				case 'select-multiple':
1648					Event.observe(element, 'change', this.onElementEvent.bind(this));
1649					break;
1650			}
1651		}
1652	}
1653}
1654
1655Form.Element.EventObserver = Class.create();
1656Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
1657	getValue: function() {
1658		return Form.Element.getValue(this.element);
1659	}
1660});
1661
1662Form.EventObserver = Class.create();
1663Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
1664	getValue: function() {
1665		return Form.serialize(this.element);
1666	}
1667});
1668if (!window.Event) {
1669	var Event = new Object();
1670}
1671
1672Object.extend(Event, {
1673	KEY_BACKSPACE: 8,
1674	KEY_TAB:			 9,
1675	KEY_RETURN:	 13,
1676	KEY_ESC:			27,
1677	KEY_LEFT:		 37,
1678	KEY_UP:			 38,
1679	KEY_RIGHT:		39,
1680	KEY_DOWN:		 40,
1681	KEY_DELETE:	 46,
1682
1683	element: function(event) {
1684		return event.target || event.srcElement;
1685	},
1686
1687	isLeftClick: function(event) {
1688		return (((event.which) && (event.which == 1)) ||
1689						((event.button) && (event.button == 1)));
1690	},
1691
1692	pointerX: function(event) {
1693		return event.pageX || (event.clientX +
1694			(document.documentElement.scrollLeft || document.body.scrollLeft));
1695	},
1696
1697	pointerY: function(event) {
1698		return event.pageY || (event.clientY +
1699			(document.documentElement.scrollTop || document.body.scrollTop));
1700	},
1701
1702	stop: function(event) {
1703		if (event.preventDefault) {
1704			event.preventDefault();
1705			event.stopPropagation();
1706		} else {
1707			event.returnValue = false;
1708			event.cancelBubble = true;
1709		}
1710	},
1711
1712	// find the first node with the given tagName, starting from the
1713	// node the event was triggered on; traverses the DOM upwards
1714	findElement: function(event, tagName) {
1715		var element = Event.element(event);
1716		while (element.parentNode && (!element.tagName ||
1717				(element.tagName.toUpperCase() != tagName.toUpperCase())))
1718			element = element.parentNode;
1719		return element;
1720	},
1721
1722	observers: false,
1723
1724	_observeAndCache: function(element, name, observer, useCapture) {
1725		if (!this.observers) this.observers = [];
1726		if (element.addEventListener) {
1727			this.observers.push([element, name, observer, useCapture]);
1728			element.addEventListener(name, observer, useCapture);
1729		} else if (element.attachEvent) {
1730			this.observers.push([element, name, observer, useCapture]);
1731			element.attachEvent('on' + name, observer);
1732		}
1733	},
1734
1735	unloadCache: function() {
1736		if (!Event.observers) return;
1737		for (var i = 0; i < Event.observers.length; i++) {
1738			Event.stopObserving.apply(this, Event.observers[i]);
1739			Event.observers[i][0] = null;
1740		}
1741		Event.observers = false;
1742	},
1743
1744	observe: function(element, name, observer, useCapture) {
1745		var element = $(element);
1746		useCapture = useCapture || false;
1747
1748		if (name == 'keypress' &&
1749				(navigator.appVersion.match(/Konqueror|Safari|KHTML/)
1750				|| element.attachEvent))
1751			name = 'keydown';
1752
1753		this._observeAndCache(element, name, observer, useCapture);
1754	},
1755
1756	stopObserving: function(element, name, observer, useCapture) {
1757		var element = $(element);
1758		useCapture = useCapture || false;
1759
1760		if (name == 'keypress' &&
1761				(navigator.appVersion.match(/Konqueror|Safari|KHTML/)
1762				|| element.detachEvent))
1763			name = 'keydown';
1764
1765		if (element.removeEventListener) {
1766			element.removeEventListener(name, observer, useCapture);
1767		} else if (element.detachEvent) {
1768			try {
1769				element.detachEvent('on' + name, observer);
1770			} catch (e) {}
1771		}
1772	}
1773});
1774
1775/* prevent memory leaks in IE */
1776if (navigator.appVersion.match(/\bMSIE\b/))
1777	Event.observe(window, 'unload', Event.unloadCache, false);
1778var Position = {
1779	// set to true if needed, warning: firefox performance problems
1780	// NOT neeeded for page scrolling, only if draggable contained in
1781	// scrollable elements
1782	includeScrollOffsets: false,
1783
1784	// must be called before calling withinIncludingScrolloffset, every time the
1785	// page is scrolled
1786	prepare: function() {
1787		this.deltaX =	window.pageXOffset
1788								|| document.documentElement.scrollLeft
1789								|| document.body.scrollLeft
1790								|| 0;
1791		this.deltaY =	window.pageYOffset
1792								|| document.documentElement.scrollTop
1793								|| document.body.scrollTop
1794								|| 0;
1795	},
1796
1797	realOffset: function(element) {
1798		var valueT = 0, valueL = 0;
1799		do {
1800			valueT += element.scrollTop	|| 0;
1801			valueL += element.scrollLeft || 0;
1802			element = element.parentNode;
1803		} while (element);
1804		return [valueL, valueT];
1805	},
1806
1807	cumulativeOffset: function(element) {
1808		var valueT = 0, valueL = 0;
1809		do {
1810			valueT += element.offsetTop	|| 0;
1811			valueL += element.offsetLeft || 0;
1812			element = element.offsetParent;
1813		} while (element);
1814		return [valueL, valueT];
1815	},
1816
1817	positionedOffset: function(element) {
1818		var valueT = 0, valueL = 0;
1819		do {
1820			valueT += element.offsetTop	|| 0;
1821			valueL += element.offsetLeft || 0;
1822			element = element.offsetParent;
1823			if (element) {
1824				p = Element.getStyle(element, 'position');
1825				if (p == 'relative' || p == 'absolute') break;
1826			}
1827		} while (element);
1828		return [valueL, valueT];
1829	},
1830
1831	offsetParent: function(element) {
1832		if (element.offsetParent) return element.offsetParent;
1833		if (element == document.body) return element;
1834
1835		while ((element = element.parentNode) && element != document.body)
1836			if (Element.getStyle(element, 'position') != 'static')
1837				return element;
1838
1839		return document.body;
1840	},
1841
1842	// caches x/y coordinate pair to use with overlap
1843	within: function(element, x, y) {
1844		if (this.includeScrollOffsets)
1845			return this.withinIncludingScrolloffsets(element, x, y);
1846		this.xcomp = x;
1847		this.ycomp = y;
1848		this.offset = this.cumulativeOffset(element);
1849
1850		return (y >= this.offset[1] &&
1851						y <	this.offset[1] + element.offsetHeight &&
1852						x >= this.offset[0] &&
1853						x <	this.offset[0] + element.offsetWidth);
1854	},
1855
1856	withinIncludingScrolloffsets: function(element, x, y) {
1857		var offsetcache = this.realOffset(element);
1858
1859		this.xcomp = x + offsetcache[0] - this.deltaX;
1860		this.ycomp = y + offsetcache[1] - this.deltaY;
1861		this.offset = this.cumulativeOffset(element);
1862
1863		return (this.ycomp >= this.offset[1] &&
1864						this.ycomp <	this.offset[1] + element.offsetHeight &&
1865						this.xcomp >= this.offset[0] &&
1866						this.xcomp <	this.offset[0] + element.offsetWidth);
1867	},
1868
1869	// within must be called directly before
1870	overlap: function(mode, element) {
1871		if (!mode) return 0;
1872		if (mode == 'vertical')
1873			return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
1874				element.offsetHeight;
1875		if (mode == 'horizontal')
1876			return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
1877				element.offsetWidth;
1878	},
1879
1880	clone: function(source, target) {
1881		source = $(source);
1882		target = $(target);
1883		target.style.position = 'absolute';
1884		var offsets = this.cumulativeOffset(source);
1885		target.style.top		= offsets[1] + 'px';
1886		target.style.left	 = offsets[0] + 'px';
1887		target.style.width	= source.offsetWidth + 'px';
1888		target.style.height = source.offsetHeight + 'px';
1889	},
1890
1891	page: function(forElement) {
1892		var valueT = 0, valueL = 0;
1893
1894		var element = forElement;
1895		do {
1896			valueT += element.offsetTop	|| 0;
1897			valueL += element.offsetLeft || 0;
1898
1899			// Safari fix
1900			if (element.offsetParent==document.body)
1901				if (Element.getStyle(element,'position')=='absolute') break;
1902
1903		} while (element = element.offsetParent);
1904
1905		element = forElement;
1906		do {
1907			valueT -= element.scrollTop	|| 0;
1908			valueL -= element.scrollLeft || 0;
1909		} while (element = element.parentNode);
1910
1911		return [valueL, valueT];
1912	},
1913
1914	clone: function(source, target) {
1915		var options = Object.extend({
1916			setLeft:		true,
1917			setTop:		 true,
1918			setWidth:	 true,
1919			setHeight:	true,
1920			offsetTop:	0,
1921			offsetLeft: 0
1922		}, arguments[2] || {})
1923
1924		// find page position of source
1925		source = $(source);
1926		var p = Position.page(source);
1927
1928		// find coordinate system to use
1929		target = $(target);
1930		var delta = [0, 0];
1931		var parent = null;
1932		// delta [0,0] will do fine with position: fixed elements,
1933		// position:absolute needs offsetParent deltas
1934		if (Element.getStyle(target,'position') == 'absolute') {
1935			parent = Position.offsetParent(target);
1936			delta = Position.page(parent);
1937		}
1938
1939		// correct by body offsets (fixes Safari)
1940		if (parent == document.body) {
1941			delta[0] -= document.body.offsetLeft;
1942			delta[1] -= document.body.offsetTop;
1943		}
1944
1945		// set position
1946		if(options.setLeft)	 target.style.left	= (p[0] - delta[0] + options.offsetLeft) + 'px';
1947		if(options.setTop)		target.style.top	 = (p[1] - delta[1] + options.offsetTop) + 'px';
1948		if(options.setWidth)	target.style.width = source.offsetWidth + 'px';
1949		if(options.setHeight) target.style.height = source.offsetHeight + 'px';
1950	},
1951
1952	absolutize: function(element) {
1953		element = $(element);
1954		if (element.style.position == 'absolute') return;
1955		Position.prepare();
1956
1957		var offsets = Position.positionedOffset(element);
1958		var top		 = offsets[1];
1959		var left		= offsets[0];
1960		var width	 = element.clientWidth;
1961		var height	= element.clientHeight;
1962
1963		element._originalLeft	 = left - parseFloat(element.style.left	|| 0);
1964		element._originalTop		= top	- parseFloat(element.style.top || 0);
1965		element._originalWidth	= element.style.width;
1966		element._originalHeight = element.style.height;
1967
1968		element.style.position = 'absolute';
1969		element.style.top		= top + 'px';;
1970		element.style.left	 = left + 'px';;
1971		element.style.width	= width + 'px';;
1972		element.style.height = height + 'px';;
1973	},
1974
1975	relativize: function(element) {
1976		element = $(element);
1977		if (element.style.position == 'relative') return;
1978		Position.prepare();
1979
1980		element.style.position = 'relative';
1981		var top	= parseFloat(element.style.top	|| 0) - (element._originalTop || 0);
1982		var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
1983
1984		element.style.top		= top + 'px';
1985		element.style.left	 = left + 'px';
1986		element.style.height = element._originalHeight;
1987		element.style.width	= element._originalWidth;
1988	}
1989}
1990
1991// Safari returns margins on body which is incorrect if the child is absolutely
1992// positioned.	For performance reasons, redefine Position.cumulativeOffset for
1993// KHTML/WebKit only.
1994if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
1995	Position.cumulativeOffset = function(element) {
1996		var valueT = 0, valueL = 0;
1997		do {
1998			valueT += element.offsetTop	|| 0;
1999			valueL += element.offsetLeft || 0;
2000			if (element.offsetParent == document.body)
2001				if (Element.getStyle(element, 'position') == 'absolute') break;
2002
2003			element = element.offsetParent;
2004		} while (element);
2005
2006		return [valueL, valueT];
2007	}
2008}

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.