]>
jfr.im git - irc/quakenet/qwebirc.git/blob - static/js/mootools-1.2-more-nc.js
1 //MooTools More, <http://mootools.net/more>. Copyright (c) 2006-2008 Valerio Proietti, <http://mad4milk.net>, MIT Style License.
5 Effect to slide an element in and out of view.
11 Fx
.Slide
= new Class({
19 initialize: function(element
, options
){
20 this.addEvent('complete', function(){
21 this.open
= (this.wrapper
['offset' + this.layout
.capitalize()] != 0);
22 if (this.open
&& Browser
.Engine
.webkit419
) this.element
.dispose().inject(this.wrapper
);
24 this.element
= this.subject
= $(element
);
26 var wrapper
= this.element
.retrieve('wrapper');
27 this.wrapper
= wrapper
|| new Element('div', {
28 styles: $extend(this.element
.getStyles('margin', 'position'), {'overflow': 'hidden'})
29 }).wraps(this.element
);
30 this.element
.store('wrapper', this.wrapper
).setStyle('margin', 0);
36 this.margin
= 'margin-top';
37 this.layout
= 'height';
38 this.offset
= this.element
.offsetHeight
;
41 horizontal: function(){
42 this.margin
= 'margin-left';
43 this.layout
= 'width';
44 this.offset
= this.element
.offsetWidth
;
48 this.element
.setStyle(this.margin
, now
[0]);
49 this.wrapper
.setStyle(this.layout
, now
[1]);
53 compute: function(from, to
, delta
){
57 now
[i
] = Fx
.compute(from[i
], to
[i
], delta
);
62 start: function(how
, mode
){
63 if (!this.check(arguments
.callee
, how
, mode
)) return this;
64 this[mode
|| this.options
.mode
]();
65 var margin
= this.element
.getStyle(this.margin
).toInt();
66 var layout
= this.wrapper
.getStyle(this.layout
).toInt();
67 var caseIn
= [[margin
, layout
], [0, this.offset
]];
68 var caseOut
= [[margin
, layout
], [-this.offset
, 0]];
71 case 'in': start
= caseIn
; break;
72 case 'out': start
= caseOut
; break;
73 case 'toggle': start
= (this.wrapper
['offset' + this.layout
.capitalize()] == 0) ? caseIn : caseOut
;
75 return this.parent(start
[0], start
[1]);
78 slideIn: function(mode
){
79 return this.start('in', mode
);
82 slideOut: function(mode
){
83 return this.start('out', mode
);
87 this[mode
|| this.options
.mode
]();
89 return this.set([-this.offset
, 0]);
93 this[mode
|| this.options
.mode
]();
95 return this.set([0, this.offset
]);
98 toggle: function(mode
){
99 return this.start('toggle', mode
);
104 Element
.Properties
.slide
= {
106 set: function(options
){
107 var slide
= this.retrieve('slide');
108 if (slide
) slide
.cancel();
109 return this.eliminate('slide').store('slide:options', $extend({link: 'cancel'}, options
));
112 get: function(options
){
113 if (options
|| !this.retrieve('slide')){
114 if (options
|| !this.retrieve('slide:options')) this.set('slide', options
);
115 this.store('slide', new Fx
.Slide(this, this.retrieve('slide:options')));
117 return this.retrieve('slide');
124 slide: function(how
, mode
){
125 how
= how
|| 'toggle';
126 var slide
= this.get('slide'), toggle
;
128 case 'hide': slide
.hide(mode
); break;
129 case 'show': slide
.show(mode
); break;
131 var flag
= this.retrieve('slide:flag', slide
.open
);
132 slide
[(flag
) ? 'slideOut' : 'slideIn'](mode
);
133 this.store('slide:flag', !flag
);
136 default: slide
.start(how
, mode
);
138 if (!toggle
) this.eliminate('slide:flag');
147 Effect to smoothly scroll any element, including the window.
153 Fx
.Scroll
= new Class({
158 offset: {'x': 0, 'y': 0},
162 initialize: function(element
, options
){
163 this.element
= this.subject
= $(element
);
164 this.parent(options
);
165 var cancel
= this.cancel
.bind(this, false);
167 if ($type(this.element
) != 'element') this.element
= $(this.element
.getDocument().body
);
169 var stopper
= this.element
;
171 if (this.options
.wheelStops
){
172 this.addEvent('start', function(){
173 stopper
.addEvent('mousewheel', cancel
);
175 this.addEvent('complete', function(){
176 stopper
.removeEvent('mousewheel', cancel
);
182 var now
= Array
.flatten(arguments
);
183 this.element
.scrollTo(now
[0], now
[1]);
186 compute: function(from, to
, delta
){
190 now
.push(Fx
.compute(from[i
], to
[i
], delta
));
195 start: function(x
, y
){
196 if (!this.check(arguments
.callee
, x
, y
)) return this;
197 var offsetSize
= this.element
.getSize(), scrollSize
= this.element
.getScrollSize();
198 var scroll
= this.element
.getScroll(), values
= {x: x
, y: y
};
199 for (var z
in values
){
200 var max
= scrollSize
[z
] - offsetSize
[z
];
201 if ($chk(values
[z
])) values
[z
] = ($type(values
[z
]) == 'number') ? values
[z
].limit(0, max
) : max
;
202 else values
[z
] = scroll
[z
];
203 values
[z
] += this.options
.offset
[z
];
205 return this.parent([scroll
.x
, scroll
.y
], [values
.x
, values
.y
]);
209 return this.start(false, 0);
213 return this.start(0, false);
217 return this.start('right', false);
220 toBottom: function(){
221 return this.start(false, 'bottom');
224 toElement: function(el
){
225 var position
= $(el
).getPosition(this.element
);
226 return this.start(position
.x
, position
.y
);
233 Script: Fx.Elements.js
234 Effect to change any number of CSS properties of any number of Elements.
240 Fx
.Elements
= new Class({
244 initialize: function(elements
, options
){
245 this.elements
= this.subject
= $$(elements
);
246 this.parent(options
);
249 compute: function(from, to
, delta
){
252 var iFrom
= from[i
], iTo
= to
[i
], iNow
= now
[i
] = {};
253 for (var p
in iFrom
) iNow
[p
] = this.parent(iFrom
[p
], iTo
[p
], delta
);
261 for (var p
in iNow
) this.render(this.elements
[i
], p
, iNow
[p
], this.options
.unit
);
266 start: function(obj
){
267 if (!this.check(arguments
.callee
, obj
)) return this;
268 var from = {}, to
= {};
270 var iProps
= obj
[i
], iFrom
= from[i
] = {}, iTo
= to
[i
] = {};
271 for (var p
in iProps
){
272 var parsed
= this.prepare(this.elements
[i
], p
, iProps
[p
]);
273 iFrom
[p
] = parsed
.from;
277 return this.parent(from, to
);
284 The base Drag Class. Can be used to drag and resize Elements using mouse events.
290 var Drag
= new Class({
292 Implements: [Events
, Options
],
295 onBeforeStart: $empty,
299 onComplete: $empty,*/
307 preventDefault: false,
308 modifiers: {x: 'left', y: 'top'}
311 initialize: function(){
312 var params
= Array
.link(arguments
, {'options': Object
.type
, 'element': $defined
});
313 this.element
= $(params
.element
);
314 this.document
= this.element
.getDocument();
315 this.setOptions(params
.options
|| {});
316 var htype
= $type(this.options
.handle
);
317 this.handles
= (htype
== 'array' || htype
== 'collection') ? $$(this.options
.handle
) : $(this.options
.handle
) || this.element
;
318 this.mouse
= {'now': {}, 'pos': {}};
319 this.value
= {'start': {}, 'now': {}};
321 this.selection
= (Browser
.Engine
.trident
) ? 'selectstart' : 'mousedown';
324 start: this.start
.bind(this),
325 check: this.check
.bind(this),
326 drag: this.drag
.bind(this),
327 stop: this.stop
.bind(this),
328 cancel: this.cancel
.bind(this),
329 eventStop: $lambda(false)
335 this.handles
.addEvent('mousedown', this.bound
.start
);
340 this.handles
.removeEvent('mousedown', this.bound
.start
);
344 start: function(event
){
345 if (this.options
.preventDefault
) event
.preventDefault();
346 this.fireEvent('beforeStart', this.element
);
347 this.mouse
.start
= event
.page
;
348 var limit
= this.options
.limit
;
349 this.limit
= {'x': [], 'y': []};
350 for (var z
in this.options
.modifiers
){
351 if (!this.options
.modifiers
[z
]) continue;
352 if (this.options
.style
) this.value
.now
[z
] = this.element
.getStyle(this.options
.modifiers
[z
]).toInt();
353 else this.value
.now
[z
] = this.element
[this.options
.modifiers
[z
]];
354 if (this.options
.invert
) this.value
.now
[z
] *= -1;
355 this.mouse
.pos
[z
] = event
.page
[z
] - this.value
.now
[z
];
356 if (limit
&& limit
[z
]){
357 for (var i
= 2; i
--; i
){
358 if ($chk(limit
[z
][i
])) this.limit
[z
][i
] = $lambda(limit
[z
][i
])();
362 if ($type(this.options
.grid
) == 'number') this.options
.grid
= {'x': this.options
.grid
, 'y': this.options
.grid
};
363 this.document
.addEvents({mousemove: this.bound
.check
, mouseup: this.bound
.cancel
});
364 this.document
.addEvent(this.selection
, this.bound
.eventStop
);
367 check: function(event
){
368 if (this.options
.preventDefault
) event
.preventDefault();
369 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)));
370 if (distance
> this.options
.snap
){
372 this.document
.addEvents({
373 mousemove: this.bound
.drag
,
374 mouseup: this.bound
.stop
376 this.fireEvent('start', this.element
).fireEvent('snap', this.element
);
380 drag: function(event
){
381 if (this.options
.preventDefault
) event
.preventDefault();
382 this.mouse
.now
= event
.page
;
383 for (var z
in this.options
.modifiers
){
384 if (!this.options
.modifiers
[z
]) continue;
385 this.value
.now
[z
] = this.mouse
.now
[z
] - this.mouse
.pos
[z
];
386 if (this.options
.invert
) this.value
.now
[z
] *= -1;
387 if (this.options
.limit
&& this.limit
[z
]){
388 if ($chk(this.limit
[z
][1]) && (this.value
.now
[z
] > this.limit
[z
][1])){
389 this.value
.now
[z
] = this.limit
[z
][1];
390 } else if ($chk(this.limit
[z
][0]) && (this.value
.now
[z
] < this.limit
[z
][0])){
391 this.value
.now
[z
] = this.limit
[z
][0];
394 if (this.options
.grid
[z
]) this.value
.now
[z
] -= (this.value
.now
[z
] % this.options
.grid
[z
]);
395 if (this.options
.style
) this.element
.setStyle(this.options
.modifiers
[z
], this.value
.now
[z
] + this.options
.unit
);
396 else this.element
[this.options
.modifiers
[z
]] = this.value
.now
[z
];
398 this.fireEvent('drag', this.element
);
401 cancel: function(event
){
402 this.document
.removeEvent('mousemove', this.bound
.check
);
403 this.document
.removeEvent('mouseup', this.bound
.cancel
);
405 this.document
.removeEvent(this.selection
, this.bound
.eventStop
);
406 this.fireEvent('cancel', this.element
);
410 stop: function(event
){
411 this.document
.removeEvent(this.selection
, this.bound
.eventStop
);
412 this.document
.removeEvent('mousemove', this.bound
.drag
);
413 this.document
.removeEvent('mouseup', this.bound
.stop
);
414 if (event
) this.fireEvent('complete', this.element
);
421 makeResizable: function(options
){
422 return new Drag(this, $merge({modifiers: {'x': 'width', 'y': 'height'}}, options
));
429 A Drag extension that provides support for the constraining of draggables to containers and droppables.
435 Drag
.Move
= new Class({
444 initialize: function(element
, options
){
445 this.parent(element
, options
);
446 this.droppables
= $$(this.options
.droppables
);
447 this.container
= $(this.options
.container
);
448 if (this.container
&& $type(this.container
) != 'element') this.container
= $(this.container
.getDocument().body
);
449 element
= this.element
;
451 var current
= element
.getStyle('position');
452 var position
= (current
!= 'static') ? current : 'absolute';
453 if (element
.getStyle('left') == 'auto' || element
.getStyle('top') == 'auto') element
.position(element
.getPosition(element
.offsetParent
));
455 element
.setStyle('position', position
);
457 this.addEvent('start', function(){
458 this.checkDroppables();
462 start: function(event
){
464 var el
= this.element
, cont
= this.container
, ccoo
= cont
.getCoordinates(el
.offsetParent
), cps
= {}, ems
= {};
466 ['top', 'right', 'bottom', 'left'].each(function(pad
){
467 cps
[pad
] = cont
.getStyle('padding-' + pad
).toInt();
468 ems
[pad
] = el
.getStyle('margin-' + pad
).toInt();
471 var width
= el
.offsetWidth
+ ems
.left
+ ems
.right
, height
= el
.offsetHeight
+ ems
.top
+ ems
.bottom
;
472 var x
= [ccoo
.left
+ cps
.left
, ccoo
.right
- cps
.right
- width
];
473 var y
= [ccoo
.top
+ cps
.top
, ccoo
.bottom
- cps
.bottom
- height
];
475 this.options
.limit
= {x: x
, y: y
};
480 checkAgainst: function(el
){
481 el
= el
.getCoordinates();
482 var now
= this.mouse
.now
;
483 return (now
.x
> el
.left
&& now
.x
< el
.right
&& now
.y
< el
.bottom
&& now
.y
> el
.top
);
486 checkDroppables: function(){
487 var overed
= this.droppables
.filter(this.checkAgainst
, this).getLast();
488 if (this.overed
!= overed
){
489 if (this.overed
) this.fireEvent('leave', [this.element
, this.overed
]);
491 this.overed
= overed
;
492 this.fireEvent('enter', [this.element
, overed
]);
499 drag: function(event
){
501 if (this.droppables
.length
) this.checkDroppables();
504 stop: function(event
){
505 this.checkDroppables();
506 this.fireEvent('drop', [this.element
, this.overed
]);
508 return this.parent(event
);
515 makeDraggable: function(options
){
516 return new Drag
.Move(this, options
);
523 Script: Hash.Cookie.js
524 Class for creating, reading, and deleting Cookies in JSON format.
530 Hash
.Cookie
= new Class({
538 initialize: function(name
, options
){
539 this.parent(name
, options
);
544 var value
= JSON
.encode(this.hash
);
545 if (!value
|| value
.length
> 4096) return false; //cookie would be truncated!
546 if (value
== '{}') this.dispose();
547 else this.write(value
);
552 this.hash
= new Hash(JSON
.decode(this.read(), true));
558 Hash
.Cookie
.implement((function(){
562 Hash
.each(Hash
.prototype, function(method
, name
){
563 methods
[name
] = function(){
564 var value
= method
.apply(this.hash
, arguments
);
565 if (this.options
.autoSave
) this.save();
576 Class for creating and manipulating colors in JavaScript. Supports HSB -> RGB Conversions and vice versa.
582 var Color
= new Native({
584 initialize: function(color
, type
){
585 if (arguments
.length
>= 3){
586 type
= "rgb"; color
= Array
.slice(arguments
, 0, 3);
587 } else if (typeof color
== 'string'){
588 if (color
.match(/rgb/)) color
= color
.rgbToHex().hexToRgb(true);
589 else if (color
.match(/hsb/)) color
= color
.hsbToRgb();
590 else color
= color
.hexToRgb(true);
592 type
= type
|| 'rgb';
596 color
= color
.hsbToRgb();
599 case 'hex': color
= color
.hexToRgb(true); break;
601 color
.rgb
= color
.slice(0, 3);
602 color
.hsb
= color
.hsb
|| color
.rgbToHsb();
603 color
.hex
= color
.rgbToHex();
604 return $extend(color
, this);
612 var colors
= Array
.slice(arguments
);
613 var alpha
= ($type(colors
.getLast()) == 'number') ? colors
.pop() : 50;
614 var rgb
= this.slice();
615 colors
.each(function(color
){
616 color
= new Color(color
);
617 for (var i
= 0; i
< 3; i
++) rgb
[i
] = Math
.round((rgb
[i
] / 100 * (100 - alpha
)) + (color
[i
] / 100 * alpha
));
619 return new Color(rgb
, 'rgb');
623 return new Color(this.map(function(value
){
628 setHue: function(value
){
629 return new Color([value
, this.hsb
[1], this.hsb
[2]], 'hsb');
632 setSaturation: function(percent
){
633 return new Color([this.hsb
[0], percent
, this.hsb
[2]], 'hsb');
636 setBrightness: function(percent
){
637 return new Color([this.hsb
[0], this.hsb
[1], percent
], 'hsb');
642 function $RGB(r
, g
, b
){
643 return new Color([r
, g
, b
], 'rgb');
646 function $HSB(h
, s
, b
){
647 return new Color([h
, s
, b
], 'hsb');
651 return new Color(hex
, 'hex');
656 rgbToHsb: function(){
657 var red
= this[0], green
= this[1], blue
= this[2];
658 var hue
, saturation
, brightness
;
659 var max
= Math
.max(red
, green
, blue
), min
= Math
.min(red
, green
, blue
);
660 var delta
= max
- min
;
661 brightness
= max
/ 255;
662 saturation
= (max
!= 0) ? delta
/ max : 0;
663 if (saturation
== 0){
666 var rr
= (max
- red
) / delta
;
667 var gr
= (max
- green
) / delta
;
668 var br
= (max
- blue
) / delta
;
669 if (red
== max
) hue
= br
- gr
;
670 else if (green
== max
) hue
= 2 + rr
- br
;
671 else hue
= 4 + gr
- rr
;
675 return [Math
.round(hue
* 360), Math
.round(saturation
* 100), Math
.round(brightness
* 100)];
678 hsbToRgb: function(){
679 var br
= Math
.round(this[2] / 100 * 255);
683 var hue
= this[0] % 360;
685 var p
= Math
.round((this[2] * (100 - this[1])) / 10000 * 255);
686 var q
= Math
.round((this[2] * (6000 - this[1] * f
)) / 600000 * 255);
687 var t
= Math
.round((this[2] * (6000 - this[1] * (60 - f
))) / 600000 * 255);
688 switch (Math
.floor(hue
/ 60)){
689 case 0: return [br
, t
, p
];
690 case 1: return [q
, br
, p
];
691 case 2: return [p
, br
, t
];
692 case 3: return [p
, q
, br
];
693 case 4: return [t
, p
, br
];
694 case 5: return [br
, p
, q
];
704 rgbToHsb: function(){
705 var rgb
= this.match(/\d{1,3}/g);
706 return (rgb
) ? hsb
.rgbToHsb() : null;
709 hsbToRgb: function(){
710 var hsb
= this.match(/\d{1,3}/g);
711 return (hsb
) ? hsb
.hsbToRgb() : null;
719 Class for monitoring collections of events
725 var Group
= new Class({
727 initialize: function(){
728 this.instances
= Array
.flatten(arguments
);
733 addEvent: function(type
, fn
){
734 this.checker
[type
] = this.checker
[type
] || {};
735 this.events
[type
] = this.events
[type
] || [];
736 if (this.events
[type
].contains(fn
)) return false;
737 else this.events
[type
].push(fn
);
738 this.instances
.each(function(instance
, i
){
739 instance
.addEvent(type
, this.check
.bind(this, [type
, instance
, i
]));
744 check: function(type
, instance
, i
){
745 this.checker
[type
][i
] = true;
746 var every
= this.instances
.every(function(current
, j
){
747 return this.checker
[type
][j
] || false;
750 this.checker
[type
] = {};
751 this.events
[type
].each(function(event
){
752 event
.call(this, this.instances
, instance
);
761 Provides methods to dynamically load JavaScript, CSS, and Image files into the document.
767 var Asset
= new Hash({
769 javascript: function(source
, properties
){
770 properties
= $extend({
776 var script
= new Element('script', {'src': source
, 'type': 'text/javascript'});
778 var load
= properties
.onload
.bind(script
), check
= properties
.check
, doc
= properties
.document
;
779 delete properties
.onload
; delete properties
.check
; delete properties
.document
;
783 readystatechange: function(){
784 if (['loaded', 'complete'].contains(this.readyState
)) load();
786 }).setProperties(properties
);
789 if (Browser
.Engine
.webkit419
) var checker
= (function(){
790 if (!$try(check
)) return;
795 return script
.inject(doc
.head
);
798 css: function(source
, properties
){
799 return new Element('link', $merge({
800 'rel': 'stylesheet', 'media': 'screen', 'type': 'text/css', 'href': source
801 }, properties
)).inject(document
.head
);
804 image: function(source
, properties
){
805 properties
= $merge({
810 var image
= new Image();
811 var element
= $(image
) || new Element('img');
812 ['load', 'abort', 'error'].each(function(name
){
813 var type
= 'on' + name
;
814 var event
= properties
[type
];
815 delete properties
[type
];
816 image
[type
] = function(){
818 if (!element
.parentNode
){
819 element
.width
= image
.width
;
820 element
.height
= image
.height
;
822 image
= image
.onload
= image
.onabort
= image
.onerror
= null;
823 event
.delay(1, element
, element
);
824 element
.fireEvent(name
, element
, 1);
827 image
.src
= element
.src
= source
;
828 if (image
&& image
.complete
) image
.onload
.delay(1);
829 return element
.setProperties(properties
);
832 images: function(sources
, options
){
837 if (!sources
.push
) sources
= [sources
];
840 sources
.each(function(source
){
841 var img
= new Asset
.image(source
, {
842 'onload': function(){
843 options
.onProgress
.call(this, counter
, sources
.indexOf(source
));
845 if (counter
== sources
.length
) options
.onComplete();
850 return new Elements(images
);
857 Class for creating a drag and drop sorting interface for lists of items.
863 var Sortables
= new Class({
865 Implements: [Events
, Options
],
870 onComplete: $empty,*/
879 initialize: function(lists
, options
){
880 this.setOptions(options
);
885 this.addLists($$($(lists
) || lists
));
886 if (!this.options
.clone
) this.options
.revert
= false;
887 if (this.options
.revert
) this.effect
= new Fx
.Morph(null, $merge({duration: 250, link: 'cancel'}, this.options
.revert
));
891 this.addLists(this.lists
);
896 this.lists
= this.removeLists(this.lists
);
900 addItems: function(){
901 Array
.flatten(arguments
).each(function(element
){
902 this.elements
.push(element
);
903 var start
= element
.retrieve('sortables:start', this.start
.bindWithEvent(this, element
));
904 (this.options
.handle
? element
.getElement(this.options
.handle
) || element : element
).addEvent('mousedown', start
);
909 addLists: function(){
910 Array
.flatten(arguments
).each(function(list
){
911 this.lists
.push(list
);
912 this.addItems(list
.getChildren());
917 removeItems: function(){
919 Array
.flatten(arguments
).each(function(element
){
920 elements
.push(element
);
921 this.elements
.erase(element
);
922 var start
= element
.retrieve('sortables:start');
923 (this.options
.handle
? element
.getElement(this.options
.handle
) || element : element
).removeEvent('mousedown', start
);
928 removeLists: function(){
930 Array
.flatten(arguments
).each(function(list
){
932 this.lists
.erase(list
);
933 this.removeItems(list
.getChildren());
938 getClone: function(event
, element
){
939 if (!this.options
.clone
) return new Element('div').inject(document
.body
);
940 if ($type(this.options
.clone
) == 'function') return this.options
.clone
.call(this, event
, element
, this.list
);
941 return element
.clone(true).setStyles({
943 'position': 'absolute',
944 'visibility': 'hidden',
945 'width': element
.getStyle('width')
946 }).inject(this.list
).position(element
.getPosition(element
.getOffsetParent()));
949 getDroppables: function(){
950 var droppables
= this.list
.getChildren();
951 if (!this.options
.constrain
) droppables
= this.lists
.concat(droppables
).erase(this.list
);
952 return droppables
.erase(this.clone
).erase(this.element
);
955 insert: function(dragging
, element
){
956 var where
= 'inside';
957 if (this.lists
.contains(element
)){
959 this.drag
.droppables
= this.getDroppables();
961 where
= this.element
.getAllPrevious().contains(element
) ? 'before' : 'after';
963 this.element
.inject(element
, where
);
964 this.fireEvent('sort', [this.element
, this.clone
]);
967 start: function(event
, element
){
968 if (!this.idle
) return;
970 this.element
= element
;
971 this.opacity
= element
.get('opacity');
972 this.list
= element
.getParent();
973 this.clone
= this.getClone(event
, element
);
975 this.drag
= new Drag
.Move(this.clone
, {
976 snap: this.options
.snap
,
977 container: this.options
.constrain
&& this.element
.getParent(),
978 droppables: this.getDroppables(),
981 this.clone
.setStyle('visibility', 'visible');
982 this.element
.set('opacity', this.options
.opacity
|| 0);
983 this.fireEvent('start', [this.element
, this.clone
]);
985 onEnter: this.insert
.bind(this),
986 onCancel: this.reset
.bind(this),
987 onComplete: this.end
.bind(this)
990 this.clone
.inject(this.element
, 'before');
991 this.drag
.start(event
);
996 this.element
.set('opacity', this.opacity
);
998 var dim
= this.element
.getStyles('width', 'height');
999 var pos
= this.clone
.computePosition(this.element
.getPosition(this.clone
.offsetParent
));
1000 this.effect
.element
= this.clone
;
1007 }).chain(this.reset
.bind(this));
1015 this.clone
.destroy();
1016 this.fireEvent('complete', this.element
);
1019 serialize: function(){
1020 var params
= Array
.link(arguments
, {modifier: Function
.type
, index: $defined
});
1021 var serial
= this.lists
.map(function(list
){
1022 return list
.getChildren().map(params
.modifier
|| function(element
){
1023 return element
.get('id');
1027 var index
= params
.index
;
1028 if (this.lists
.length
== 1) index
= 0;
1029 return $chk(index
) && index
>= 0 && index
< this.lists
.length
? serial
[index
] : serial
;
1036 Class for creating nice tips that follow the mouse cursor when hovering an element.
1042 var Tips
= new Class({
1044 Implements: [Events
, Options
],
1047 onShow: function(tip
){
1048 tip
.setStyle('visibility', 'visible');
1050 onHide: function(tip
){
1051 tip
.setStyle('visibility', 'hidden');
1056 offsets: {x: 16, y: 16},
1060 initialize: function(){
1061 var params
= Array
.link(arguments
, {options: Object
.type
, elements: $defined
});
1062 this.setOptions(params
.options
|| null);
1064 this.tip
= new Element('div').inject(document
.body
);
1066 if (this.options
.className
) this.tip
.addClass(this.options
.className
);
1068 var top
= new Element('div', {'class': 'tip-top'}).inject(this.tip
);
1069 this.container
= new Element('div', {'class': 'tip'}).inject(this.tip
);
1070 var bottom
= new Element('div', {'class': 'tip-bottom'}).inject(this.tip
);
1072 this.tip
.setStyles({position: 'absolute', top: 0, left: 0, visibility: 'hidden'});
1074 if (params
.elements
) this.attach(params
.elements
);
1077 attach: function(elements
){
1078 $$(elements
).each(function(element
){
1079 var title
= element
.retrieve('tip:title', element
.get('title'));
1080 var text
= element
.retrieve('tip:text', element
.get('rel') || element
.get('href'));
1081 var enter
= element
.retrieve('tip:enter', this.elementEnter
.bindWithEvent(this, element
));
1082 var leave
= element
.retrieve('tip:leave', this.elementLeave
.bindWithEvent(this, element
));
1083 element
.addEvents({mouseenter: enter
, mouseleave: leave
});
1084 if (!this.options
.fixed
){
1085 var move = element
.retrieve('tip:move', this.elementMove
.bindWithEvent(this, element
));
1086 element
.addEvent('mousemove', move);
1088 element
.store('tip:native', element
.get('title'));
1089 element
.erase('title');
1094 detach: function(elements
){
1095 $$(elements
).each(function(element
){
1096 element
.removeEvent('mouseenter', element
.retrieve('tip:enter') || $empty
);
1097 element
.removeEvent('mouseleave', element
.retrieve('tip:leave') || $empty
);
1098 element
.removeEvent('mousemove', element
.retrieve('tip:move') || $empty
);
1099 element
.eliminate('tip:enter').eliminate('tip:leave').eliminate('tip:move');
1100 var original
= element
.retrieve('tip:native');
1101 if (original
) element
.set('title', original
);
1106 elementEnter: function(event
, element
){
1108 $A(this.container
.childNodes
).each(Element
.dispose
);
1110 var title
= element
.retrieve('tip:title');
1113 this.titleElement
= new Element('div', {'class': 'tip-title'}).inject(this.container
);
1114 this.fill(this.titleElement
, title
);
1117 var text
= element
.retrieve('tip:text');
1119 this.textElement
= new Element('div', {'class': 'tip-text'}).inject(this.container
);
1120 this.fill(this.textElement
, text
);
1123 this.timer
= $clear(this.timer
);
1124 this.timer
= this.show
.delay(this.options
.showDelay
, this);
1126 this.position((!this.options
.fixed
) ? event : {page: element
.getPosition()});
1129 elementLeave: function(event
){
1131 this.timer
= this.hide
.delay(this.options
.hideDelay
, this);
1134 elementMove: function(event
){
1135 this.position(event
);
1138 position: function(event
){
1139 var size
= window
.getSize(), scroll
= window
.getScroll();
1140 var tip
= {x: this.tip
.offsetWidth
, y: this.tip
.offsetHeight
};
1141 var props
= {x: 'left', y: 'top'};
1142 for (var z
in props
){
1143 var pos
= event
.page
[z
] + this.options
.offsets
[z
];
1144 if ((pos
+ tip
[z
] - scroll
[z
]) > size
[z
]) pos
= event
.page
[z
] - this.options
.offsets
[z
] - tip
[z
];
1145 this.tip
.setStyle(props
[z
], pos
);
1149 fill: function(element
, contents
){
1150 (typeof contents
== 'string') ? element
.set('html', contents
) : element
.adopt(contents
);
1154 this.fireEvent('show', this.tip
);
1158 this.fireEvent('hide', this.tip
);
1164 Script: SmoothScroll.js
1165 Class for creating a smooth scrolling effect to all internal links on the page.
1171 var SmoothScroll
= new Class({
1175 initialize: function(options
, context
){
1176 context
= context
|| document
;
1177 var doc
= context
.getDocument(), win
= context
.getWindow();
1178 this.parent(doc
, options
);
1179 this.links
= (this.options
.links
) ? $$(this.options
.links
) : $$(doc
.links
);
1180 var location
= win
.location
.href
.match(/^[^#]*/)[0] + '#';
1181 this.links
.each(function(link
){
1182 if (link
.href
.indexOf(location
) != 0) return;
1183 var anchor
= link
.href
.substr(location
.length
);
1184 if (anchor
&& $(anchor
)) this.useLink(link
, anchor
);
1186 if (!Browser
.Engine
.webkit419
) this.addEvent('complete', function(){
1187 win
.location
.hash
= this.anchor
;
1191 useLink: function(link
, anchor
){
1192 link
.addEvent('click', function(event
){
1193 this.anchor
= anchor
;
1194 this.toElement(anchor
);
1203 Class for creating horizontal and vertical slider controls.
1209 var Slider
= new Class({
1211 Implements: [Events
, Options
],
1215 onComplete: $empty,*/
1216 onTick: function(position
){
1217 if(this.options
.snap
) position
= this.toPosition(this.step
);
1218 this.knob
.setStyle(this.property
, position
);
1228 initialize: function(element
, knob
, options
){
1229 this.setOptions(options
);
1230 this.element
= $(element
);
1231 this.knob
= $(knob
);
1232 this.previousChange
= this.previousEnd
= this.step
= -1;
1233 this.element
.addEvent('mousedown', this.clickedElement
.bind(this));
1234 if (this.options
.wheel
) this.element
.addEvent('mousewheel', this.scrolledElement
.bindWithEvent(this));
1235 var offset
, limit
= {}, modifiers
= {'x': false, 'y': false};
1236 switch (this.options
.mode
){
1239 this.property
= 'top';
1240 offset
= 'offsetHeight';
1244 this.property
= 'left';
1245 offset
= 'offsetWidth';
1247 this.half
= this.knob
[offset
] / 2;
1248 this.full
= this.element
[offset
] - this.knob
[offset
] + (this.options
.offset
* 2);
1249 this.min
= $chk(this.options
.range
[0]) ? this.options
.range
[0] : 0;
1250 this.max
= $chk(this.options
.range
[1]) ? this.options
.range
[1] : this.options
.steps
;
1251 this.range
= this.max
- this.min
;
1252 this.steps
= this.options
.steps
|| this.full
;
1253 this.stepSize
= Math
.abs(this.range
) / this.steps
;
1254 this.stepWidth
= this.stepSize
* this.full
/ Math
.abs(this.range
) ;
1256 this.knob
.setStyle('position', 'relative').setStyle(this.property
, - this.options
.offset
);
1257 modifiers
[this.axis
] = this.property
;
1258 limit
[this.axis
] = [- this.options
.offset
, this.full
- this.options
.offset
];
1259 this.drag
= new Drag(this.knob
, {
1262 modifiers: modifiers
,
1263 onDrag: this.draggedKnob
.bind(this),
1264 onStart: this.draggedKnob
.bind(this),
1265 onComplete: function(){
1270 if (this.options
.snap
) {
1271 this.drag
.options
.grid
= Math
.ceil(this.stepWidth
);
1272 this.drag
.options
.limit
[this.axis
][1] = this.full
;
1276 set: function(step
){
1277 if (!((this.range
> 0) ^ (step
< this.min
))) step
= this.min
;
1278 if (!((this.range
> 0) ^ (step
> this.max
))) step
= this.max
;
1280 this.step
= Math
.round(step
);
1283 this.fireEvent('tick', this.toPosition(this.step
));
1287 clickedElement: function(event
){
1288 var dir
= this.range
< 0 ? -1 : 1;
1289 var position
= event
.page
[this.axis
] - this.element
.getPosition()[this.axis
] - this.half
;
1290 position
= position
.limit(-this.options
.offset
, this.full
-this.options
.offset
);
1292 this.step
= Math
.round(this.min
+ dir
* this.toStep(position
));
1295 this.fireEvent('tick', position
);
1298 scrolledElement: function(event
){
1299 var mode
= (this.options
.mode
== 'horizontal') ? (event
.wheel
< 0) : (event
.wheel
> 0);
1300 this.set(mode
? this.step
- this.stepSize : this.step
+ this.stepSize
);
1304 draggedKnob: function(){
1305 var dir
= this.range
< 0 ? -1 : 1;
1306 var position
= this.drag
.value
.now
[this.axis
];
1307 position
= position
.limit(-this.options
.offset
, this.full
-this.options
.offset
);
1308 this.step
= Math
.round(this.min
+ dir
* this.toStep(position
));
1312 checkStep: function(){
1313 if (this.previousChange
!= this.step
){
1314 this.previousChange
= this.step
;
1315 this.fireEvent('change', this.step
);
1320 if (this.previousEnd
!== this.step
){
1321 this.previousEnd
= this.step
;
1322 this.fireEvent('complete', this.step
+ '');
1326 toStep: function(position
){
1327 var step
= (position
+ this.options
.offset
) * this.stepSize
/ this.full
* this.steps
;
1328 return this.options
.steps
? Math
.round(step
-= step
% this.stepSize
) : step
;
1331 toPosition: function(step
){
1332 return (this.full
* Math
.abs(this.min
- step
)) / (this.steps
* this.stepSize
) - this.options
.offset
;
1339 Class which scrolls the contents of any Element (including the window) when the mouse reaches the Element's boundaries.
1345 var Scroller
= new Class({
1347 Implements: [Events
, Options
],
1352 onChange: function(x
, y
){
1353 this.element
.scrollTo(x
, y
);
1357 initialize: function(element
, options
){
1358 this.setOptions(options
);
1359 this.element
= $(element
);
1360 this.listener
= ($type(this.element
) != 'element') ? $(this.element
.getDocument().body
) : this.element
;
1362 this.coord
= this.getCoords
.bind(this);
1366 this.listener
.addEvent('mousemove', this.coord
);
1370 this.listener
.removeEvent('mousemove', this.coord
);
1371 this.timer
= $clear(this.timer
);
1374 getCoords: function(event
){
1375 this.page
= (this.listener
.get('tag') == 'body') ? event
.client : event
.page
;
1376 if (!this.timer
) this.timer
= this.scroll
.periodical(50, this);
1380 var size
= this.element
.getSize(), scroll
= this.element
.getScroll(), pos
= this.element
.getPosition(), change
= {'x': 0, 'y': 0};
1381 for (var z
in this.page
){
1382 if (this.page
[z
] < (this.options
.area
+ pos
[z
]) && scroll
[z
] != 0)
1383 change
[z
] = (this.page
[z
] - this.options
.area
- pos
[z
]) * this.options
.velocity
;
1384 else if (this.page
[z
] + this.options
.area
> (size
[z
] + pos
[z
]) && size
[z
] + size
[z
] != scroll
[z
])
1385 change
[z
] = (this.page
[z
] - size
[z
] + this.options
.area
- pos
[z
]) * this.options
.velocity
;
1387 if (change
.y
|| change
.x
) this.fireEvent('change', [scroll
.x
+ change
.x
, scroll
.y
+ change
.y
]);
1393 Script: Accordion.js
1394 An Fx.Elements extension which allows you to easily create accordion type controls.
1400 var Accordion
= new Class({
1402 Extends: Fx
.Elements
,
1406 onBackground: $empty,*/
1418 initialize: function(){
1419 var params
= Array
.link(arguments
, {'container': Element
.type
, 'options': Object
.type
, 'togglers': $defined
, 'elements': $defined
});
1420 this.parent(params
.elements
, params
.options
);
1421 this.togglers
= $$(params
.togglers
);
1422 this.container
= $(params
.container
);
1424 if (this.options
.alwaysHide
) this.options
.wait
= true;
1425 if ($chk(this.options
.show
)){
1426 this.options
.display
= false;
1427 this.previous
= this.options
.show
;
1429 if (this.options
.start
){
1430 this.options
.display
= false;
1431 this.options
.show
= false;
1434 if (this.options
.opacity
) this.effects
.opacity
= 'fullOpacity';
1435 if (this.options
.width
) this.effects
.width
= this.options
.fixedWidth
? 'fullWidth' : 'offsetWidth';
1436 if (this.options
.height
) this.effects
.height
= this.options
.fixedHeight
? 'fullHeight' : 'scrollHeight';
1437 for (var i
= 0, l
= this.togglers
.length
; i
< l
; i
++) this.addSection(this.togglers
[i
], this.elements
[i
]);
1438 this.elements
.each(function(el
, i
){
1439 if (this.options
.show
=== i
){
1440 this.fireEvent('active', [this.togglers
[i
], el
]);
1442 for (var fx
in this.effects
) el
.setStyle(fx
, 0);
1445 if ($chk(this.options
.display
)) this.display(this.options
.display
);
1448 addSection: function(toggler
, element
, pos
){
1449 toggler
= $(toggler
);
1450 element
= $(element
);
1451 var test
= this.togglers
.contains(toggler
);
1452 var len
= this.togglers
.length
;
1453 this.togglers
.include(toggler
);
1454 this.elements
.include(element
);
1455 if (len
&& (!test
|| pos
)){
1456 pos
= $pick(pos
, len
- 1);
1457 toggler
.inject(this.togglers
[pos
], 'before');
1458 element
.inject(toggler
, 'after');
1459 } else if (this.container
&& !test
){
1460 toggler
.inject(this.container
);
1461 element
.inject(this.container
);
1463 var idx
= this.togglers
.indexOf(toggler
);
1464 toggler
.addEvent('click', this.display
.bind(this, idx
));
1465 if (this.options
.height
) element
.setStyles({'padding-top': 0, 'border-top': 'none', 'padding-bottom': 0, 'border-bottom': 'none'});
1466 if (this.options
.width
) element
.setStyles({'padding-left': 0, 'border-left': 'none', 'padding-right': 0, 'border-right': 'none'});
1467 element
.fullOpacity
= 1;
1468 if (this.options
.fixedWidth
) element
.fullWidth
= this.options
.fixedWidth
;
1469 if (this.options
.fixedHeight
) element
.fullHeight
= this.options
.fixedHeight
;
1470 element
.setStyle('overflow', 'hidden');
1472 for (var fx
in this.effects
) element
.setStyle(fx
, 0);
1477 display: function(index
){
1478 index
= ($type(index
) == 'element') ? this.elements
.indexOf(index
) : index
;
1479 if ((this.timer
&& this.options
.wait
) || (index
=== this.previous
&& !this.options
.alwaysHide
)) return this;
1480 this.previous
= index
;
1482 this.elements
.each(function(el
, i
){
1484 var hide
= (i
!= index
) || (this.options
.alwaysHide
&& (el
.offsetHeight
> 0));
1485 this.fireEvent(hide
? 'background' : 'active', [this.togglers
[i
], el
]);
1486 for (var fx
in this.effects
) obj
[i
][fx
] = hide
? 0 : el
[this.effects
[fx
]];
1488 return this.start(obj
);