PageSourceSearch

https://artershov.ru/js/mootools-more.js?202403181500

js artershov.ru collected 2026-10-08 13:54:08 UTC 32,394 bytes, 1,161 lines download raw bytes

1//MooTools More, <http://mootools.net/more>. Copyright (c) 2006-2009 Aaron Newton <http://clientcide.com/>, Valerio Proietti <http://mad4milk.net> & the MooTools team <http://mootools.net/developers>, MIT Style License.
2
3MooTools.More = {
4	'version': '1.2.3.1'
5};
6
7/*
8Script: Log.js
9	Provides basic logging functionality for plugins to implement.
10
11	License:
12		MIT-style license.
13
14	Authors:
15		Guillermo Rauch
16*/
17
18var Log = new Class({
19	
20	log: function(){
21		Log.logger.call(this, arguments);
22	}
23	
24});
25
26Log.logged = [];
27
28Log.logger = function(){
29	if(window.console && console.log) console.log.apply(console, arguments);
30	else Log.logged.push(arguments);
31};
32
33/*
34Script: Class.Refactor.js
35	Extends a class onto itself with new property, preserving any items attached to the class's namespace.
36
37	License:
38		MIT-style license.
39
40	Authors:
41		Aaron Newton
42*/
43
44Class.refactor = function(original, refactors){
45
46	$each(refactors, function(item, name){
47		var origin = original.prototype[name];
48		if (origin && (origin = origin._origin) && typeof item == 'function') original.implement(name, function(){
49			var old = this.previous;
50			this.previous = origin;
51			var value = item.apply(this, arguments);
52			this.previous = old;
53			return value;
54		}); else original.implement(name, item);
55	});
56
57	return original;
58
59};
60
61/*
62Script: Class.Binds.js
63	Automagically binds specified methods in a class to the instance of the class.
64
65	License:
66		MIT-style license.
67
68	Authors:
69		Aaron Newton
70*/
71
72Class.Mutators.Binds = function(binds){
73    return binds;
74};
75
76Class.Mutators.initialize = function(initialize){
77	return function(){
78		$splat(this.Binds).each(function(name){
79			var original = this[name];
80			if (original) this[name] = original.bind(this);
81		}, this);
82		return initialize.apply(this, arguments);
83	};
84};
85
86/*
87Script: Drag.js
88	The base Drag Class. Can be used to drag and resize Elements using mouse events.
89
90	License:
91		MIT-style license.
92
93	Authors:
94		Valerio Proietti
95		Tom Occhinno
96		Jan Kassens
97*/
98
99var Drag = new Class({
100
101	Implements: [Events, Options],
102
103	options: {/*
104		onBeforeStart: $empty(thisElement),
105		onStart: $empty(thisElement, event),
106		onSnap: $empty(thisElement)
107		onDrag: $empty(thisElement, event),
108		onCancel: $empty(thisElement),
109		onComplete: $empty(thisElement, event),*/
110		snap: 6,
111		unit: 'px',
112		grid: false,
113		style: true,
114		limit: false,
115		handle: false,
116		invert: false,
117		preventDefault: false,
118		modifiers: {x: 'left', y: 'top'}
119	},
120
121	initialize: function(){
122		var params = Array.link(arguments, {'options': Object.type, 'element': $defined});
123		this.element = document.id(params.element);
124		this.document = this.element.getDocument();
125		this.setOptions(params.options || {});
126		var htype = $type(this.options.handle);
127		this.handles = ((htype == 'array' || htype == 'collection') ? $$(this.options.handle) : document.id(this.options.handle)) || this.element;
128		this.mouse = {'now': {}, 'pos': {}};
129		this.value = {'start': {}, 'now': {}};
130
131		this.selection = (Browser.Engine.trident) ? 'selectstart' : 'mousedown';
132
133		this.bound = {
134			start: this.start.bind(this),
135			check: this.check.bind(this),
136			drag: this.drag.bind(this),
137			stop: this.stop.bind(this),
138			cancel: this.cancel.bind(this),
139			eventStop: $lambda(false)
140		};
141		this.attach();
142	},
143
144	attach: function(){
145		this.handles.addEvent('mousedown', this.bound.start);
146		return this;
147	},
148
149	detach: function(){
150		this.handles.removeEvent('mousedown', this.bound.start);
151		return this;
152	},
153
154	start: function(event){
155		if (this.options.preventDefault) event.preventDefault();
156		this.mouse.start = event.page;
157		this.fireEvent('beforeStart', this.element);
158		var limit = this.options.limit;
159		this.limit = {x: [], y: []};
160		for (var z in this.options.modifiers){
161			if (!this.options.modifiers[z]) continue;
162			if (this.options.style) this.value.now[z] = this.element.getStyle(this.options.modifiers[z]).toInt();
163			else this.value.now[z] = this.element[this.options.modifiers[z]];
164			if (this.options.invert) this.value.now[z] *= -1;
165			this.mouse.pos[z] = event.page[z] - this.value.now[z];
166			if (limit && limit[z]){
167				for (var i = 2; i--; i){
168					if ($chk(limit[z][i])) this.limit[z][i] = $lambda(limit[z][i])();
169				}
170			}
171		}
172		if ($type(this.options.grid) == 'number') this.options.grid = {x: this.options.grid, y: this.options.grid};
173		this.document.addEvents({mousemove: this.bound.check, mouseup: this.bound.cancel});
174		this.document.addEvent(this.selection, this.bound.eventStop);
175	},
176
177	check: function(event){
178		if (this.options.preventDefault) event.preventDefault();
179		var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2)));
180		if (distance > this.options.snap){
181			this.cancel();
182			this.document.addEvents({
183				mousemove: this.bound.drag,
184				mouseup: this.bound.stop
185			});
186			this.fireEvent('start', [this.element, event]).fireEvent('snap', this.element);
187		}
188	},
189
190	drag: function(event){
191		if (this.options.preventDefault) event.preventDefault();
192		this.mouse.now = event.page;
193		for (var z in this.options.modifiers){
194			if (!this.options.modifiers[z]) continue;
195			this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z];
196			if (this.options.invert) this.value.now[z] *= -1;
197			if (this.options.limit && this.limit[z]){
198				if ($chk(this.limit[z][1]) && (this.value.now[z] > this.limit[z][1])){
199					this.value.now[z] = this.limit[z][1];
200				} else if ($chk(this.limit[z][0]) && (this.value.now[z] < this.limit[z][0])){
201					this.value.now[z] = this.limit[z][0];
202				}
203			}
204			if (this.options.grid[z]) this.value.now[z] -= ((this.value.now[z] - (this.limit[z][0]||0)) % this.options.grid[z]);
205			if (this.options.style) this.element.setStyle(this.options.modifiers[z], this.value.now[z] + this.options.unit);
206			else this.element[this.options.modifiers[z]] = this.value.now[z];
207		}
208        
209		this.fireEvent('drag', [this.element, event]);
210	},
211
212	cancel: function(event){
213		this.document.removeEvent('mousemove', this.bound.check);
214		this.document.removeEvent('mouseup', this.bound.cancel);
215		if (event){
216			this.document.removeEvent(this.selection, this.bound.eventStop);
217			this.fireEvent('cancel', this.element);
218		}
219	},
220
221	stop: function(event){
222		this.document.removeEvent(this.selection, this.bound.eventStop);
223		this.document.removeEvent('mousemove', this.bound.drag);
224		this.document.removeEvent('mouseup', this.bound.stop);
225		if (event) this.fireEvent('complete', [this.element, event]);
226	}
227
228});
229
230Element.implement({
231
232	makeResizable: function(options){
233		var drag = new Drag(this, $merge({modifiers: {x: 'width', y: 'height'}}, options));
234		this.store('resizer', drag);
235		return drag.addEvent('drag', function(){
236			this.fireEvent('resize', drag);
237		}.bind(this));
238	}
239
240});
241
242
243/*
244Script: Drag.Move.js
245	A Drag extension that provides support for the constraining of draggables to containers and droppables.
246
247	License:
248		MIT-style license.
249
250	Authors:
251		Valerio Proietti
252		Tom Occhinno
253		Jan Kassens*/
254
255Drag.Move = new Class({
256
257	Extends: Drag,
258
259	options: {/*
260		onEnter: $empty(thisElement, overed),
261		onLeave: $empty(thisElement, overed),
262		onDrop: $empty(thisElement, overed, event),*/
263		droppables: [],
264		container: false,
265		precalculate: false,
266		includeMargins: true,
267		checkDroppables: true
268	},
269
270	initialize: function(element, options){
271		this.parent(element, options);
272		this.droppables = $$(this.options.droppables);
273		this.container = document.id(this.options.container);
274		if (this.container && $type(this.container) != 'element') this.container = document.id(this.container.getDocument().body);
275
276		var position = this.element.getStyle('position');
277		if (position=='static') position = 'absolute';
278		if ([this.element.getStyle('left'), this.element.getStyle('top')].contains('auto')) this.element.position(this.element.getPosition(this.element.offsetParent));
279		this.element.setStyle('position', position);
280
281		this.addEvent('start', this.checkDroppables, true);
282
283		this.overed = null;
284	},
285
286	start: function(event){
287		if (this.container){
288			var ccoo = this.container.getCoordinates(this.element.getOffsetParent()), cbs = {}, ems = {};
289
290			['top', 'right', 'bottom', 'left'].each(function(pad){
291				cbs[pad] = this.container.getStyle('border-' + pad).toInt();
292				ems[pad] = this.element.getStyle('margin-' + pad).toInt();
293			}, this);
294
295			var width = this.element.offsetWidth + ems.left + ems.right;
296			var height = this.element.offsetHeight + ems.top + ems.bottom;
297
298			if (this.options.includeMargins) {
299				$each(ems, function(value, key) {
300					ems[key] = 0;
301				});
302			}
303			if (this.container == this.element.getOffsetParent()) {
304				this.options.limit = {
305					x: [0 - ems.left, ccoo.right - cbs.left - cbs.right - width + ems.right],
306					y: [0 - ems.top, ccoo.bottom - cbs.top - cbs.bottom - height + ems.bottom]
307				};
308			} else {
309				this.options.limit = {
310					x: [ccoo.left + cbs.left - ems.left, ccoo.right - cbs.right - width + ems.right],
311					y: [ccoo.top + cbs.top - ems.top, ccoo.bottom - cbs.bottom - height + ems.bottom]
312				};
313			}
314
315		}
316		if (this.options.precalculate){
317			this.positions = this.droppables.map(function(el) {
318				return el.getCoordinates();
319			});
320		}
321		this.parent(event);
322	},
323
324	checkAgainst: function(el, i){
325		el = (this.positions) ? this.positions[i] : el.getCoordinates();
326		var now = this.mouse.now;
327		return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top);
328	},
329
330	checkDroppables: function(){
331		var overed = this.droppables.filter(this.checkAgainst, this).getLast();
332		if (this.overed != overed){
333			if (this.overed) this.fireEvent('leave', [this.element, this.overed]);
334			if (overed) this.fireEvent('enter', [this.element, overed]);
335			this.overed = overed;
336		}
337	},
338
339	drag: function(event){
340		this.parent(event);
341		if (this.options.checkDroppables && this.droppables.length) this.checkDroppables();
342	},
343
344	stop: function(event){
345		this.checkDroppables();
346		this.fireEvent('drop', [this.element, this.overed, event]);
347		this.overed = null;
348		return this.parent(event);
349	}
350
351});
352
353Element.implement({
354
355	makeDraggable: function(options){
356		var drag = new Drag.Move(this, options);
357		this.store('dragger', drag);
358		return drag;
359	}
360
361});
362
363
364/*
365Script: Slider.js
366	Class for creating horizontal and vertical slider controls.
367
368	License:
369		MIT-style license.
370
371	Authors:
372		Valerio Proietti
373*/
374
375var Slider = new Class({
376
377	Implements: [Events, Options],
378
379	Binds: ['clickedElement', 'draggedKnob', 'scrolledElement'],
380
381	options: {/*
382		onTick: $empty(intPosition),
383		onChange: $empty(intStep),
384		onComplete: $empty(strStep),*/
385		onTick: function(position){
386			if (this.options.snap) position = this.toPosition(this.step);
387			this.knob.setStyle(this.property, position);
388		},
389		snap: false,
390		offset: 0,
391		range: false,
392		wheel: false,
393		steps: 100,
394		mode: 'horizontal'
395	},
396
397	initialize: function(element, knob, options){
398		this.setOptions(options);
399		this.element = document.id(element);
400		this.knob = document.id(knob);
401		this.previousChange = this.previousEnd = this.step = -1;
402		var offset, limit = {}, modifiers = {'x': false, 'y': false};
403		switch (this.options.mode){
404			case 'vertical':
405				this.axis = 'y';
406				this.property = 'top';
407				offset = 'offsetHeight';
408				break;
409			case 'horizontal':
410				this.axis = 'x';
411				this.property = 'left';
412				offset = 'offsetWidth';
413		}
414
415		this.half = this.knob[offset] / 2;
416		this.full = this.element[offset] - this.knob[offset] + (this.options.offset * 2);
417		this.min = $chk(this.options.range[0]) ? this.options.range[0] : 0;
418		this.max = $chk(this.options.range[1]) ? this.options.range[1] : this.options.steps;
419		this.range = this.max - this.min;
420		this.steps = this.options.steps || this.full;
421		this.stepSize = Math.abs(this.range) / this.steps;
422		this.stepWidth = this.stepSize * this.full / Math.abs(this.range) ;
423
424		this.knob.setStyle('position', 'relative').setStyle(this.property, - this.options.offset);
425		modifiers[this.axis] = this.property;
426		limit[this.axis] = [- this.options.offset, this.full - this.options.offset];
427
428		this.bound = {
429			clickedElement: this.clickedElement.bind(this),
430			scrolledElement: this.scrolledElement.bindWithEvent(this),
431			draggedKnob: this.draggedKnob.bind(this)
432		};
433
434		var dragOptions = {
435			snap: 0,
436			limit: limit,
437			modifiers: modifiers,
438			onDrag: (function(){
439				this.draggedKnob();
440				this.end();
441			}).bind(this),//this.bound.draggedKnob,
442			onStart: this.bound.draggedKnob,
443			onBeforeStart: (function(){
444				this.isDragging = true;
445			}).bind(this),
446			onComplete: function(){
447				this.isDragging = false;
448				this.draggedKnob();
449				this.end();
450			}.bind(this)
451		};
452		if (this.options.snap){
453			dragOptions.grid = Math.ceil(this.stepWidth);
454			dragOptions.limit[this.axis][1] = this.full;
455		}
456
457		this.drag = new Drag(this.knob, dragOptions);
458		this.attach();
459	},
460
461	attach: function(){
462		this.element.addEvent('mousedown', this.bound.clickedElement);
463		if (this.options.wheel) this.element.addEvent('mousewheel', this.bound.scrolledElement);
464		this.drag.attach();
465		return this;
466	},
467
468	detach: function(){
469		this.element.removeEvent('mousedown', this.bound.clickedElement);
470		this.element.removeEvent('mousewheel', this.bound.scrolledElement);
471		this.drag.detach();
472		return this;
473	},
474
475	set: function(step){
476		if (!((this.range > 0) ^ (step < this.min))) step = this.min;
477		if (!((this.range > 0) ^ (step > this.max))) step = this.max;
478
479		this.step = Math.round(step);
480		this.checkStep();
481		this.fireEvent('tick', this.toPosition(this.step));
482		this.end();
483		return this;
484	},
485
486	clickedElement: function(event){
487		if (this.isDragging || event.target == this.knob) return;
488
489		var dir = this.range < 0 ? -1 : 1;
490		var position = event.page[this.axis] - this.element.getPosition()[this.axis] - this.half;
491		position = position.limit(-this.options.offset, this.full -this.options.offset);
492
493		this.step = Math.round(this.min + dir * this.toStep(position));
494		this.checkStep();
495		this.fireEvent('tick', position);
496		this.end();
497	},
498
499	scrolledElement: function(event){
500		var mode = (this.options.mode == 'horizontal') ? (event.wheel < 0) : (event.wheel > 0);
501		this.set(mode ? this.step - this.stepSize : this.step + this.stepSize);
502		event.stop();
503	},
504
505	draggedKnob: function(){
506		var dir = this.range < 0 ? -1 : 1;
507		var position = this.drag.value.now[this.axis];
508		position = position.limit(-this.options.offset, this.full -this.options.offset);
509		this.step = Math.round(this.min + dir * this.toStep(position));
510		this.checkStep();
511	},
512
513	checkStep: function(){
514		if (this.previousChange != this.step){
515			this.previousChange = this.step;
516			this.fireEvent('change', this.step);
517		}
518	},
519
520	end: function(){
521		if (this.previousEnd !== this.step){
522			this.previousEnd = this.step;
523			this.fireEvent('complete', this.step + '');
524		}
525	},
526
527	toStep: function(position){
528		var step = (position + this.options.offset) * this.stepSize / this.full * this.steps;
529		return this.options.steps ? Math.round(step -= step % this.stepSize) : step;
530	},
531
532	toPosition: function(step){
533		return (this.full * Math.abs(this.min - step)) / (this.steps * this.stepSize) - this.options.offset;
534	}
535
536});
537
538/*
539Script: Sortables.js
540	Class for creating a drag and drop sorting interface for lists of items.
541
542	License:
543		MIT-style license.
544
545	Authors:
546		Tom Occhino
547*/
548
549var Sortables = new Class({
550
551	Implements: [Events, Options],
552
553	options: {/*
554		onSort: $empty(element, clone),
555		onStart: $empty(element, clone),
556		onComplete: $empty(element),*/
557		snap: 4,
558		opacity: 1,
559		clone: false,
560		revert: false,
561		handle: false,
562		constrain: false
563	},
564
565	initialize: function(lists, options){
566		this.setOptions(options);
567		this.elements = [];
568		this.lists = [];
569		this.idle = true;
570
571		this.addLists($$(document.id(lists) || lists));
572		if (!this.options.clone) this.options.revert = false;
573		if (this.options.revert) this.effect = new Fx.Morph(null, $merge({duration: 250, link: 'cancel'}, this.options.revert));
574	},
575
576	attach: function(){
577		this.addLists(this.lists);
578		return this;
579	},
580
581	detach: function(){
582		this.lists = this.removeLists(this.lists);
583		return this;
584	},
585
586	addItems: function(){
587		Array.flatten(arguments).each(function(element){
588			this.elements.push(element);
589			var start = element.retrieve('sortables:start', this.start.bindWithEvent(this, element));
590			(this.options.handle ? element.getElement(this.options.handle) || element : element).addEvent('mousedown', start);
591		}, this);
592		return this;
593	},
594
595	addLists: function(){
596		Array.flatten(arguments).each(function(list){
597			this.lists.push(list);
598			this.addItems(list.getChildren());
599		}, this);
600		return this;
601	},
602
603	removeItems: function(){
604		return $$(Array.flatten(arguments).map(function(element){
605			this.elements.erase(element);
606			var start = element.retrieve('sortables:start');
607			(this.options.handle ? element.getElement(this.options.handle) || element : element).removeEvent('mousedown', start);
608			
609			return element;
610		}, this));
611	},
612
613	removeLists: function(){
614		return $$(Array.flatten(arguments).map(function(list){
615			this.lists.erase(list);
616			this.removeItems(list.getChildren());
617			
618			return list;
619		}, this));
620	},
621
622	getClone: function(event, element){
623		if (!this.options.clone) return new Element('div').inject(document.body);
624		if ($type(this.options.clone) == 'function') return this.options.clone.call(this, event, element, this.list);
625		return element.clone(true).setStyles({
626			margin: '0px',
627			position: 'absolute',
628			visibility: 'hidden',
629			'width': element.getStyle('width')
630		}).inject(this.list).position(element.getPosition(element.getOffsetParent()));
631	},
632
633	getDroppables: function(){
634		var droppables = this.list.getChildren();
635		if (!this.options.constrain) droppables = this.lists.concat(droppables).erase(this.list);
636		return droppables.erase(this.clone).erase(this.element);
637	},
638
639	insert: function(dragging, element){
640		var where = 'inside';
641		if (this.lists.contains(element)){
642			this.list = element;
643			this.drag.droppables = this.getDroppables();
644		} else {
645			where = this.element.getAllPrevious().contains(element) ? 'before' : 'after';
646		}
647		this.element.inject(element, where);
648		this.fireEvent('sort', [this.element, this.clone]);
649	},
650
651	start: function(event, element){
652		if (!this.idle) return;
653		this.idle = false;
654		this.element = element;
655		this.opacity = element.get('opacity');
656		this.list = element.getParent();
657		this.clone = this.getClone(event, element);
658
659		this.drag = new Drag.Move(this.clone, {
660			snap: this.options.snap,
661			container: this.options.constrain && this.element.getParent(),
662			droppables: this.getDroppables(),
663			onSnap: function(){
664				event.stop();
665				this.clone.setStyle('visibility', 'visible');
666				this.element.set('opacity', this.options.opacity || 0);
667				this.fireEvent('start', [this.element, this.clone]);
668			}.bind(this),
669			onEnter: this.insert.bind(this),
670			onCancel: this.reset.bind(this),
671			onComplete: this.end.bind(this)
672		});
673
674		this.clone.inject(this.element, 'before');
675		this.drag.start(event);
676	},
677
678	end: function(){
679		this.drag.detach();
680		this.element.set('opacity', this.opacity);
681		if (this.effect){
682			var dim = this.element.getStyles('width', 'height');
683			var pos = this.clone.computePosition(this.element.getPosition(this.clone.offsetParent));
684			this.effect.element = this.clone;
685			this.effect.start({
686				top: pos.top,
687				left: pos.left,
688				width: dim.width,
689				height: dim.height,
690				opacity: 0.25
691			}).chain(this.reset.bind(this));
692		} else {
693			this.reset();
694		}
695	},
696
697	reset: function(){
698		this.idle = true;
699		this.clone.destroy();
700		this.fireEvent('complete', this.element);
701	},
702
703	serialize: function(){
704		var params = Array.link(arguments, {modifier: Function.type, index: $defined});
705		var serial = this.lists.map(function(list){
706			return list.getChildren().map(params.modifier || function(element){
707				return element.get('id');
708			}, this);
709		}, this);
710
711		var index = params.index;
712		if (this.lists.length == 1) index = 0;
713		return $chk(index) && index >= 0 && index < this.lists.length ? serial[index] : serial;
714	}
715
716});
717
718
719/*
720Script: Request.JSONP.js
721	Defines Request.JSONP, a class for cross domain javascript via script injection.
722
723	License:
724		MIT-style license.
725
726	Authors:
727		Aaron Newton
728		Guillermo Rauch
729*/
730
731Request.JSONP = new Class({
732
733	Implements: [Chain, Events, Options, Log],
734
735	options: {/*
736		onRetry: $empty(intRetries),
737		onRequest: $empty(scriptElement),
738		onComplete: $empty(data),
739		onSuccess: $empty(data),
740		onCancel: $empty(),*/
741		url: '',
742		data: {},
743		retries: 0,
744		timeout: 0,
745		link: 'ignore',
746		callbackKey: 'callback',
747		injectScript: document.head
748	},
749
750	initialize: function(options){
751		this.setOptions(options);
752		this.running = false;
753		this.requests = 0;
754		this.triesRemaining = [];
755	},
756
757	check: function(){
758		if (!this.running) return true;
759		switch (this.options.link){
760			case 'cancel': this.cancel(); return true;
761			case 'chain': this.chain(this.caller.bind(this, arguments)); return false;
762		}
763		return false;
764	},
765
766	send: function(options){
767		if (!$chk(arguments[1]) && !this.check(options)) return this;
768
769		var type = $type(options), old = this.options, index = $chk(arguments[1]) ? arguments[1] : this.requests++;
770		if (type == 'string' || type == 'element') options = {data: options};
771
772		options = $extend({data: old.data, url: old.url}, options);
773
774		if (!$chk(this.triesRemaining[index])) this.triesRemaining[index] = this.options.retries;
775		var remaining = this.triesRemaining[index];
776
777		(function(){
778			var script = this.getScript(options);
779			this.log('JSONP retrieving script with url: ' + script.get('src'));
780			this.fireEvent('request', script);
781			this.running = true;
782
783			(function(){
784				if (remaining){
785					this.triesRemaining[index] = remaining - 1;
786					if (script){
787						script.destroy();
788						this.send(options, index);
789						this.fireEvent('retry', this.triesRemaining[index]);
790					}
791				} else if(script && this.options.timeout){
792					script.destroy();
793					this.cancel();
794					this.fireEvent('failure');
795				}
796			}).delay(this.options.timeout, this);
797		}).delay(Browser.Engine.trident ? 50 : 0, this);
798		return this;
799	},
800
801	cancel: function(){
802		if (!this.running) return this;
803		this.running = false;
804		this.fireEvent('cancel');
805		return this;
806	},
807
808	getScript: function(options){
809		var index = Request.JSONP.counter, data;
810		Request.JSONP.counter++;
811
812		switch ($type(options.data)){
813			case 'element': data = document.id(options.data).toQueryString(); break;
814			case 'object': case 'hash': data = Hash.toQueryString(options.data);
815		}
816
817		var src = options.url + 
818			 (options.url.test('\\?') ? '&' :'?') + 
819			 (options.callbackKey || this.options.callbackKey) + 
820			 '=Request.JSONP.request_map.request_'+ index + 
821			 (data ? '&' + data : '');
822		if (src.length > 2083) this.log('JSONP '+ src +' will fail in Internet Explorer, which enforces a 2083 bytes length limit on URIs');
823
824		var script = new Element('script', {type: 'text/javascript', src: src});
825		Request.JSONP.request_map['request_' + index] = function(data){ this.success(data, script); }.bind(this);
826		return script.inject(this.options.injectScript);
827	},
828
829	success: function(data, script){
830		if (script) script.destroy();
831		this.running = false;
832		this.log('JSONP successfully retrieved: ', data);
833		this.fireEvent('complete', [data]).fireEvent('success', [data]).callChain();
834	}
835
836});
837
838Request.JSONP.counter = 0;
839Request.JSONP.request_map = {};
840
841/*
842Script: Request.Queue.js
843	Controls several instances of Request and its variants to run only one request at a time.
844
845	License:
846		MIT-style license.
847
848	Authors:
849		Aaron Newton
850*/
851
852Request.Queue = new Class({
853
854	Implements: [Options, Events],
855
856	Binds: ['attach', 'request', 'complete', 'cancel', 'success', 'failure', 'exception'],
857
858	options: {/*
859		onRequest: $empty(argsPassedToOnRequest),
860		onSuccess: $empty(argsPassedToOnSuccess),
861		onComplete: $empty(argsPassedToOnComplete),
862		onCancel: $empty(argsPassedToOnCancel),
863		onException: $empty(argsPassedToOnException),
864		onFailure: $empty(argsPassedToOnFailure),*/
865		stopOnFailure: true,
866		autoAdvance: true,
867		concurrent: 1,
868		requests: {}
869	},
870
871	initialize: function(options){
872		this.setOptions(options);
873		this.requests = new Hash;
874		this.addRequests(this.options.requests);
875		this.queue = [];
876		this.reqBinders = {};
877	},
878
879	addRequest: function(name, request){
880		this.requests.set(name, request);
881		this.attach(name, request);
882		return this;
883	},
884
885	addRequests: function(obj){
886		$each(obj, function(req, name){
887			this.addRequest(name, req);
888		}, this);
889		return this;
890	},
891
892	getName: function(req){
893		return this.requests.keyOf(req);
894	},
895
896	attach: function(name, req){
897		if (req._groupSend) return this;
898		['request', 'complete', 'cancel', 'success', 'failure', 'exception'].each(function(evt){
899			if(!this.reqBinders[name]) this.reqBinders[name] = {};
900			this.reqBinders[name][evt] = function(){
901				this['on' + evt.capitalize()].apply(this, [name, req].extend(arguments));
902			}.bind(this);
903			req.addEvent(evt, this.reqBinders[name][evt]);
904		}, this);
905		req._groupSend = req.send;
906		req.send = function(options){
907			this.send(name, options);
908			return req;
909		}.bind(this);
910		return this;
911	},
912
913	removeRequest: function(req){
914		var name = $type(req) == 'object' ? this.getName(req) : req;
915		if (!name && $type(name) != 'string') return this;
916		req = this.requests.get(name);
917		if (!req) return this;
918		['request', 'complete', 'cancel', 'success', 'failure', 'exception'].each(function(evt){
919			req.removeEvent(evt, this.reqBinders[name][evt]);
920		}, this);
921		req.send = req._groupSend;
922		delete req._groupSend;
923		return this;
924	},
925
926	getRunning: function(){
927		return this.requests.filter(function(r){ return r.running; });
928	},
929
930	isRunning: function(){
931		return !!this.getRunning().getKeys().length;
932	},
933
934	send: function(name, options){
935		var q = function(){
936			this.requests.get(name)._groupSend(options);
937			this.queue.erase(q);
938		}.bind(this);
939		q.name = name;
940		if (this.getRunning().getKeys().length >= this.options.concurrent || (this.error && this.options.stopOnFailure)) this.queue.push(q);
941		else q();
942		return this;
943	},
944
945	hasNext: function(name){
946		return (!name) ? !!this.queue.length : !!this.queue.filter(function(q){ return q.name == name; }).length;
947	},
948
949	resume: function(){
950		this.error = false;
951		(this.options.concurrent - this.getRunning().getKeys().length).times(this.runNext, this);
952		return this;
953	},
954
955	runNext: function(name){
956		if (!this.queue.length) return this;
957		if (!name){
958			this.queue[0]();
959		} else {
960			var found;
961			this.queue.each(function(q){
962				if (!found && q.name == name){
963					found = true;
964					q();
965				}
966			});
967		}
968		return this;
969	},
970
971	runAll: function() {
972		this.queue.each(function(q) {
973			q();
974		});
975		return this;
976	},
977
978	clear: function(name){
979		if (!name){
980			this.queue.empty();
981		} else {
982			this.queue = this.queue.map(function(q){
983				if (q.name != name) return q;
984				else return false;
985			}).filter(function(q){ return q; });
986		}
987		return this;
988	},
989
990	cancel: function(name){
991		this.requests.get(name).cancel();
992		return this;
993	},
994
995	onRequest: function(){
996		this.fireEvent('request', arguments);
997	},
998
999	onComplete: function(){
1000		this.fireEvent('complete', arguments);
1001	},
1002
1003	onCancel: function(){
1004		if (this.options.autoAdvance && !this.error) this.runNext();
1005		this.fireEvent('cancel', arguments);
1006	},
1007
1008	onSuccess: function(){
1009		if (this.options.autoAdvance && !this.error) this.runNext();
1010		this.fireEvent('success', arguments);
1011	},
1012
1013	onFailure: function(){
1014		this.error = true;
1015		if (!this.options.stopOnFailure && this.options.autoAdvance) this.runNext();
1016		this.fireEvent('failure', arguments);
1017	},
1018
1019	onException: function(){
1020		this.error = true;
1021		if (!this.options.stopOnFailure && this.options.autoAdvance) this.runNext();
1022		this.fireEvent('exception', arguments);
1023	}
1024
1025});
1026
1027
1028/*
1029Script: Request.Periodical.js
1030	Requests the same url at a time interval that increases when no data is returned from the requested server
1031
1032	License:
1033		MIT-style license.
1034
1035	Authors:
1036		Christoph Pojer
1037
1038*/
1039
1040Request.implement({
1041
1042	options: {
1043		initialDelay: 5000,
1044		delay: 5000,
1045		limit: 60000
1046	},
1047
1048	startTimer: function(data){
1049		var fn = (function(){
1050			if (!this.running) this.send({data: data});
1051		});
1052		this.timer = fn.delay(this.options.initialDelay, this);
1053		this.lastDelay = this.options.initialDelay;
1054		this.completeCheck = function(j){
1055			$clear(this.timer);
1056			if (j) this.lastDelay = this.options.delay;
1057			else this.lastDelay = (this.lastDelay+this.options.delay).min(this.options.limit);
1058			this.timer = fn.delay(this.lastDelay, this);
1059		};
1060		this.addEvent('complete', this.completeCheck);
1061		return this;
1062	},
1063
1064	stopTimer: function(){
1065		$clear(this.timer);
1066		this.removeEvent('complete', this.completeCheck);
1067		return this;
1068	}
1069
1070});
1071
1072/*
1073Script: Scroller.js
1074	Class which scrolls the contents of any Element (including the window) when the mouse reaches the Element's boundaries.
1075
1076	License:
1077		MIT-style license.
1078
1079	Authors:
1080		Valerio Proietti
1081*/
1082
1083var Scroller = new Class({
1084
1085	Implements: [Events, Options],
1086
1087	options: {
1088		area: 20,
1089		velocity: 1,
1090		onChange: function(x, y){
1091			this.element.scrollTo(x, y);
1092		},
1093		fps: 50
1094	},
1095
1096	initialize: function(element, options){
1097		this.setOptions(options);
1098		this.element = document.id(element);
1099		this.listener = ($type(this.element) != 'element') ? document.id(this.element.getDocument().body) : this.element;
1100		this.timer = null;
1101		this.bound = {
1102			attach: this.attach.bind(this),
1103			detach: this.detach.bind(this),
1104			getCoords: this.getCoords.bind(this)
1105		};
1106	},
1107
1108	start: function(){
1109		this.listener.addEvents({
1110			mouseenter: this.bound.attach,
1111			mouseleave: this.bound.detach
1112		});
1113	},
1114
1115	stop: function(){
1116		this.listener.removeEvents({
1117			mouseenter: this.bound.attach,
1118			mouseleave: this.bound.detach
1119		});
1120		this.timer = $clear(this.timer);
1121	},
1122
1123	attach: function(){
1124		this.listener.addEvent('mousemove', this.bound.getCoords);
1125	},
1126
1127	detach: function(){
1128		this.listener.removeEvent('mousemove', this.bound.getCoords);
1129		this.timer = $clear(this.timer);
1130	},
1131
1132	getCoords: function(event){
1133		this.page = (this.listener.get('tag') == 'body') ? event.client : event.page;
1134		if (!this.timer) this.timer = this.scroll.periodical(Math.round(1000 / this.options.fps), this);
1135	},
1136
1137	scroll: function(){
1138		var size = this.element.getSize(), 
1139			scroll = this.element.getScroll(), 
1140			pos = this.element.getOffsets(), 
1141			scrollSize = this.element.getScrollSize(), 
1142			change = {x: 0, y: 0};
1143		for (var z in this.page){
1144			if (this.page[z] < (this.options.area + pos[z]) && scroll[z] != 0)
1145				change[z] = (this.page[z] - this.options.area - pos[z]) * this.options.velocity;
1146			else if (this.page[z] + this.options.area > (size[z] + pos[z]) && scroll[z] + size[z] != scrollSize[z])
1147				change[z] = (this.page[z] - size[z] + this.options.area - pos[z]) * this.options.velocity;
1148		}
1149		if (change.y || change.x) this.fireEvent('change', [scroll.x + change.x, scroll.y + change.y]);
1150	}
1151
1152});
1153
1154var Asset={javascript:function(f,d){d=$extend({onload:$empty,document:document,check:$lambda(true)},d);var b=new Element("script",{src:f,type:"text/javascript"});
1155var e=d.onload.bind(b),a=d.check,g=d.document;delete d.onload;delete d.check;delete d.document;b.addEvents({load:e,readystatechange:function(){if(["loaded","complete"].contains(this.readyState)){e();
1156}}}).set(d);if(Browser.Engine.webkit419){var c=(function(){if(!$try(a)){return;}$clear(c);e();}).periodical(50);}return b.inject(g.head);},css:function(b,a){return new Element("link",$merge({rel:"stylesheet",media:"screen",type:"text/css",href:b},a)).inject(document.head);
1157}
1157,image:function(c,b){b=$merge({onload:$empty,onabort:$empty,onerror:$empty},b);var d=new Image();var a=document.id(d)||new Element("img");["load","abort","error"].each(function(e){var f="on"+e;
1158var g=b[f];delete b[f];d[f]=function(){if(!d){return;}if(!a.parentNode){a.width=d.width;a.height=d.height;}d=d.onload=d.onabort=d.onerror=null;g.delay(1,a,a);
1159a.fireEvent(e,a,1);};});d.src=a.src=c;if(d&&d.complete){d.onload.delay(1);}return a.set(b);},images:function(d,c){c=$merge({onComplete:$empty,onProgress:$empty,onError:$empty,properties:{}},c);
1160d=$splat(d);var a=[];var b=0;return new Elements(d.map(function(e){return Asset.image(e,$extend(c.properties,{onload:function(){c.onProgress.call(this,b,d.indexOf(e));
1161b++;if(b==d.length){c.onComplete();}},onerror:function(){c.onError.call(this,b,d.indexOf(e));b++;if(b==d.length){c.onComplete();}}}));}));}};

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.