4 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT (MIT-LICENSE.txt)
6 * and GPL (GPL-LICENSE.txt) licenses.
8 * http://docs.jquery.com/UI
10 ;jQuery
.ui
|| (function($) {
12 var _remove
= $.fn
.remove
,
13 isFF2
= $.browser
.mozilla
&& (parseFloat($.browser
.version
) < 1.9);
15 //Helper functions and ui object
19 // $.ui.plugin is deprecated. Use the proxy pattern instead.
21 add: function(module
, option
, set) {
22 var proto
= $.ui
[module
].prototype;
24 proto
.plugins
[i
] = proto
.plugins
[i
] || [];
25 proto
.plugins
[i
].push([option
, set[i
]]);
28 call: function(instance
, name
, args
) {
29 var set = instance
.plugins
[name
];
30 if(!set || !instance
.element
[0].parentNode
) { return; }
32 for (var i
= 0; i
< set.length
; i
++) {
33 if (instance
.options
[set[i
][0]]) {
34 set[i
][1].apply(instance
.element
, args
);
40 contains: function(a
, b
) {
41 return document
.compareDocumentPosition
42 ? a
.compareDocumentPosition(b
) & 16
43 : a
!== b
&& a
.contains(b
);
46 hasScroll: function(el
, a
) {
48 //If overflow is hidden, the element might have extra content, but the user wants to hide it
49 if ($(el
).css('overflow') == 'hidden') { return false; }
51 var scroll
= (a
&& a
== 'left') ? 'scrollLeft' : 'scrollTop',
54 if (el
[scroll
] > 0) { return true; }
56 // TODO: determine which cases actually cause this to happen
57 // if the element doesn't have the scroll set, see if it's possible to
60 has
= (el
[scroll
] > 0);
65 isOverAxis: function(x
, reference
, size
) {
66 //Determines when x coordinate is over "b" element axis
67 return (x
> reference
) && (x
< (reference
+ size
));
70 isOver: function(y
, x
, top
, left
, height
, width
) {
71 //Determines when x, y coordinates is over "b" element
72 return $.ui
.isOverAxis(y
, top
, height
) && $.ui
.isOverAxis(x
, left
, width
);
105 // WAI-ARIA normalization
108 removeAttr
= $.fn
.removeAttr
,
109 ariaNS
= "http://www.w3.org/2005/07/aaa",
110 ariaState
= /^aria-/,
111 ariaRole
= /^wairole:/;
113 $.attr = function(elem
, name
, value
) {
114 var set = value
!== undefined;
116 return (name
== 'role'
118 ? attr
.call(this, elem
, name
, "wairole:" + value
)
119 : (attr
.apply(this, arguments
) || "").replace(ariaRole
, ""))
120 : (ariaState
.test(name
)
122 ? elem
.setAttributeNS(ariaNS
,
123 name
.replace(ariaState
, "aaa:"), value
)
124 : attr
.call(this, elem
, name
.replace(ariaState
, "aaa:")))
125 : attr
.apply(this, arguments
)));
128 $.fn
.removeAttr = function(name
) {
129 return (ariaState
.test(name
)
130 ? this.each(function() {
131 this.removeAttributeNS(ariaNS
, name
.replace(ariaState
, ""));
132 }) : removeAttr
.call(this, name
));
139 // Safari has a native remove event which actually removes DOM elements,
140 // so we have to use triggerHandler instead of trigger (#3037).
141 $("*", this).add(this).each(function() {
142 $(this).triggerHandler("remove");
144 return _remove
.apply(this, arguments
);
147 enableSelection: function() {
149 .attr('unselectable', 'off')
150 .css('MozUserSelect', '')
151 .unbind('selectstart.ui');
154 disableSelection: function() {
156 .attr('unselectable', 'on')
157 .css('MozUserSelect', 'none')
158 .bind('selectstart.ui', function() { return false; });
161 scrollParent: function() {
163 if(($.browser
.msie
&& (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
164 scrollParent
= this.parents().filter(function() {
165 return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
168 scrollParent
= this.parents().filter(function() {
169 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
173 return (/fixed/).test(this.css('position')) || !scrollParent
.length
? $(document
) : scrollParent
;
178 //Additional selectors
179 $.extend($.expr
[':'], {
180 data: function(elem
, i
, match
) {
181 return !!$.data(elem
, match
[3]);
184 focusable: function(element
) {
185 var nodeName
= element
.nodeName
.toLowerCase(),
186 tabIndex
= $.attr(element
, 'tabindex');
187 return (/input|select|textarea|button|object/.test(nodeName
)
189 : 'a' == nodeName
|| 'area' == nodeName
190 ? element
.href
|| !isNaN(tabIndex
)
192 // the element and all of its ancestors must be visible
193 // the browser may report that the area is hidden
194 && !$(element
)['area' == nodeName
? 'parents' : 'closest'](':hidden').length
;
197 tabbable: function(element
) {
198 var tabIndex
= $.attr(element
, 'tabindex');
199 return (isNaN(tabIndex
) || tabIndex
>= 0) && $(element
).is(':focusable');
204 // $.widget is a factory to create jQuery plugins
205 // taking some boilerplate code out of the plugin code
206 function getter(namespace, plugin
, method
, args
) {
207 function getMethods(type
) {
208 var methods
= $[namespace][plugin
][type
] || [];
209 return (typeof methods
== 'string' ? methods
.split(/,?\s+/) : methods
);
212 var methods
= getMethods('getter');
213 if (args
.length
== 1 && typeof args
[0] == 'string') {
214 methods
= methods
.concat(getMethods('getterSetter'));
216 return ($.inArray(method
, methods
) != -1);
219 $.widget = function(name
, prototype) {
220 var namespace = name
.split(".")[0];
221 name
= name
.split(".")[1];
223 // create plugin method
224 $.fn
[name
] = function(options
) {
225 var isMethodCall
= (typeof options
== 'string'),
226 args
= Array
.prototype.slice
.call(arguments
, 1);
228 // prevent calls to internal methods
229 if (isMethodCall
&& options
.substring(0, 1) == '_') {
233 // handle getter methods
234 if (isMethodCall
&& getter(namespace, name
, options
, args
)) {
235 var instance
= $.data(this[0], name
);
236 return (instance
? instance
[options
].apply(instance
, args
)
240 // handle initialization and non-getter methods
241 return this.each(function() {
242 var instance
= $.data(this, name
);
245 (!instance
&& !isMethodCall
&&
246 $.data(this, name
, new $[namespace][name
](this, options
))._init());
249 (instance
&& isMethodCall
&& $.isFunction(instance
[options
]) &&
250 instance
[options
].apply(instance
, args
));
254 // create widget constructor
255 $[namespace] = $[namespace] || {};
256 $[namespace][name
] = function(element
, options
) {
259 this.namespace = namespace;
260 this.widgetName
= name
;
261 this.widgetEventPrefix
= $[namespace][name
].eventPrefix
|| name
;
262 this.widgetBaseClass
= namespace + '-' + name
;
264 this.options
= $.extend({},
266 $[namespace][name
].defaults
,
267 $.metadata
&& $.metadata
.get(element
)[name
],
270 this.element
= $(element
)
271 .bind('setData.' + name
, function(event
, key
, value
) {
272 if (event
.target
== element
) {
273 return self
._setData(key
, value
);
276 .bind('getData.' + name
, function(event
, key
) {
277 if (event
.target
== element
) {
278 return self
._getData(key
);
281 .bind('remove', function() {
282 return self
.destroy();
286 // add widget prototype
287 $[namespace][name
].prototype = $.extend({}, $.widget
.prototype, prototype);
289 // TODO: merge getter and getterSetter properties from widget prototype
290 // and plugin prototype
291 $[namespace][name
].getterSetter
= 'option';
294 $.widget
.prototype = {
295 _init: function() {},
296 destroy: function() {
297 this.element
.removeData(this.widgetName
)
298 .removeClass(this.widgetBaseClass
+ '-disabled' + ' ' + this.namespace + '-state-disabled')
299 .removeAttr('aria-disabled');
302 option: function(key
, value
) {
306 if (typeof key
== "string") {
307 if (value
=== undefined) {
308 return this._getData(key
);
311 options
[key
] = value
;
314 $.each(options
, function(key
, value
) {
315 self
._setData(key
, value
);
318 _getData: function(key
) {
319 return this.options
[key
];
321 _setData: function(key
, value
) {
322 this.options
[key
] = value
;
324 if (key
== 'disabled') {
326 [value
? 'addClass' : 'removeClass'](
327 this.widgetBaseClass
+ '-disabled' + ' ' +
328 this.namespace + '-state-disabled')
329 .attr("aria-disabled", value
);
334 this._setData('disabled', false);
336 disable: function() {
337 this._setData('disabled', true);
340 _trigger: function(type
, event
, data
) {
341 var callback
= this.options
[type
],
342 eventName
= (type
== this.widgetEventPrefix
343 ? type
: this.widgetEventPrefix
+ type
);
345 event
= $.Event(event
);
346 event
.type
= eventName
;
348 // copy original event properties over to the new event
349 // this would happen if we could call $.event.fix instead of $.Event
350 // but we don't have a way to force an event to be fixed multiple times
351 if (event
.originalEvent
) {
352 for (var i
= $.event
.props
.length
, prop
; i
;) {
353 prop
= $.event
.props
[--i
];
354 event
[prop
] = event
.originalEvent
[prop
];
358 this.element
.trigger(event
, data
);
360 return !($.isFunction(callback
) && callback
.call(this.element
[0], event
, data
) === false
361 || event
.isDefaultPrevented());
365 $.widget
.defaults
= {
370 /** Mouse Interaction Plugin **/
373 _mouseInit: function() {
377 .bind('mousedown.'+this.widgetName
, function(event
) {
378 return self
._mouseDown(event
);
380 .bind('click.'+this.widgetName
, function(event
) {
381 if(self
._preventClickEvent
) {
382 self
._preventClickEvent
= false;
383 event
.stopImmediatePropagation();
388 // Prevent text selection in IE
389 if ($.browser
.msie
) {
390 this._mouseUnselectable
= this.element
.attr('unselectable');
391 this.element
.attr('unselectable', 'on');
394 this.started
= false;
397 // TODO: make sure destroying one instance of mouse doesn't mess with
398 // other instances of mouse
399 _mouseDestroy: function() {
400 this.element
.unbind('.'+this.widgetName
);
402 // Restore text selection in IE
404 && this.element
.attr('unselectable', this._mouseUnselectable
));
407 _mouseDown: function(event
) {
408 // don't let more than one widget handle mouseStart
409 // TODO: figure out why we have to use originalEvent
410 event
.originalEvent
= event
.originalEvent
|| {};
411 if (event
.originalEvent
.mouseHandled
) { return; }
413 // we may have missed mouseup (out of window)
414 (this._mouseStarted
&& this._mouseUp(event
));
416 this._mouseDownEvent
= event
;
419 btnIsLeft
= (event
.which
== 1),
420 elIsCancel
= (typeof this.options
.cancel
== "string" ? $(event
.target
).parents().add(event
.target
).filter(this.options
.cancel
).length
: false);
421 if (!btnIsLeft
|| elIsCancel
|| !this._mouseCapture(event
)) {
425 this.mouseDelayMet
= !this.options
.delay
;
426 if (!this.mouseDelayMet
) {
427 this._mouseDelayTimer
= setTimeout(function() {
428 self
.mouseDelayMet
= true;
429 }, this.options
.delay
);
432 if (this._mouseDistanceMet(event
) && this._mouseDelayMet(event
)) {
433 this._mouseStarted
= (this._mouseStart(event
) !== false);
434 if (!this._mouseStarted
) {
435 event
.preventDefault();
440 // these delegates are required to keep context
441 this._mouseMoveDelegate = function(event
) {
442 return self
._mouseMove(event
);
444 this._mouseUpDelegate = function(event
) {
445 return self
._mouseUp(event
);
448 .bind('mousemove.'+this.widgetName
, this._mouseMoveDelegate
)
449 .bind('mouseup.'+this.widgetName
, this._mouseUpDelegate
);
451 // preventDefault() is used to prevent the selection of text here -
452 // however, in Safari, this causes select boxes not to be selectable
453 // anymore, so this fix is needed
454 ($.browser
.safari
|| event
.preventDefault());
456 event
.originalEvent
.mouseHandled
= true;
460 _mouseMove: function(event
) {
461 // IE mouseup check - mouseup happened when mouse was out of window
462 if ($.browser
.msie
&& !event
.button
) {
463 return this._mouseUp(event
);
466 if (this._mouseStarted
) {
467 this._mouseDrag(event
);
468 return event
.preventDefault();
471 if (this._mouseDistanceMet(event
) && this._mouseDelayMet(event
)) {
473 (this._mouseStart(this._mouseDownEvent
, event
) !== false);
474 (this._mouseStarted
? this._mouseDrag(event
) : this._mouseUp(event
));
477 return !this._mouseStarted
;
480 _mouseUp: function(event
) {
482 .unbind('mousemove.'+this.widgetName
, this._mouseMoveDelegate
)
483 .unbind('mouseup.'+this.widgetName
, this._mouseUpDelegate
);
485 if (this._mouseStarted
) {
486 this._mouseStarted
= false;
487 this._preventClickEvent
= (event
.target
== this._mouseDownEvent
.target
);
488 this._mouseStop(event
);
494 _mouseDistanceMet: function(event
) {
496 Math
.abs(this._mouseDownEvent
.pageX
- event
.pageX
),
497 Math
.abs(this._mouseDownEvent
.pageY
- event
.pageY
)
498 ) >= this.options
.distance
502 _mouseDelayMet: function(event
) {
503 return this.mouseDelayMet
;
506 // These are placeholder methods, to be overriden by extending plugin
507 _mouseStart: function(event
) {},
508 _mouseDrag: function(event
) {},
509 _mouseStop: function(event
) {},
510 _mouseCapture: function(event
) { return true; }
513 $.ui
.mouse
.defaults
= {
521 * jQuery UI Draggable 1.7.1
523 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
524 * Dual licensed under the MIT (MIT-LICENSE.txt)
525 * and GPL (GPL-LICENSE.txt) licenses.
527 * http://docs.jquery.com/UI/Draggables
534 $.widget("ui.draggable", $.extend({}, $.ui
.mouse
, {
538 if (this.options
.helper
== 'original' && !(/^(?:r|a|f)/).test(this.element
.css("position")))
539 this.element
[0].style
.position
= 'relative';
541 (this.options
.addClasses
&& this.element
.addClass("ui-draggable"));
542 (this.options
.disabled
&& this.element
.addClass("ui-draggable-disabled"));
548 destroy: function() {
549 if(!this.element
.data('draggable')) return;
551 .removeData("draggable")
552 .unbind(".draggable")
553 .removeClass("ui-draggable"
554 + " ui-draggable-dragging"
555 + " ui-draggable-disabled");
556 this._mouseDestroy();
559 _mouseCapture: function(event
) {
561 var o
= this.options
;
563 if (this.helper
|| o
.disabled
|| $(event
.target
).is('.ui-resizable-handle'))
566 //Quit if we're not on a valid handle
567 this.handle
= this._getHandle(event
);
575 _mouseStart: function(event
) {
577 var o
= this.options
;
579 //Create and append the visible helper
580 this.helper
= this._createHelper(event
);
582 //Cache the helper size
583 this._cacheHelperProportions();
585 //If ddmanager is used for droppables, set the global draggable
587 $.ui
.ddmanager
.current
= this;
590 * - Position generation -
591 * This block generates everything position related - it's the core of draggables.
594 //Cache the margins of the original element
595 this._cacheMargins();
597 //Store the helper's css position
598 this.cssPosition
= this.helper
.css("position");
599 this.scrollParent
= this.helper
.scrollParent();
601 //The element's absolute position on the page minus margins
602 this.offset
= this.element
.offset();
604 top
: this.offset
.top
- this.margins
.top
,
605 left
: this.offset
.left
- this.margins
.left
608 $.extend(this.offset
, {
609 click
: { //Where the click happened, relative to the element
610 left
: event
.pageX
- this.offset
.left
,
611 top
: event
.pageY
- this.offset
.top
613 parent
: this._getParentOffset(),
614 relative
: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
617 //Generate the original position
618 this.originalPosition
= this._generatePosition(event
);
619 this.originalPageX
= event
.pageX
;
620 this.originalPageY
= event
.pageY
;
622 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
624 this._adjustOffsetFromHelper(o
.cursorAt
);
626 //Set a containment if given in the options
628 this._setContainment();
630 //Call plugins and callbacks
631 this._trigger("start", event
);
633 //Recache the helper size
634 this._cacheHelperProportions();
636 //Prepare the droppable offsets
637 if ($.ui
.ddmanager
&& !o
.dropBehaviour
)
638 $.ui
.ddmanager
.prepareOffsets(this, event
);
640 this.helper
.addClass("ui-draggable-dragging");
641 this._mouseDrag(event
, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
645 _mouseDrag: function(event
, noPropagation
) {
647 //Compute the helpers position
648 this.position
= this._generatePosition(event
);
649 this.positionAbs
= this._convertPositionTo("absolute");
651 //Call plugins and callbacks and use the resulting position if something is returned
652 if (!noPropagation
) {
653 var ui
= this._uiHash();
654 this._trigger('drag', event
, ui
);
655 this.position
= ui
.position
;
658 if(!this.options
.axis
|| this.options
.axis
!= "y") this.helper
[0].style
.left
= this.position
.left
+'px';
659 if(!this.options
.axis
|| this.options
.axis
!= "x") this.helper
[0].style
.top
= this.position
.top
+'px';
660 if($.ui
.ddmanager
) $.ui
.ddmanager
.drag(this, event
);
665 _mouseStop: function(event
) {
667 //If we are using droppables, inform the manager about the drop
669 if ($.ui
.ddmanager
&& !this.options
.dropBehaviour
)
670 dropped
= $.ui
.ddmanager
.drop(this, event
);
672 //if a drop comes from outside (a sortable)
674 dropped
= this.dropped
;
675 this.dropped
= false;
678 if((this.options
.revert
== "invalid" && !dropped
) || (this.options
.revert
== "valid" && dropped
) || this.options
.revert
=== true || ($.isFunction(this.options
.revert
) && this.options
.revert
.call(this.element
, dropped
))) {
680 $(this.helper
).animate(this.originalPosition
, parseInt(this.options
.revertDuration
, 10), function() {
681 self
._trigger("stop", event
);
685 this._trigger("stop", event
);
692 _getHandle: function(event
) {
694 var handle
= !this.options
.handle
|| !$(this.options
.handle
, this.element
).length
? true : false;
695 $(this.options
.handle
, this.element
)
699 if(this == event
.target
) handle
= true;
706 _createHelper: function(event
) {
708 var o
= this.options
;
709 var helper
= $.isFunction(o
.helper
) ? $(o
.helper
.apply(this.element
[0], [event
])) : (o
.helper
== 'clone' ? this.element
.clone() : this.element
);
711 if(!helper
.parents('body').length
)
712 helper
.appendTo((o
.appendTo
== 'parent' ? this.element
[0].parentNode
: o
.appendTo
));
714 if(helper
[0] != this.element
[0] && !(/(fixed|absolute)/).test(helper
.css("position")))
715 helper
.css("position", "absolute");
721 _adjustOffsetFromHelper: function(obj
) {
722 if(obj
.left
!= undefined) this.offset
.click
.left
= obj
.left
+ this.margins
.left
;
723 if(obj
.right
!= undefined) this.offset
.click
.left
= this.helperProportions
.width
- obj
.right
+ this.margins
.left
;
724 if(obj
.top
!= undefined) this.offset
.click
.top
= obj
.top
+ this.margins
.top
;
725 if(obj
.bottom
!= undefined) this.offset
.click
.top
= this.helperProportions
.height
- obj
.bottom
+ this.margins
.top
;
728 _getParentOffset: function() {
730 //Get the offsetParent and cache its position
731 this.offsetParent
= this.helper
.offsetParent();
732 var po
= this.offsetParent
.offset();
734 // This is a special case where we need to modify a offset calculated on start, since the following happened:
735 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
736 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
737 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
738 if(this.cssPosition
== 'absolute' && this.scrollParent
[0] != document
&& $.ui
.contains(this.scrollParent
[0], this.offsetParent
[0])) {
739 po
.left
+= this.scrollParent
.scrollLeft();
740 po
.top
+= this.scrollParent
.scrollTop();
743 if((this.offsetParent
[0] == document
.body
) //This needs to be actually done for all browsers, since pageX/pageY includes this information
744 || (this.offsetParent
[0].tagName
&& this.offsetParent
[0].tagName
.toLowerCase() == 'html' && $.browser
.msie
)) //Ugly IE fix
745 po
= { top
: 0, left
: 0 };
748 top
: po
.top
+ (parseInt(this.offsetParent
.css("borderTopWidth"),10) || 0),
749 left
: po
.left
+ (parseInt(this.offsetParent
.css("borderLeftWidth"),10) || 0)
754 _getRelativeOffset: function() {
756 if(this.cssPosition
== "relative") {
757 var p
= this.element
.position();
759 top
: p
.top
- (parseInt(this.helper
.css("top"),10) || 0) + this.scrollParent
.scrollTop(),
760 left
: p
.left
- (parseInt(this.helper
.css("left"),10) || 0) + this.scrollParent
.scrollLeft()
763 return { top
: 0, left
: 0 };
768 _cacheMargins: function() {
770 left
: (parseInt(this.element
.css("marginLeft"),10) || 0),
771 top
: (parseInt(this.element
.css("marginTop"),10) || 0)
775 _cacheHelperProportions: function() {
776 this.helperProportions
= {
777 width
: this.helper
.outerWidth(),
778 height
: this.helper
.outerHeight()
782 _setContainment: function() {
784 var o
= this.options
;
785 if(o
.containment
== 'parent') o
.containment
= this.helper
[0].parentNode
;
786 if(o
.containment
== 'document' || o
.containment
== 'window') this.containment
= [
787 0 - this.offset
.relative
.left
- this.offset
.parent
.left
,
788 0 - this.offset
.relative
.top
- this.offset
.parent
.top
,
789 $(o
.containment
== 'document' ? document
: window
).width() - this.helperProportions
.width
- this.margins
.left
,
790 ($(o
.containment
== 'document' ? document
: window
).height() || document
.body
.parentNode
.scrollHeight
) - this.helperProportions
.height
- this.margins
.top
793 if(!(/^(document|window|parent)$/).test(o
.containment
) && o
.containment
.constructor != Array
) {
794 var ce
= $(o
.containment
)[0]; if(!ce
) return;
795 var co
= $(o
.containment
).offset();
796 var over
= ($(ce
).css("overflow") != 'hidden');
799 co
.left
+ (parseInt($(ce
).css("borderLeftWidth"),10) || 0) + (parseInt($(ce
).css("paddingLeft"),10) || 0) - this.margins
.left
,
800 co
.top
+ (parseInt($(ce
).css("borderTopWidth"),10) || 0) + (parseInt($(ce
).css("paddingTop"),10) || 0) - this.margins
.top
,
801 co
.left
+(over
? Math
.max(ce
.scrollWidth
,ce
.offsetWidth
) : ce
.offsetWidth
) - (parseInt($(ce
).css("borderLeftWidth"),10) || 0) - (parseInt($(ce
).css("paddingRight"),10) || 0) - this.helperProportions
.width
- this.margins
.left
,
802 co
.top
+(over
? Math
.max(ce
.scrollHeight
,ce
.offsetHeight
) : ce
.offsetHeight
) - (parseInt($(ce
).css("borderTopWidth"),10) || 0) - (parseInt($(ce
).css("paddingBottom"),10) || 0) - this.helperProportions
.height
- this.margins
.top
804 } else if(o
.containment
.constructor == Array
) {
805 this.containment
= o
.containment
;
810 _convertPositionTo: function(d
, pos
) {
812 if(!pos
) pos
= this.position
;
813 var mod
= d
== "absolute" ? 1 : -1;
814 var o
= this.options
, scroll
= this.cssPosition
== 'absolute' && !(this.scrollParent
[0] != document
&& $.ui
.contains(this.scrollParent
[0], this.offsetParent
[0])) ? this.offsetParent
: this.scrollParent
, scrollIsRootNode
= (/(html|body)/i).test(scroll
[0].tagName
);
818 pos
.top
// The absolute mouse position
819 + this.offset
.relative
.top
* mod
// Only for relative positioned nodes: Relative offset from element to offset parent
820 + this.offset
.parent
.top
* mod
// The offsetParent's offset without borders (offset + border)
821 - ($.browser
.safari
&& this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollTop() : ( scrollIsRootNode
? 0 : scroll
.scrollTop() ) ) * mod
)
824 pos
.left
// The absolute mouse position
825 + this.offset
.relative
.left
* mod
// Only for relative positioned nodes: Relative offset from element to offset parent
826 + this.offset
.parent
.left
* mod
// The offsetParent's offset without borders (offset + border)
827 - ($.browser
.safari
&& this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollLeft() : scrollIsRootNode
? 0 : scroll
.scrollLeft() ) * mod
)
833 _generatePosition: function(event
) {
835 var o
= this.options
, scroll
= this.cssPosition
== 'absolute' && !(this.scrollParent
[0] != document
&& $.ui
.contains(this.scrollParent
[0], this.offsetParent
[0])) ? this.offsetParent
: this.scrollParent
, scrollIsRootNode
= (/(html|body)/i).test(scroll
[0].tagName
);
837 // This is another very weird special case that only happens for relative elements:
838 // 1. If the css position is relative
839 // 2. and the scroll parent is the document or similar to the offset parent
840 // we have to refresh the relative offset during the scroll so there are no jumps
841 if(this.cssPosition
== 'relative' && !(this.scrollParent
[0] != document
&& this.scrollParent
[0] != this.offsetParent
[0])) {
842 this.offset
.relative
= this._getRelativeOffset();
845 var pageX
= event
.pageX
;
846 var pageY
= event
.pageY
;
849 * - Position constraining -
850 * Constrain the position to a mix of grid, containment.
853 if(this.originalPosition
) { //If we are not dragging yet, we won't check for options
855 if(this.containment
) {
856 if(event
.pageX
- this.offset
.click
.left
< this.containment
[0]) pageX
= this.containment
[0] + this.offset
.click
.left
;
857 if(event
.pageY
- this.offset
.click
.top
< this.containment
[1]) pageY
= this.containment
[1] + this.offset
.click
.top
;
858 if(event
.pageX
- this.offset
.click
.left
> this.containment
[2]) pageX
= this.containment
[2] + this.offset
.click
.left
;
859 if(event
.pageY
- this.offset
.click
.top
> this.containment
[3]) pageY
= this.containment
[3] + this.offset
.click
.top
;
863 var top
= this.originalPageY
+ Math
.round((pageY
- this.originalPageY
) / o
.grid
[1]) * o
.grid
[1];
864 pageY
= this.containment
? (!(top
- this.offset
.click
.top
< this.containment
[1] || top
- this.offset
.click
.top
> this.containment
[3]) ? top
: (!(top
- this.offset
.click
.top
< this.containment
[1]) ? top
- o
.grid
[1] : top
+ o
.grid
[1])) : top
;
866 var left
= this.originalPageX
+ Math
.round((pageX
- this.originalPageX
) / o
.grid
[0]) * o
.grid
[0];
867 pageX
= this.containment
? (!(left
- this.offset
.click
.left
< this.containment
[0] || left
- this.offset
.click
.left
> this.containment
[2]) ? left
: (!(left
- this.offset
.click
.left
< this.containment
[0]) ? left
- o
.grid
[0] : left
+ o
.grid
[0])) : left
;
874 pageY
// The absolute mouse position
875 - this.offset
.click
.top
// Click offset (relative to the element)
876 - this.offset
.relative
.top
// Only for relative positioned nodes: Relative offset from element to offset parent
877 - this.offset
.parent
.top
// The offsetParent's offset without borders (offset + border)
878 + ($.browser
.safari
&& this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollTop() : ( scrollIsRootNode
? 0 : scroll
.scrollTop() ) ))
881 pageX
// The absolute mouse position
882 - this.offset
.click
.left
// Click offset (relative to the element)
883 - this.offset
.relative
.left
// Only for relative positioned nodes: Relative offset from element to offset parent
884 - this.offset
.parent
.left
// The offsetParent's offset without borders (offset + border)
885 + ($.browser
.safari
&& this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollLeft() : scrollIsRootNode
? 0 : scroll
.scrollLeft() ))
892 this.helper
.removeClass("ui-draggable-dragging");
893 if(this.helper
[0] != this.element
[0] && !this.cancelHelperRemoval
) this.helper
.remove();
894 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
896 this.cancelHelperRemoval
= false;
899 // From now on bulk stuff - mainly helpers
901 _trigger: function(type
, event
, ui
) {
902 ui
= ui
|| this._uiHash();
903 $.ui
.plugin
.call(this, type
, [event
, ui
]);
904 if(type
== "drag") this.positionAbs
= this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
905 return $.widget
.prototype._trigger
.call(this, type
, event
, ui
);
910 _uiHash: function(event
) {
913 position
: this.position
,
914 absolutePosition
: this.positionAbs
, //deprecated
915 offset
: this.positionAbs
921 $.extend($.ui
.draggable
, {
928 cancel
: ":input,option",
929 connectToSortable
: false,
940 refreshPositions
: false,
945 scrollSensitivity
: 20,
955 $.ui
.plugin
.add("draggable", "connectToSortable", {
956 start: function(event
, ui
) {
958 var inst
= $(this).data("draggable"), o
= inst
.options
,
959 uiSortable
= $.extend({}, ui
, { item
: inst
.element
});
961 $(o
.connectToSortable
).each(function() {
962 var sortable
= $.data(this, 'sortable');
963 if (sortable
&& !sortable
.options
.disabled
) {
964 inst
.sortables
.push({
966 shouldRevert
: sortable
.options
.revert
968 sortable
._refreshItems(); //Do a one-time refresh at start to refresh the containerCache
969 sortable
._trigger("activate", event
, uiSortable
);
974 stop: function(event
, ui
) {
976 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
977 var inst
= $(this).data("draggable"),
978 uiSortable
= $.extend({}, ui
, { item
: inst
.element
});
980 $.each(inst
.sortables
, function() {
981 if(this.instance
.isOver
) {
983 this.instance
.isOver
= 0;
985 inst
.cancelHelperRemoval
= true; //Don't remove the helper in the draggable instance
986 this.instance
.cancelHelperRemoval
= false; //Remove it in the sortable instance (so sortable plugins like revert still work)
988 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
989 if(this.shouldRevert
) this.instance
.options
.revert
= true;
991 //Trigger the stop of the sortable
992 this.instance
._mouseStop(event
);
994 this.instance
.options
.helper
= this.instance
.options
._helper
;
996 //If the helper has been the original item, restore properties in the sortable
997 if(inst
.options
.helper
== 'original')
998 this.instance
.currentItem
.css({ top
: 'auto', left
: 'auto' });
1001 this.instance
.cancelHelperRemoval
= false; //Remove the helper in the sortable instance
1002 this.instance
._trigger("deactivate", event
, uiSortable
);
1008 drag: function(event
, ui
) {
1010 var inst
= $(this).data("draggable"), self
= this;
1012 var checkPos = function(o
) {
1013 var dyClick
= this.offset
.click
.top
, dxClick
= this.offset
.click
.left
;
1014 var helperTop
= this.positionAbs
.top
, helperLeft
= this.positionAbs
.left
;
1015 var itemHeight
= o
.height
, itemWidth
= o
.width
;
1016 var itemTop
= o
.top
, itemLeft
= o
.left
;
1018 return $.ui
.isOver(helperTop
+ dyClick
, helperLeft
+ dxClick
, itemTop
, itemLeft
, itemHeight
, itemWidth
);
1021 $.each(inst
.sortables
, function(i
) {
1023 //Copy over some variables to allow calling the sortable's native _intersectsWith
1024 this.instance
.positionAbs
= inst
.positionAbs
;
1025 this.instance
.helperProportions
= inst
.helperProportions
;
1026 this.instance
.offset
.click
= inst
.offset
.click
;
1028 if(this.instance
._intersectsWith(this.instance
.containerCache
)) {
1030 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1031 if(!this.instance
.isOver
) {
1033 this.instance
.isOver
= 1;
1034 //Now we fake the start of dragging for the sortable instance,
1035 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1036 //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
1037 this.instance
.currentItem
= $(self
).clone().appendTo(this.instance
.element
).data("sortable-item", true);
1038 this.instance
.options
._helper
= this.instance
.options
.helper
; //Store helper option to later restore it
1039 this.instance
.options
.helper = function() { return ui
.helper
[0]; };
1041 event
.target
= this.instance
.currentItem
[0];
1042 this.instance
._mouseCapture(event
, true);
1043 this.instance
._mouseStart(event
, true, true);
1045 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1046 this.instance
.offset
.click
.top
= inst
.offset
.click
.top
;
1047 this.instance
.offset
.click
.left
= inst
.offset
.click
.left
;
1048 this.instance
.offset
.parent
.left
-= inst
.offset
.parent
.left
- this.instance
.offset
.parent
.left
;
1049 this.instance
.offset
.parent
.top
-= inst
.offset
.parent
.top
- this.instance
.offset
.parent
.top
;
1051 inst
._trigger("toSortable", event
);
1052 inst
.dropped
= this.instance
.element
; //draggable revert needs that
1053 //hack so receive/update callbacks work (mostly)
1054 inst
.currentItem
= inst
.element
;
1055 this.instance
.fromOutside
= inst
;
1059 //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
1060 if(this.instance
.currentItem
) this.instance
._mouseDrag(event
);
1064 //If it doesn't intersect with the sortable, and it intersected before,
1065 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1066 if(this.instance
.isOver
) {
1068 this.instance
.isOver
= 0;
1069 this.instance
.cancelHelperRemoval
= true;
1071 //Prevent reverting on this forced stop
1072 this.instance
.options
.revert
= false;
1074 // The out event needs to be triggered independently
1075 this.instance
._trigger('out', event
, this.instance
._uiHash(this.instance
));
1077 this.instance
._mouseStop(event
, true);
1078 this.instance
.options
.helper
= this.instance
.options
._helper
;
1080 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1081 this.instance
.currentItem
.remove();
1082 if(this.instance
.placeholder
) this.instance
.placeholder
.remove();
1084 inst
._trigger("fromSortable", event
);
1085 inst
.dropped
= false; //draggable revert needs that
1095 $.ui
.plugin
.add("draggable", "cursor", {
1096 start: function(event
, ui
) {
1097 var t
= $('body'), o
= $(this).data('draggable').options
;
1098 if (t
.css("cursor")) o
._cursor
= t
.css("cursor");
1099 t
.css("cursor", o
.cursor
);
1101 stop: function(event
, ui
) {
1102 var o
= $(this).data('draggable').options
;
1103 if (o
._cursor
) $('body').css("cursor", o
._cursor
);
1107 $.ui
.plugin
.add("draggable", "iframeFix", {
1108 start: function(event
, ui
) {
1109 var o
= $(this).data('draggable').options
;
1110 $(o
.iframeFix
=== true ? "iframe" : o
.iframeFix
).each(function() {
1111 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
1113 width
: this.offsetWidth
+"px", height
: this.offsetHeight
+"px",
1114 position
: "absolute", opacity
: "0.001", zIndex
: 1000
1116 .css($(this).offset())
1120 stop: function(event
, ui
) {
1121 $("div.ui-draggable-iframeFix").each(function() { this.parentNode
.removeChild(this); }); //Remove frame helpers
1125 $.ui
.plugin
.add("draggable", "opacity", {
1126 start: function(event
, ui
) {
1127 var t
= $(ui
.helper
), o
= $(this).data('draggable').options
;
1128 if(t
.css("opacity")) o
._opacity
= t
.css("opacity");
1129 t
.css('opacity', o
.opacity
);
1131 stop: function(event
, ui
) {
1132 var o
= $(this).data('draggable').options
;
1133 if(o
._opacity
) $(ui
.helper
).css('opacity', o
._opacity
);
1137 $.ui
.plugin
.add("draggable", "scroll", {
1138 start: function(event
, ui
) {
1139 var i
= $(this).data("draggable");
1140 if(i
.scrollParent
[0] != document
&& i
.scrollParent
[0].tagName
!= 'HTML') i
.overflowOffset
= i
.scrollParent
.offset();
1142 drag: function(event
, ui
) {
1144 var i
= $(this).data("draggable"), o
= i
.options
, scrolled
= false;
1146 if(i
.scrollParent
[0] != document
&& i
.scrollParent
[0].tagName
!= 'HTML') {
1148 if(!o
.axis
|| o
.axis
!= 'x') {
1149 if((i
.overflowOffset
.top
+ i
.scrollParent
[0].offsetHeight
) - event
.pageY
< o
.scrollSensitivity
)
1150 i
.scrollParent
[0].scrollTop
= scrolled
= i
.scrollParent
[0].scrollTop
+ o
.scrollSpeed
;
1151 else if(event
.pageY
- i
.overflowOffset
.top
< o
.scrollSensitivity
)
1152 i
.scrollParent
[0].scrollTop
= scrolled
= i
.scrollParent
[0].scrollTop
- o
.scrollSpeed
;
1155 if(!o
.axis
|| o
.axis
!= 'y') {
1156 if((i
.overflowOffset
.left
+ i
.scrollParent
[0].offsetWidth
) - event
.pageX
< o
.scrollSensitivity
)
1157 i
.scrollParent
[0].scrollLeft
= scrolled
= i
.scrollParent
[0].scrollLeft
+ o
.scrollSpeed
;
1158 else if(event
.pageX
- i
.overflowOffset
.left
< o
.scrollSensitivity
)
1159 i
.scrollParent
[0].scrollLeft
= scrolled
= i
.scrollParent
[0].scrollLeft
- o
.scrollSpeed
;
1164 if(!o
.axis
|| o
.axis
!= 'x') {
1165 if(event
.pageY
- $(document
).scrollTop() < o
.scrollSensitivity
)
1166 scrolled
= $(document
).scrollTop($(document
).scrollTop() - o
.scrollSpeed
);
1167 else if($(window
).height() - (event
.pageY
- $(document
).scrollTop()) < o
.scrollSensitivity
)
1168 scrolled
= $(document
).scrollTop($(document
).scrollTop() + o
.scrollSpeed
);
1171 if(!o
.axis
|| o
.axis
!= 'y') {
1172 if(event
.pageX
- $(document
).scrollLeft() < o
.scrollSensitivity
)
1173 scrolled
= $(document
).scrollLeft($(document
).scrollLeft() - o
.scrollSpeed
);
1174 else if($(window
).width() - (event
.pageX
- $(document
).scrollLeft()) < o
.scrollSensitivity
)
1175 scrolled
= $(document
).scrollLeft($(document
).scrollLeft() + o
.scrollSpeed
);
1180 if(scrolled
!== false && $.ui
.ddmanager
&& !o
.dropBehaviour
)
1181 $.ui
.ddmanager
.prepareOffsets(i
, event
);
1186 $.ui
.plugin
.add("draggable", "snap", {
1187 start: function(event
, ui
) {
1189 var i
= $(this).data("draggable"), o
= i
.options
;
1190 i
.snapElements
= [];
1192 $(o
.snap
.constructor != String
? ( o
.snap
.items
|| ':data(draggable)' ) : o
.snap
).each(function() {
1193 var $t
= $(this); var $o
= $t
.offset();
1194 if(this != i
.element
[0]) i
.snapElements
.push({
1196 width
: $t
.outerWidth(), height
: $t
.outerHeight(),
1197 top
: $o
.top
, left
: $o
.left
1202 drag: function(event
, ui
) {
1204 var inst
= $(this).data("draggable"), o
= inst
.options
;
1205 var d
= o
.snapTolerance
;
1207 var x1
= ui
.offset
.left
, x2
= x1
+ inst
.helperProportions
.width
,
1208 y1
= ui
.offset
.top
, y2
= y1
+ inst
.helperProportions
.height
;
1210 for (var i
= inst
.snapElements
.length
- 1; i
>= 0; i
--){
1212 var l
= inst
.snapElements
[i
].left
, r
= l
+ inst
.snapElements
[i
].width
,
1213 t
= inst
.snapElements
[i
].top
, b
= t
+ inst
.snapElements
[i
].height
;
1215 //Yes, I know, this is insane ;)
1216 if(!((l
-d
< x1
&& x1
< r
+d
&& t
-d
< y1
&& y1
< b
+d
) || (l
-d
< x1
&& x1
< r
+d
&& t
-d
< y2
&& y2
< b
+d
) || (l
-d
< x2
&& x2
< r
+d
&& t
-d
< y1
&& y1
< b
+d
) || (l
-d
< x2
&& x2
< r
+d
&& t
-d
< y2
&& y2
< b
+d
))) {
1217 if(inst
.snapElements
[i
].snapping
) (inst
.options
.snap
.release
&& inst
.options
.snap
.release
.call(inst
.element
, event
, $.extend(inst
._uiHash(), { snapItem
: inst
.snapElements
[i
].item
})));
1218 inst
.snapElements
[i
].snapping
= false;
1222 if(o
.snapMode
!= 'inner') {
1223 var ts
= Math
.abs(t
- y2
) <= d
;
1224 var bs
= Math
.abs(b
- y1
) <= d
;
1225 var ls
= Math
.abs(l
- x2
) <= d
;
1226 var rs
= Math
.abs(r
- x1
) <= d
;
1227 if(ts
) ui
.position
.top
= inst
._convertPositionTo("relative", { top
: t
- inst
.helperProportions
.height
, left
: 0 }).top
- inst
.margins
.top
;
1228 if(bs
) ui
.position
.top
= inst
._convertPositionTo("relative", { top
: b
, left
: 0 }).top
- inst
.margins
.top
;
1229 if(ls
) ui
.position
.left
= inst
._convertPositionTo("relative", { top
: 0, left
: l
- inst
.helperProportions
.width
}).left
- inst
.margins
.left
;
1230 if(rs
) ui
.position
.left
= inst
._convertPositionTo("relative", { top
: 0, left
: r
}).left
- inst
.margins
.left
;
1233 var first
= (ts
|| bs
|| ls
|| rs
);
1235 if(o
.snapMode
!= 'outer') {
1236 var ts
= Math
.abs(t
- y1
) <= d
;
1237 var bs
= Math
.abs(b
- y2
) <= d
;
1238 var ls
= Math
.abs(l
- x1
) <= d
;
1239 var rs
= Math
.abs(r
- x2
) <= d
;
1240 if(ts
) ui
.position
.top
= inst
._convertPositionTo("relative", { top
: t
, left
: 0 }).top
- inst
.margins
.top
;
1241 if(bs
) ui
.position
.top
= inst
._convertPositionTo("relative", { top
: b
- inst
.helperProportions
.height
, left
: 0 }).top
- inst
.margins
.top
;
1242 if(ls
) ui
.position
.left
= inst
._convertPositionTo("relative", { top
: 0, left
: l
}).left
- inst
.margins
.left
;
1243 if(rs
) ui
.position
.left
= inst
._convertPositionTo("relative", { top
: 0, left
: r
- inst
.helperProportions
.width
}).left
- inst
.margins
.left
;
1246 if(!inst
.snapElements
[i
].snapping
&& (ts
|| bs
|| ls
|| rs
|| first
))
1247 (inst
.options
.snap
.snap
&& inst
.options
.snap
.snap
.call(inst
.element
, event
, $.extend(inst
._uiHash(), { snapItem
: inst
.snapElements
[i
].item
})));
1248 inst
.snapElements
[i
].snapping
= (ts
|| bs
|| ls
|| rs
|| first
);
1255 $.ui
.plugin
.add("draggable", "stack", {
1256 start: function(event
, ui
) {
1258 var o
= $(this).data("draggable").options
;
1260 var group
= $.makeArray($(o
.stack
.group
)).sort(function(a
,b
) {
1261 return (parseInt($(a
).css("zIndex"),10) || o
.stack
.min
) - (parseInt($(b
).css("zIndex"),10) || o
.stack
.min
);
1264 $(group
).each(function(i
) {
1265 this.style
.zIndex
= o
.stack
.min
+ i
;
1268 this[0].style
.zIndex
= o
.stack
.min
+ group
.length
;
1273 $.ui
.plugin
.add("draggable", "zIndex", {
1274 start: function(event
, ui
) {
1275 var t
= $(ui
.helper
), o
= $(this).data("draggable").options
;
1276 if(t
.css("zIndex")) o
._zIndex
= t
.css("zIndex");
1277 t
.css('zIndex', o
.zIndex
);
1279 stop: function(event
, ui
) {
1280 var o
= $(this).data("draggable").options
;
1281 if(o
._zIndex
) $(ui
.helper
).css('zIndex', o
._zIndex
);
1287 * jQuery UI Droppable 1.7.1
1289 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
1290 * Dual licensed under the MIT (MIT-LICENSE.txt)
1291 * and GPL (GPL-LICENSE.txt) licenses.
1293 * http://docs.jquery.com/UI/Droppables
1301 $.widget("ui.droppable", {
1305 var o
= this.options
, accept
= o
.accept
;
1306 this.isover
= 0; this.isout
= 1;
1308 this.options
.accept
= this.options
.accept
&& $.isFunction(this.options
.accept
) ? this.options
.accept : function(d
) {
1309 return d
.is(accept
);
1312 //Store the droppable's proportions
1313 this.proportions
= { width
: this.element
[0].offsetWidth
, height
: this.element
[0].offsetHeight
};
1315 // Add the reference and positions to the manager
1316 $.ui
.ddmanager
.droppables
[this.options
.scope
] = $.ui
.ddmanager
.droppables
[this.options
.scope
] || [];
1317 $.ui
.ddmanager
.droppables
[this.options
.scope
].push(this);
1319 (this.options
.addClasses
&& this.element
.addClass("ui-droppable"));
1323 destroy: function() {
1324 var drop
= $.ui
.ddmanager
.droppables
[this.options
.scope
];
1325 for ( var i
= 0; i
< drop
.length
; i
++ )
1326 if ( drop
[i
] == this )
1330 .removeClass("ui-droppable ui-droppable-disabled")
1331 .removeData("droppable")
1332 .unbind(".droppable");
1335 _setData: function(key
, value
) {
1337 if(key
== 'accept') {
1338 this.options
.accept
= value
&& $.isFunction(value
) ? value : function(d
) {
1342 $.widget
.prototype._setData
.apply(this, arguments
);
1347 _activate: function(event
) {
1348 var draggable
= $.ui
.ddmanager
.current
;
1349 if(this.options
.activeClass
) this.element
.addClass(this.options
.activeClass
);
1350 (draggable
&& this._trigger('activate', event
, this.ui(draggable
)));
1353 _deactivate: function(event
) {
1354 var draggable
= $.ui
.ddmanager
.current
;
1355 if(this.options
.activeClass
) this.element
.removeClass(this.options
.activeClass
);
1356 (draggable
&& this._trigger('deactivate', event
, this.ui(draggable
)));
1359 _over: function(event
) {
1361 var draggable
= $.ui
.ddmanager
.current
;
1362 if (!draggable
|| (draggable
.currentItem
|| draggable
.element
)[0] == this.element
[0]) return; // Bail if draggable and droppable are same element
1364 if (this.options
.accept
.call(this.element
[0],(draggable
.currentItem
|| draggable
.element
))) {
1365 if(this.options
.hoverClass
) this.element
.addClass(this.options
.hoverClass
);
1366 this._trigger('over', event
, this.ui(draggable
));
1371 _out: function(event
) {
1373 var draggable
= $.ui
.ddmanager
.current
;
1374 if (!draggable
|| (draggable
.currentItem
|| draggable
.element
)[0] == this.element
[0]) return; // Bail if draggable and droppable are same element
1376 if (this.options
.accept
.call(this.element
[0],(draggable
.currentItem
|| draggable
.element
))) {
1377 if(this.options
.hoverClass
) this.element
.removeClass(this.options
.hoverClass
);
1378 this._trigger('out', event
, this.ui(draggable
));
1383 _drop: function(event
,custom
) {
1385 var draggable
= custom
|| $.ui
.ddmanager
.current
;
1386 if (!draggable
|| (draggable
.currentItem
|| draggable
.element
)[0] == this.element
[0]) return false; // Bail if draggable and droppable are same element
1388 var childrenIntersection
= false;
1389 this.element
.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
1390 var inst
= $.data(this, 'droppable');
1391 if(inst
.options
.greedy
&& $.ui
.intersect(draggable
, $.extend(inst
, { offset
: inst
.element
.offset() }), inst
.options
.tolerance
)) {
1392 childrenIntersection
= true; return false;
1395 if(childrenIntersection
) return false;
1397 if(this.options
.accept
.call(this.element
[0],(draggable
.currentItem
|| draggable
.element
))) {
1398 if(this.options
.activeClass
) this.element
.removeClass(this.options
.activeClass
);
1399 if(this.options
.hoverClass
) this.element
.removeClass(this.options
.hoverClass
);
1400 this._trigger('drop', event
, this.ui(draggable
));
1401 return this.element
;
1410 draggable
: (c
.currentItem
|| c
.element
),
1412 position
: c
.position
,
1413 absolutePosition
: c
.positionAbs
, //deprecated
1414 offset
: c
.positionAbs
1420 $.extend($.ui
.droppable
, {
1422 eventPrefix
: 'drop',
1430 tolerance
: 'intersect'
1434 $.ui
.intersect = function(draggable
, droppable
, toleranceMode
) {
1436 if (!droppable
.offset
) return false;
1438 var x1
= (draggable
.positionAbs
|| draggable
.position
.absolute
).left
, x2
= x1
+ draggable
.helperProportions
.width
,
1439 y1
= (draggable
.positionAbs
|| draggable
.position
.absolute
).top
, y2
= y1
+ draggable
.helperProportions
.height
;
1440 var l
= droppable
.offset
.left
, r
= l
+ droppable
.proportions
.width
,
1441 t
= droppable
.offset
.top
, b
= t
+ droppable
.proportions
.height
;
1443 switch (toleranceMode
) {
1445 return (l
< x1
&& x2
< r
1446 && t
< y1
&& y2
< b
);
1449 return (l
< x1
+ (draggable
.helperProportions
.width
/ 2) // Right Half
1450 && x2
- (draggable
.helperProportions
.width
/ 2) < r
// Left Half
1451 && t
< y1
+ (draggable
.helperProportions
.height
/ 2) // Bottom Half
1452 && y2
- (draggable
.helperProportions
.height
/ 2) < b
); // Top Half
1455 var draggableLeft
= ((draggable
.positionAbs
|| draggable
.position
.absolute
).left
+ (draggable
.clickOffset
|| draggable
.offset
.click
).left
),
1456 draggableTop
= ((draggable
.positionAbs
|| draggable
.position
.absolute
).top
+ (draggable
.clickOffset
|| draggable
.offset
.click
).top
),
1457 isOver
= $.ui
.isOver(draggableTop
, draggableLeft
, t
, l
, droppable
.proportions
.height
, droppable
.proportions
.width
);
1462 (y1
>= t
&& y1
<= b
) || // Top edge touching
1463 (y2
>= t
&& y2
<= b
) || // Bottom edge touching
1464 (y1
< t
&& y2
> b
) // Surrounded vertically
1466 (x1
>= l
&& x1
<= r
) || // Left edge touching
1467 (x2
>= l
&& x2
<= r
) || // Right edge touching
1468 (x1
< l
&& x2
> r
) // Surrounded horizontally
1479 This manager tracks offsets of draggables and droppables
1483 droppables
: { 'default': [] },
1484 prepareOffsets: function(t
, event
) {
1486 var m
= $.ui
.ddmanager
.droppables
[t
.options
.scope
];
1487 var type
= event
? event
.type
: null; // workaround for #2317
1488 var list
= (t
.currentItem
|| t
.element
).find(":data(droppable)").andSelf();
1490 droppablesLoop
: for (var i
= 0; i
< m
.length
; i
++) {
1492 if(m
[i
].options
.disabled
|| (t
&& !m
[i
].options
.accept
.call(m
[i
].element
[0],(t
.currentItem
|| t
.element
)))) continue; //No disabled and non-accepted
1493 for (var j
=0; j
< list
.length
; j
++) { if(list
[j
] == m
[i
].element
[0]) { m
[i
].proportions
.height
= 0; continue droppablesLoop
; } }; //Filter out elements in the current dragged item
1494 m
[i
].visible
= m
[i
].element
.css("display") != "none"; if(!m
[i
].visible
) continue; //If the element is not visible, continue
1496 m
[i
].offset
= m
[i
].element
.offset();
1497 m
[i
].proportions
= { width
: m
[i
].element
[0].offsetWidth
, height
: m
[i
].element
[0].offsetHeight
};
1499 if(type
== "mousedown") m
[i
]._activate
.call(m
[i
], event
); //Activate the droppable if used directly from draggables
1504 drop: function(draggable
, event
) {
1506 var dropped
= false;
1507 $.each($.ui
.ddmanager
.droppables
[draggable
.options
.scope
], function() {
1509 if(!this.options
) return;
1510 if (!this.options
.disabled
&& this.visible
&& $.ui
.intersect(draggable
, this, this.options
.tolerance
))
1511 dropped
= this._drop
.call(this, event
);
1513 if (!this.options
.disabled
&& this.visible
&& this.options
.accept
.call(this.element
[0],(draggable
.currentItem
|| draggable
.element
))) {
1514 this.isout
= 1; this.isover
= 0;
1515 this._deactivate
.call(this, event
);
1522 drag: function(draggable
, event
) {
1524 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
1525 if(draggable
.options
.refreshPositions
) $.ui
.ddmanager
.prepareOffsets(draggable
, event
);
1527 //Run through all droppables and check their positions based on specific tolerance options
1529 $.each($.ui
.ddmanager
.droppables
[draggable
.options
.scope
], function() {
1531 if(this.options
.disabled
|| this.greedyChild
|| !this.visible
) return;
1532 var intersects
= $.ui
.intersect(draggable
, this, this.options
.tolerance
);
1534 var c
= !intersects
&& this.isover
== 1 ? 'isout' : (intersects
&& this.isover
== 0 ? 'isover' : null);
1538 if (this.options
.greedy
) {
1539 var parent
= this.element
.parents(':data(droppable):eq(0)');
1540 if (parent
.length
) {
1541 parentInstance
= $.data(parent
[0], 'droppable');
1542 parentInstance
.greedyChild
= (c
== 'isover' ? 1 : 0);
1546 // we just moved into a greedy child
1547 if (parentInstance
&& c
== 'isover') {
1548 parentInstance
['isover'] = 0;
1549 parentInstance
['isout'] = 1;
1550 parentInstance
._out
.call(parentInstance
, event
);
1553 this[c
] = 1; this[c
== 'isout' ? 'isover' : 'isout'] = 0;
1554 this[c
== "isover" ? "_over" : "_out"].call(this, event
);
1556 // we just moved out of a greedy child
1557 if (parentInstance
&& c
== 'isout') {
1558 parentInstance
['isout'] = 0;
1559 parentInstance
['isover'] = 1;
1560 parentInstance
._over
.call(parentInstance
, event
);
1569 * jQuery UI Resizable 1.7.1
1571 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
1572 * Dual licensed under the MIT (MIT-LICENSE.txt)
1573 * and GPL (GPL-LICENSE.txt) licenses.
1575 * http://docs.jquery.com/UI/Resizables
1582 $.widget("ui.resizable", $.extend({}, $.ui
.mouse
, {
1586 var self
= this, o
= this.options
;
1587 this.element
.addClass("ui-resizable");
1590 _aspectRatio
: !!(o
.aspectRatio
),
1591 aspectRatio
: o
.aspectRatio
,
1592 originalElement
: this.element
,
1593 _proportionallyResizeElements
: [],
1594 _helper
: o
.helper
|| o
.ghost
|| o
.animate
? o
.helper
|| 'ui-resizable-helper' : null
1597 //Wrap the element if it cannot hold child nodes
1598 if(this.element
[0].nodeName
.match(/canvas|textarea|input|select|button|img/i)) {
1600 //Opera fix for relative positioning
1601 if (/relative/.test(this.element
.css('position')) && $.browser
.opera
)
1602 this.element
.css({ position
: 'relative', top
: 'auto', left
: 'auto' });
1604 //Create a wrapper element and set the wrapper to the new current internal element
1606 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
1607 position
: this.element
.css('position'),
1608 width
: this.element
.outerWidth(),
1609 height
: this.element
.outerHeight(),
1610 top
: this.element
.css('top'),
1611 left
: this.element
.css('left')
1615 //Overwrite the original this.element
1616 this.element
= this.element
.parent().data(
1617 "resizable", this.element
.data('resizable')
1620 this.elementIsWrapper
= true;
1622 //Move margins to the wrapper
1623 this.element
.css({ marginLeft
: this.originalElement
.css("marginLeft"), marginTop
: this.originalElement
.css("marginTop"), marginRight
: this.originalElement
.css("marginRight"), marginBottom
: this.originalElement
.css("marginBottom") });
1624 this.originalElement
.css({ marginLeft
: 0, marginTop
: 0, marginRight
: 0, marginBottom
: 0});
1626 //Prevent Safari textarea resize
1627 this.originalResizeStyle
= this.originalElement
.css('resize');
1628 this.originalElement
.css('resize', 'none');
1630 //Push the actual element to our proportionallyResize internal array
1631 this._proportionallyResizeElements
.push(this.originalElement
.css({ position
: 'static', zoom
: 1, display
: 'block' }));
1633 // avoid IE jump (hard set the margin)
1634 this.originalElement
.css({ margin
: this.originalElement
.css('margin') });
1636 // fix handlers offset
1637 this._proportionallyResize();
1641 this.handles
= o
.handles
|| (!$('.ui-resizable-handle', this.element
).length
? "e,s,se" : { n
: '.ui-resizable-n', e
: '.ui-resizable-e', s
: '.ui-resizable-s', w
: '.ui-resizable-w', se
: '.ui-resizable-se', sw
: '.ui-resizable-sw', ne
: '.ui-resizable-ne', nw
: '.ui-resizable-nw' });
1642 if(this.handles
.constructor == String
) {
1644 if(this.handles
== 'all') this.handles
= 'n,e,s,w,se,sw,ne,nw';
1645 var n
= this.handles
.split(","); this.handles
= {};
1647 for(var i
= 0; i
< n
.length
; i
++) {
1649 var handle
= $.trim(n
[i
]), hname
= 'ui-resizable-'+handle
;
1650 var axis
= $('<div class="ui-resizable-handle ' + hname
+ '"></div>');
1652 // increase zIndex of sw, se, ne, nw axis
1653 //TODO : this modifies original option
1654 if(/sw|se|ne|nw/.test(handle
)) axis
.css({ zIndex
: ++o
.zIndex
});
1656 //TODO : What's going on here?
1657 if ('se' == handle
) {
1658 axis
.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
1661 //Insert into internal handles object and append to element
1662 this.handles
[handle
] = '.ui-resizable-'+handle
;
1663 this.element
.append(axis
);
1668 this._renderAxis = function(target
) {
1670 target
= target
|| this.element
;
1672 for(var i
in this.handles
) {
1674 if(this.handles
[i
].constructor == String
)
1675 this.handles
[i
] = $(this.handles
[i
], this.element
).show();
1677 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
1678 if (this.elementIsWrapper
&& this.originalElement
[0].nodeName
.match(/textarea|input|select|button/i)) {
1680 var axis
= $(this.handles
[i
], this.element
), padWrapper
= 0;
1682 //Checking the correct pad and border
1683 padWrapper
= /sw|ne|nw|se|n|s/.test(i
) ? axis
.outerHeight() : axis
.outerWidth();
1685 //The padding type i have to apply...
1686 var padPos
= [ 'padding',
1687 /ne|nw|n/.test(i
) ? 'Top' :
1688 /se|sw|s/.test(i
) ? 'Bottom' :
1689 /^e$/.test(i
) ? 'Right' : 'Left' ].join("");
1691 target
.css(padPos
, padWrapper
);
1693 this._proportionallyResize();
1697 //TODO: What's that good for? There's not anything to be executed left
1698 if(!$(this.handles
[i
]).length
)
1704 //TODO: make renderAxis a prototype function
1705 this._renderAxis(this.element
);
1707 this._handles
= $('.ui-resizable-handle', this.element
)
1708 .disableSelection();
1710 //Matching axis name
1711 this._handles
.mouseover(function() {
1712 if (!self
.resizing
) {
1714 var axis
= this.className
.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
1715 //Axis, default = se
1716 self
.axis
= axis
&& axis
[1] ? axis
[1] : 'se';
1720 //If we want to auto hide the elements
1722 this._handles
.hide();
1724 .addClass("ui-resizable-autohide")
1726 $(this).removeClass("ui-resizable-autohide");
1727 self
._handles
.show();
1730 if (!self
.resizing
) {
1731 $(this).addClass("ui-resizable-autohide");
1732 self
._handles
.hide();
1737 //Initialize the mouse interaction
1742 destroy: function() {
1744 this._mouseDestroy();
1746 var _destroy = function(exp
) {
1747 $(exp
).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
1748 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
1751 //TODO: Unwrap at same DOM position
1752 if (this.elementIsWrapper
) {
1753 _destroy(this.element
);
1754 var wrapper
= this.element
;
1755 wrapper
.parent().append(
1756 this.originalElement
.css({
1757 position
: wrapper
.css('position'),
1758 width
: wrapper
.outerWidth(),
1759 height
: wrapper
.outerHeight(),
1760 top
: wrapper
.css('top'),
1761 left
: wrapper
.css('left')
1766 this.originalElement
.css('resize', this.originalResizeStyle
);
1767 _destroy(this.originalElement
);
1771 _mouseCapture: function(event
) {
1774 for(var i
in this.handles
) {
1775 if($(this.handles
[i
])[0] == event
.target
) handle
= true;
1778 return this.options
.disabled
|| !!handle
;
1782 _mouseStart: function(event
) {
1784 var o
= this.options
, iniPos
= this.element
.position(), el
= this.element
;
1786 this.resizing
= true;
1787 this.documentScroll
= { top
: $(document
).scrollTop(), left
: $(document
).scrollLeft() };
1789 // bugfix for http://dev.jquery.com/ticket/1749
1790 if (el
.is('.ui-draggable') || (/absolute/).test(el
.css('position'))) {
1791 el
.css({ position
: 'absolute', top
: iniPos
.top
, left
: iniPos
.left
});
1794 //Opera fixing relative position
1795 if ($.browser
.opera
&& (/relative/).test(el
.css('position')))
1796 el
.css({ position
: 'relative', top
: 'auto', left
: 'auto' });
1798 this._renderProxy();
1800 var curleft
= num(this.helper
.css('left')), curtop
= num(this.helper
.css('top'));
1802 if (o
.containment
) {
1803 curleft
+= $(o
.containment
).scrollLeft() || 0;
1804 curtop
+= $(o
.containment
).scrollTop() || 0;
1807 //Store needed variables
1808 this.offset
= this.helper
.offset();
1809 this.position
= { left
: curleft
, top
: curtop
};
1810 this.size
= this._helper
? { width
: el
.outerWidth(), height
: el
.outerHeight() } : { width
: el
.width(), height
: el
.height() };
1811 this.originalSize
= this._helper
? { width
: el
.outerWidth(), height
: el
.outerHeight() } : { width
: el
.width(), height
: el
.height() };
1812 this.originalPosition
= { left
: curleft
, top
: curtop
};
1813 this.sizeDiff
= { width
: el
.outerWidth() - el
.width(), height
: el
.outerHeight() - el
.height() };
1814 this.originalMousePosition
= { left
: event
.pageX
, top
: event
.pageY
};
1817 this.aspectRatio
= (typeof o
.aspectRatio
== 'number') ? o
.aspectRatio
: ((this.originalSize
.width
/ this.originalSize
.height
) || 1);
1819 var cursor
= $('.ui-resizable-' + this.axis
).css('cursor');
1820 $('body').css('cursor', cursor
== 'auto' ? this.axis
+ '-resize' : cursor
);
1822 el
.addClass("ui-resizable-resizing");
1823 this._propagate("start", event
);
1827 _mouseDrag: function(event
) {
1829 //Increase performance, avoid regex
1830 var el
= this.helper
, o
= this.options
, props
= {},
1831 self
= this, smp
= this.originalMousePosition
, a
= this.axis
;
1833 var dx
= (event
.pageX
-smp
.left
)||0, dy
= (event
.pageY
-smp
.top
)||0;
1834 var trigger
= this._change
[a
];
1835 if (!trigger
) return false;
1837 // Calculate the attrs that will be change
1838 var data
= trigger
.apply(this, [event
, dx
, dy
]), ie6
= $.browser
.msie
&& $.browser
.version
< 7, csdif
= this.sizeDiff
;
1840 if (this._aspectRatio
|| event
.shiftKey
)
1841 data
= this._updateRatio(data
, event
);
1843 data
= this._respectSize(data
, event
);
1845 // plugins callbacks need to be called first
1846 this._propagate("resize", event
);
1849 top
: this.position
.top
+ "px", left
: this.position
.left
+ "px",
1850 width
: this.size
.width
+ "px", height
: this.size
.height
+ "px"
1853 if (!this._helper
&& this._proportionallyResizeElements
.length
)
1854 this._proportionallyResize();
1856 this._updateCache(data
);
1858 // calling the user callback at the end
1859 this._trigger('resize', event
, this.ui());
1864 _mouseStop: function(event
) {
1866 this.resizing
= false;
1867 var o
= this.options
, self
= this;
1870 var pr
= this._proportionallyResizeElements
, ista
= pr
.length
&& (/textarea/i).test(pr
[0].nodeName
),
1871 soffseth
= ista
&& $.ui
.hasScroll(pr
[0], 'left') /* TODO - jump height */ ? 0 : self
.sizeDiff
.height
,
1872 soffsetw
= ista
? 0 : self
.sizeDiff
.width
;
1874 var s
= { width
: (self
.size
.width
- soffsetw
), height
: (self
.size
.height
- soffseth
) },
1875 left
= (parseInt(self
.element
.css('left'), 10) + (self
.position
.left
- self
.originalPosition
.left
)) || null,
1876 top
= (parseInt(self
.element
.css('top'), 10) + (self
.position
.top
- self
.originalPosition
.top
)) || null;
1879 this.element
.css($.extend(s
, { top
: top
, left
: left
}));
1881 self
.helper
.height(self
.size
.height
);
1882 self
.helper
.width(self
.size
.width
);
1884 if (this._helper
&& !o
.animate
) this._proportionallyResize();
1887 $('body').css('cursor', 'auto');
1889 this.element
.removeClass("ui-resizable-resizing");
1891 this._propagate("stop", event
);
1893 if (this._helper
) this.helper
.remove();
1898 _updateCache: function(data
) {
1899 var o
= this.options
;
1900 this.offset
= this.helper
.offset();
1901 if (isNumber(data
.left
)) this.position
.left
= data
.left
;
1902 if (isNumber(data
.top
)) this.position
.top
= data
.top
;
1903 if (isNumber(data
.height
)) this.size
.height
= data
.height
;
1904 if (isNumber(data
.width
)) this.size
.width
= data
.width
;
1907 _updateRatio: function(data
, event
) {
1909 var o
= this.options
, cpos
= this.position
, csize
= this.size
, a
= this.axis
;
1911 if (data
.height
) data
.width
= (csize
.height
* this.aspectRatio
);
1912 else if (data
.width
) data
.height
= (csize
.width
/ this.aspectRatio
);
1915 data
.left
= cpos
.left
+ (csize
.width
- data
.width
);
1919 data
.top
= cpos
.top
+ (csize
.height
- data
.height
);
1920 data
.left
= cpos
.left
+ (csize
.width
- data
.width
);
1926 _respectSize: function(data
, event
) {
1928 var el
= this.helper
, o
= this.options
, pRatio
= this._aspectRatio
|| event
.shiftKey
, a
= this.axis
,
1929 ismaxw
= isNumber(data
.width
) && o
.maxWidth
&& (o
.maxWidth
< data
.width
), ismaxh
= isNumber(data
.height
) && o
.maxHeight
&& (o
.maxHeight
< data
.height
),
1930 isminw
= isNumber(data
.width
) && o
.minWidth
&& (o
.minWidth
> data
.width
), isminh
= isNumber(data
.height
) && o
.minHeight
&& (o
.minHeight
> data
.height
);
1932 if (isminw
) data
.width
= o
.minWidth
;
1933 if (isminh
) data
.height
= o
.minHeight
;
1934 if (ismaxw
) data
.width
= o
.maxWidth
;
1935 if (ismaxh
) data
.height
= o
.maxHeight
;
1937 var dw
= this.originalPosition
.left
+ this.originalSize
.width
, dh
= this.position
.top
+ this.size
.height
;
1938 var cw
= /sw|nw|w/.test(a
), ch
= /nw|ne|n/.test(a
);
1940 if (isminw
&& cw
) data
.left
= dw
- o
.minWidth
;
1941 if (ismaxw
&& cw
) data
.left
= dw
- o
.maxWidth
;
1942 if (isminh
&& ch
) data
.top
= dh
- o
.minHeight
;
1943 if (ismaxh
&& ch
) data
.top
= dh
- o
.maxHeight
;
1945 // fixing jump error on top/left - bug #2330
1946 var isNotwh
= !data
.width
&& !data
.height
;
1947 if (isNotwh
&& !data
.left
&& data
.top
) data
.top
= null;
1948 else if (isNotwh
&& !data
.top
&& data
.left
) data
.left
= null;
1953 _proportionallyResize: function() {
1955 var o
= this.options
;
1956 if (!this._proportionallyResizeElements
.length
) return;
1957 var element
= this.helper
|| this.element
;
1959 for (var i
=0; i
< this._proportionallyResizeElements
.length
; i
++) {
1961 var prel
= this._proportionallyResizeElements
[i
];
1963 if (!this.borderDif
) {
1964 var b
= [prel
.css('borderTopWidth'), prel
.css('borderRightWidth'), prel
.css('borderBottomWidth'), prel
.css('borderLeftWidth')],
1965 p
= [prel
.css('paddingTop'), prel
.css('paddingRight'), prel
.css('paddingBottom'), prel
.css('paddingLeft')];
1967 this.borderDif
= $.map(b
, function(v
, i
) {
1968 var border
= parseInt(v
,10)||0, padding
= parseInt(p
[i
],10)||0;
1969 return border
+ padding
;
1973 if ($.browser
.msie
&& !(!($(element
).is(':hidden') || $(element
).parents(':hidden').length
)))
1977 height
: (element
.height() - this.borderDif
[0] - this.borderDif
[2]) || 0,
1978 width
: (element
.width() - this.borderDif
[1] - this.borderDif
[3]) || 0
1985 _renderProxy: function() {
1987 var el
= this.element
, o
= this.options
;
1988 this.elementOffset
= el
.offset();
1992 this.helper
= this.helper
|| $('<div style="overflow:hidden;"></div>');
1994 // fix ie6 offset TODO: This seems broken
1995 var ie6
= $.browser
.msie
&& $.browser
.version
< 7, ie6offset
= (ie6
? 1 : 0),
1996 pxyoffset
= ( ie6
? 2 : -1 );
1998 this.helper
.addClass(this._helper
).css({
1999 width
: this.element
.outerWidth() + pxyoffset
,
2000 height
: this.element
.outerHeight() + pxyoffset
,
2001 position
: 'absolute',
2002 left
: this.elementOffset
.left
- ie6offset
+'px',
2003 top
: this.elementOffset
.top
- ie6offset
+'px',
2004 zIndex
: ++o
.zIndex
//TODO: Don't modify option
2009 .disableSelection();
2012 this.helper
= this.element
;
2018 e: function(event
, dx
, dy
) {
2019 return { width
: this.originalSize
.width
+ dx
};
2021 w: function(event
, dx
, dy
) {
2022 var o
= this.options
, cs
= this.originalSize
, sp
= this.originalPosition
;
2023 return { left
: sp
.left
+ dx
, width
: cs
.width
- dx
};
2025 n: function(event
, dx
, dy
) {
2026 var o
= this.options
, cs
= this.originalSize
, sp
= this.originalPosition
;
2027 return { top
: sp
.top
+ dy
, height
: cs
.height
- dy
};
2029 s: function(event
, dx
, dy
) {
2030 return { height
: this.originalSize
.height
+ dy
};
2032 se: function(event
, dx
, dy
) {
2033 return $.extend(this._change
.s
.apply(this, arguments
), this._change
.e
.apply(this, [event
, dx
, dy
]));
2035 sw: function(event
, dx
, dy
) {
2036 return $.extend(this._change
.s
.apply(this, arguments
), this._change
.w
.apply(this, [event
, dx
, dy
]));
2038 ne: function(event
, dx
, dy
) {
2039 return $.extend(this._change
.n
.apply(this, arguments
), this._change
.e
.apply(this, [event
, dx
, dy
]));
2041 nw: function(event
, dx
, dy
) {
2042 return $.extend(this._change
.n
.apply(this, arguments
), this._change
.w
.apply(this, [event
, dx
, dy
]));
2046 _propagate: function(n
, event
) {
2047 $.ui
.plugin
.call(this, n
, [event
, this.ui()]);
2048 (n
!= "resize" && this._trigger(n
, event
, this.ui()));
2055 originalElement
: this.originalElement
,
2056 element
: this.element
,
2057 helper
: this.helper
,
2058 position
: this.position
,
2060 originalSize
: this.originalSize
,
2061 originalPosition
: this.originalPosition
2067 $.extend($.ui
.resizable
, {
2069 eventPrefix
: "resize",
2073 animateDuration
: "slow",
2074 animateEasing
: "swing",
2077 cancel
: ":input,option",
2094 * Resizable Extensions
2097 $.ui
.plugin
.add("resizable", "alsoResize", {
2099 start: function(event
, ui
) {
2101 var self
= $(this).data("resizable"), o
= self
.options
;
2103 _store = function(exp
) {
2104 $(exp
).each(function() {
2105 $(this).data("resizable-alsoresize", {
2106 width
: parseInt($(this).width(), 10), height
: parseInt($(this).height(), 10),
2107 left
: parseInt($(this).css('left'), 10), top
: parseInt($(this).css('top'), 10)
2112 if (typeof(o
.alsoResize
) == 'object' && !o
.alsoResize
.parentNode
) {
2113 if (o
.alsoResize
.length
) { o
.alsoResize
= o
.alsoResize
[0]; _store(o
.alsoResize
); }
2114 else { $.each(o
.alsoResize
, function(exp
, c
) { _store(exp
); }); }
2116 _store(o
.alsoResize
);
2120 resize: function(event
, ui
){
2121 var self
= $(this).data("resizable"), o
= self
.options
, os
= self
.originalSize
, op
= self
.originalPosition
;
2124 height
: (self
.size
.height
- os
.height
) || 0, width
: (self
.size
.width
- os
.width
) || 0,
2125 top
: (self
.position
.top
- op
.top
) || 0, left
: (self
.position
.left
- op
.left
) || 0
2128 _alsoResize = function(exp
, c
) {
2129 $(exp
).each(function() {
2130 var el
= $(this), start
= $(this).data("resizable-alsoresize"), style
= {}, css
= c
&& c
.length
? c
: ['width', 'height', 'top', 'left'];
2132 $.each(css
|| ['width', 'height', 'top', 'left'], function(i
, prop
) {
2133 var sum
= (start
[prop
]||0) + (delta
[prop
]||0);
2134 if (sum
&& sum
>= 0)
2135 style
[prop
] = sum
|| null;
2138 //Opera fixing relative position
2139 if (/relative/.test(el
.css('position')) && $.browser
.opera
) {
2140 self
._revertToRelativePosition
= true;
2141 el
.css({ position
: 'absolute', top
: 'auto', left
: 'auto' });
2148 if (typeof(o
.alsoResize
) == 'object' && !o
.alsoResize
.nodeType
) {
2149 $.each(o
.alsoResize
, function(exp
, c
) { _alsoResize(exp
, c
); });
2151 _alsoResize(o
.alsoResize
);
2155 stop: function(event
, ui
){
2156 var self
= $(this).data("resizable");
2158 //Opera fixing relative position
2159 if (self
._revertToRelativePosition
&& $.browser
.opera
) {
2160 self
._revertToRelativePosition
= false;
2161 el
.css({ position
: 'relative' });
2164 $(this).removeData("resizable-alsoresize-start");
2168 $.ui
.plugin
.add("resizable", "animate", {
2170 stop: function(event
, ui
) {
2171 var self
= $(this).data("resizable"), o
= self
.options
;
2173 var pr
= self
._proportionallyResizeElements
, ista
= pr
.length
&& (/textarea/i).test(pr
[0].nodeName
),
2174 soffseth
= ista
&& $.ui
.hasScroll(pr
[0], 'left') /* TODO - jump height */ ? 0 : self
.sizeDiff
.height
,
2175 soffsetw
= ista
? 0 : self
.sizeDiff
.width
;
2177 var style
= { width
: (self
.size
.width
- soffsetw
), height
: (self
.size
.height
- soffseth
) },
2178 left
= (parseInt(self
.element
.css('left'), 10) + (self
.position
.left
- self
.originalPosition
.left
)) || null,
2179 top
= (parseInt(self
.element
.css('top'), 10) + (self
.position
.top
- self
.originalPosition
.top
)) || null;
2181 self
.element
.animate(
2182 $.extend(style
, top
&& left
? { top
: top
, left
: left
} : {}), {
2183 duration
: o
.animateDuration
,
2184 easing
: o
.animateEasing
,
2188 width
: parseInt(self
.element
.css('width'), 10),
2189 height
: parseInt(self
.element
.css('height'), 10),
2190 top
: parseInt(self
.element
.css('top'), 10),
2191 left
: parseInt(self
.element
.css('left'), 10)
2194 if (pr
&& pr
.length
) $(pr
[0]).css({ width
: data
.width
, height
: data
.height
});
2196 // propagating resize, and updating values for each animation step
2197 self
._updateCache(data
);
2198 self
._propagate("resize", event
);
2207 $.ui
.plugin
.add("resizable", "containment", {
2209 start: function(event
, ui
) {
2210 var self
= $(this).data("resizable"), o
= self
.options
, el
= self
.element
;
2211 var oc
= o
.containment
, ce
= (oc
instanceof $) ? oc
.get(0) : (/parent/.test(oc
)) ? el
.parent().get(0) : oc
;
2214 self
.containerElement
= $(ce
);
2216 if (/document/.test(oc
) || oc
== document
) {
2217 self
.containerOffset
= { left
: 0, top
: 0 };
2218 self
.containerPosition
= { left
: 0, top
: 0 };
2221 element
: $(document
), left
: 0, top
: 0,
2222 width
: $(document
).width(), height
: $(document
).height() || document
.body
.parentNode
.scrollHeight
2226 // i'm a node, so compute top, left, right, bottom
2228 var element
= $(ce
), p
= [];
2229 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i
, name
) { p
[i
] = num(element
.css("padding" + name
)); });
2231 self
.containerOffset
= element
.offset();
2232 self
.containerPosition
= element
.position();
2233 self
.containerSize
= { height
: (element
.innerHeight() - p
[3]), width
: (element
.innerWidth() - p
[1]) };
2235 var co
= self
.containerOffset
, ch
= self
.containerSize
.height
, cw
= self
.containerSize
.width
,
2236 width
= ($.ui
.hasScroll(ce
, "left") ? ce
.scrollWidth
: cw
), height
= ($.ui
.hasScroll(ce
) ? ce
.scrollHeight
: ch
);
2239 element
: ce
, left
: co
.left
, top
: co
.top
, width
: width
, height
: height
2244 resize: function(event
, ui
) {
2245 var self
= $(this).data("resizable"), o
= self
.options
,
2246 ps
= self
.containerSize
, co
= self
.containerOffset
, cs
= self
.size
, cp
= self
.position
,
2247 pRatio
= self
._aspectRatio
|| event
.shiftKey
, cop
= { top
:0, left
:0 }, ce
= self
.containerElement
;
2249 if (ce
[0] != document
&& (/static/).test(ce
.css('position'))) cop
= co
;
2251 if (cp
.left
< (self
._helper
? co
.left
: 0)) {
2252 self
.size
.width
= self
.size
.width
+ (self
._helper
? (self
.position
.left
- co
.left
) : (self
.position
.left
- cop
.left
));
2253 if (pRatio
) self
.size
.height
= self
.size
.width
/ o
.aspectRatio
;
2254 self
.position
.left
= o
.helper
? co
.left
: 0;
2257 if (cp
.top
< (self
._helper
? co
.top
: 0)) {
2258 self
.size
.height
= self
.size
.height
+ (self
._helper
? (self
.position
.top
- co
.top
) : self
.position
.top
);
2259 if (pRatio
) self
.size
.width
= self
.size
.height
* o
.aspectRatio
;
2260 self
.position
.top
= self
._helper
? co
.top
: 0;
2263 self
.offset
.left
= self
.parentData
.left
+self
.position
.left
;
2264 self
.offset
.top
= self
.parentData
.top
+self
.position
.top
;
2266 var woset
= Math
.abs( (self
._helper
? self
.offset
.left
- cop
.left
: (self
.offset
.left
- cop
.left
)) + self
.sizeDiff
.width
),
2267 hoset
= Math
.abs( (self
._helper
? self
.offset
.top
- cop
.top
: (self
.offset
.top
- co
.top
)) + self
.sizeDiff
.height
);
2269 var isParent
= self
.containerElement
.get(0) == self
.element
.parent().get(0),
2270 isOffsetRelative
= /relative|absolute/.test(self
.containerElement
.css('position'));
2272 if(isParent
&& isOffsetRelative
) woset
-= self
.parentData
.left
;
2274 if (woset
+ self
.size
.width
>= self
.parentData
.width
) {
2275 self
.size
.width
= self
.parentData
.width
- woset
;
2276 if (pRatio
) self
.size
.height
= self
.size
.width
/ self
.aspectRatio
;
2279 if (hoset
+ self
.size
.height
>= self
.parentData
.height
) {
2280 self
.size
.height
= self
.parentData
.height
- hoset
;
2281 if (pRatio
) self
.size
.width
= self
.size
.height
* self
.aspectRatio
;
2285 stop: function(event
, ui
){
2286 var self
= $(this).data("resizable"), o
= self
.options
, cp
= self
.position
,
2287 co
= self
.containerOffset
, cop
= self
.containerPosition
, ce
= self
.containerElement
;
2289 var helper
= $(self
.helper
), ho
= helper
.offset(), w
= helper
.outerWidth() - self
.sizeDiff
.width
, h
= helper
.outerHeight() - self
.sizeDiff
.height
;
2291 if (self
._helper
&& !o
.animate
&& (/relative/).test(ce
.css('position')))
2292 $(this).css({ left
: ho
.left
- cop
.left
- co
.left
, width
: w
, height
: h
});
2294 if (self
._helper
&& !o
.animate
&& (/static/).test(ce
.css('position')))
2295 $(this).css({ left
: ho
.left
- cop
.left
- co
.left
, width
: w
, height
: h
});
2300 $.ui
.plugin
.add("resizable", "ghost", {
2302 start: function(event
, ui
) {
2304 var self
= $(this).data("resizable"), o
= self
.options
, cs
= self
.size
;
2306 self
.ghost
= self
.originalElement
.clone();
2308 .css({ opacity
: .25, display
: 'block', position
: 'relative', height
: cs
.height
, width
: cs
.width
, margin
: 0, left
: 0, top
: 0 })
2309 .addClass('ui-resizable-ghost')
2310 .addClass(typeof o
.ghost
== 'string' ? o
.ghost
: '');
2312 self
.ghost
.appendTo(self
.helper
);
2316 resize: function(event
, ui
){
2317 var self
= $(this).data("resizable"), o
= self
.options
;
2318 if (self
.ghost
) self
.ghost
.css({ position
: 'relative', height
: self
.size
.height
, width
: self
.size
.width
});
2321 stop: function(event
, ui
){
2322 var self
= $(this).data("resizable"), o
= self
.options
;
2323 if (self
.ghost
&& self
.helper
) self
.helper
.get(0).removeChild(self
.ghost
.get(0));
2328 $.ui
.plugin
.add("resizable", "grid", {
2330 resize: function(event
, ui
) {
2331 var self
= $(this).data("resizable"), o
= self
.options
, cs
= self
.size
, os
= self
.originalSize
, op
= self
.originalPosition
, a
= self
.axis
, ratio
= o
._aspectRatio
|| event
.shiftKey
;
2332 o
.grid
= typeof o
.grid
== "number" ? [o
.grid
, o
.grid
] : o
.grid
;
2333 var ox
= Math
.round((cs
.width
- os
.width
) / (o
.grid
[0]||1)) * (o
.grid
[0]||1), oy
= Math
.round((cs
.height
- os
.height
) / (o
.grid
[1]||1)) * (o
.grid
[1]||1);
2335 if (/^(se|s|e)$/.test(a
)) {
2336 self
.size
.width
= os
.width
+ ox
;
2337 self
.size
.height
= os
.height
+ oy
;
2339 else if (/^(ne)$/.test(a
)) {
2340 self
.size
.width
= os
.width
+ ox
;
2341 self
.size
.height
= os
.height
+ oy
;
2342 self
.position
.top
= op
.top
- oy
;
2344 else if (/^(sw)$/.test(a
)) {
2345 self
.size
.width
= os
.width
+ ox
;
2346 self
.size
.height
= os
.height
+ oy
;
2347 self
.position
.left
= op
.left
- ox
;
2350 self
.size
.width
= os
.width
+ ox
;
2351 self
.size
.height
= os
.height
+ oy
;
2352 self
.position
.top
= op
.top
- oy
;
2353 self
.position
.left
= op
.left
- ox
;
2359 var num = function(v
) {
2360 return parseInt(v
, 10) || 0;
2363 var isNumber = function(value
) {
2364 return !isNaN(parseInt(value
, 10));
2369 * jQuery UI Selectable 1.7.1
2371 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
2372 * Dual licensed under the MIT (MIT-LICENSE.txt)
2373 * and GPL (GPL-LICENSE.txt) licenses.
2375 * http://docs.jquery.com/UI/Selectables
2382 $.widget("ui.selectable", $.extend({}, $.ui
.mouse
, {
2387 this.element
.addClass("ui-selectable");
2389 this.dragged
= false;
2391 // cache selectee children based on filter
2393 this.refresh = function() {
2394 selectees
= $(self
.options
.filter
, self
.element
[0]);
2395 selectees
.each(function() {
2396 var $this = $(this);
2397 var pos
= $this.offset();
2398 $.data(this, "selectable-item", {
2403 right
: pos
.left
+ $this.outerWidth(),
2404 bottom
: pos
.top
+ $this.outerHeight(),
2405 startselected
: false,
2406 selected
: $this.hasClass('ui-selected'),
2407 selecting
: $this.hasClass('ui-selecting'),
2408 unselecting
: $this.hasClass('ui-unselecting')
2414 this.selectees
= selectees
.addClass("ui-selectee");
2418 this.helper
= $(document
.createElement('div'))
2419 .css({border
:'1px dotted black'})
2420 .addClass("ui-selectable-helper");
2423 destroy: function() {
2425 .removeClass("ui-selectable ui-selectable-disabled")
2426 .removeData("selectable")
2427 .unbind(".selectable");
2428 this._mouseDestroy();
2431 _mouseStart: function(event
) {
2434 this.opos
= [event
.pageX
, event
.pageY
];
2436 if (this.options
.disabled
)
2439 var options
= this.options
;
2441 this.selectees
= $(options
.filter
, this.element
[0]);
2443 this._trigger("start", event
);
2445 $(options
.appendTo
).append(this.helper
);
2446 // position helper (lasso)
2449 "position": "absolute",
2450 "left": event
.clientX
,
2451 "top": event
.clientY
,
2456 if (options
.autoRefresh
) {
2460 this.selectees
.filter('.ui-selected').each(function() {
2461 var selectee
= $.data(this, "selectable-item");
2462 selectee
.startselected
= true;
2463 if (!event
.metaKey
) {
2464 selectee
.$element
.removeClass('ui-selected');
2465 selectee
.selected
= false;
2466 selectee
.$element
.addClass('ui-unselecting');
2467 selectee
.unselecting
= true;
2468 // selectable UNSELECTING callback
2469 self
._trigger("unselecting", event
, {
2470 unselecting
: selectee
.element
2475 $(event
.target
).parents().andSelf().each(function() {
2476 var selectee
= $.data(this, "selectable-item");
2478 selectee
.$element
.removeClass("ui-unselecting").addClass('ui-selecting');
2479 selectee
.unselecting
= false;
2480 selectee
.selecting
= true;
2481 selectee
.selected
= true;
2482 // selectable SELECTING callback
2483 self
._trigger("selecting", event
, {
2484 selecting
: selectee
.element
2492 _mouseDrag: function(event
) {
2494 this.dragged
= true;
2496 if (this.options
.disabled
)
2499 var options
= this.options
;
2501 var x1
= this.opos
[0], y1
= this.opos
[1], x2
= event
.pageX
, y2
= event
.pageY
;
2502 if (x1
> x2
) { var tmp
= x2
; x2
= x1
; x1
= tmp
; }
2503 if (y1
> y2
) { var tmp
= y2
; y2
= y1
; y1
= tmp
; }
2504 this.helper
.css({left
: x1
, top
: y1
, width
: x2
-x1
, height
: y2
-y1
});
2506 this.selectees
.each(function() {
2507 var selectee
= $.data(this, "selectable-item");
2508 //prevent helper from being selected if appendTo: selectable
2509 if (!selectee
|| selectee
.element
== self
.element
[0])
2512 if (options
.tolerance
== 'touch') {
2513 hit
= ( !(selectee
.left
> x2
|| selectee
.right
< x1
|| selectee
.top
> y2
|| selectee
.bottom
< y1
) );
2514 } else if (options
.tolerance
== 'fit') {
2515 hit
= (selectee
.left
> x1
&& selectee
.right
< x2
&& selectee
.top
> y1
&& selectee
.bottom
< y2
);
2520 if (selectee
.selected
) {
2521 selectee
.$element
.removeClass('ui-selected');
2522 selectee
.selected
= false;
2524 if (selectee
.unselecting
) {
2525 selectee
.$element
.removeClass('ui-unselecting');
2526 selectee
.unselecting
= false;
2528 if (!selectee
.selecting
) {
2529 selectee
.$element
.addClass('ui-selecting');
2530 selectee
.selecting
= true;
2531 // selectable SELECTING callback
2532 self
._trigger("selecting", event
, {
2533 selecting
: selectee
.element
2538 if (selectee
.selecting
) {
2539 if (event
.metaKey
&& selectee
.startselected
) {
2540 selectee
.$element
.removeClass('ui-selecting');
2541 selectee
.selecting
= false;
2542 selectee
.$element
.addClass('ui-selected');
2543 selectee
.selected
= true;
2545 selectee
.$element
.removeClass('ui-selecting');
2546 selectee
.selecting
= false;
2547 if (selectee
.startselected
) {
2548 selectee
.$element
.addClass('ui-unselecting');
2549 selectee
.unselecting
= true;
2551 // selectable UNSELECTING callback
2552 self
._trigger("unselecting", event
, {
2553 unselecting
: selectee
.element
2557 if (selectee
.selected
) {
2558 if (!event
.metaKey
&& !selectee
.startselected
) {
2559 selectee
.$element
.removeClass('ui-selected');
2560 selectee
.selected
= false;
2562 selectee
.$element
.addClass('ui-unselecting');
2563 selectee
.unselecting
= true;
2564 // selectable UNSELECTING callback
2565 self
._trigger("unselecting", event
, {
2566 unselecting
: selectee
.element
2576 _mouseStop: function(event
) {
2579 this.dragged
= false;
2581 var options
= this.options
;
2583 $('.ui-unselecting', this.element
[0]).each(function() {
2584 var selectee
= $.data(this, "selectable-item");
2585 selectee
.$element
.removeClass('ui-unselecting');
2586 selectee
.unselecting
= false;
2587 selectee
.startselected
= false;
2588 self
._trigger("unselected", event
, {
2589 unselected
: selectee
.element
2592 $('.ui-selecting', this.element
[0]).each(function() {
2593 var selectee
= $.data(this, "selectable-item");
2594 selectee
.$element
.removeClass('ui-selecting').addClass('ui-selected');
2595 selectee
.selecting
= false;
2596 selectee
.selected
= true;
2597 selectee
.startselected
= true;
2598 self
._trigger("selected", event
, {
2599 selected
: selectee
.element
2602 this._trigger("stop", event
);
2604 this.helper
.remove();
2611 $.extend($.ui
.selectable
, {
2616 cancel
: ":input,option",
2626 * jQuery UI Sortable 1.7.1
2628 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
2629 * Dual licensed under the MIT (MIT-LICENSE.txt)
2630 * and GPL (GPL-LICENSE.txt) licenses.
2632 * http://docs.jquery.com/UI/Sortables
2639 $.widget("ui.sortable", $.extend({}, $.ui
.mouse
, {
2642 var o
= this.options
;
2643 this.containerCache
= {};
2644 this.element
.addClass("ui-sortable");
2649 //Let's determine if the items are floating
2650 this.floating
= this.items
.length
? (/left|right/).test(this.items
[0].item
.css('float')) : false;
2652 //Let's determine the parent's offset
2653 this.offset
= this.element
.offset();
2655 //Initialize mouse events for interaction
2660 destroy: function() {
2662 .removeClass("ui-sortable ui-sortable-disabled")
2663 .removeData("sortable")
2664 .unbind(".sortable");
2665 this._mouseDestroy();
2667 for ( var i
= this.items
.length
- 1; i
>= 0; i
-- )
2668 this.items
[i
].item
.removeData("sortable-item");
2671 _mouseCapture: function(event
, overrideHandle
) {
2673 if (this.reverting
) {
2677 if(this.options
.disabled
|| this.options
.type
== 'static') return false;
2679 //We have to refresh the items data once first
2680 this._refreshItems(event
);
2682 //Find out if the clicked node (or one of its parents) is a actual item in this.items
2683 var currentItem
= null, self
= this, nodes
= $(event
.target
).parents().each(function() {
2684 if($.data(this, 'sortable-item') == self
) {
2685 currentItem
= $(this);
2689 if($.data(event
.target
, 'sortable-item') == self
) currentItem
= $(event
.target
);
2691 if(!currentItem
) return false;
2692 if(this.options
.handle
&& !overrideHandle
) {
2693 var validHandle
= false;
2695 $(this.options
.handle
, currentItem
).find("*").andSelf().each(function() { if(this == event
.target
) validHandle
= true; });
2696 if(!validHandle
) return false;
2699 this.currentItem
= currentItem
;
2700 this._removeCurrentsFromItems();
2705 _mouseStart: function(event
, overrideHandle
, noActivation
) {
2707 var o
= this.options
, self
= this;
2708 this.currentContainer
= this;
2710 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
2711 this.refreshPositions();
2713 //Create and append the visible helper
2714 this.helper
= this._createHelper(event
);
2716 //Cache the helper size
2717 this._cacheHelperProportions();
2720 * - Position generation -
2721 * This block generates everything position related - it's the core of draggables.
2724 //Cache the margins of the original element
2725 this._cacheMargins();
2727 //Get the next scrolling parent
2728 this.scrollParent
= this.helper
.scrollParent();
2730 //The element's absolute position on the page minus margins
2731 this.offset
= this.currentItem
.offset();
2733 top
: this.offset
.top
- this.margins
.top
,
2734 left
: this.offset
.left
- this.margins
.left
2737 // Only after we got the offset, we can change the helper's position to absolute
2738 // TODO: Still need to figure out a way to make relative sorting possible
2739 this.helper
.css("position", "absolute");
2740 this.cssPosition
= this.helper
.css("position");
2742 $.extend(this.offset
, {
2743 click
: { //Where the click happened, relative to the element
2744 left
: event
.pageX
- this.offset
.left
,
2745 top
: event
.pageY
- this.offset
.top
2747 parent
: this._getParentOffset(),
2748 relative
: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
2751 //Generate the original position
2752 this.originalPosition
= this._generatePosition(event
);
2753 this.originalPageX
= event
.pageX
;
2754 this.originalPageY
= event
.pageY
;
2756 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
2758 this._adjustOffsetFromHelper(o
.cursorAt
);
2760 //Cache the former DOM position
2761 this.domPosition
= { prev
: this.currentItem
.prev()[0], parent
: this.currentItem
.parent()[0] };
2763 //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
2764 if(this.helper
[0] != this.currentItem
[0]) {
2765 this.currentItem
.hide();
2768 //Create the placeholder
2769 this._createPlaceholder();
2771 //Set a containment if given in the options
2773 this._setContainment();
2775 if(o
.cursor
) { // cursor option
2776 if ($('body').css("cursor")) this._storedCursor
= $('body').css("cursor");
2777 $('body').css("cursor", o
.cursor
);
2780 if(o
.opacity
) { // opacity option
2781 if (this.helper
.css("opacity")) this._storedOpacity
= this.helper
.css("opacity");
2782 this.helper
.css("opacity", o
.opacity
);
2785 if(o
.zIndex
) { // zIndex option
2786 if (this.helper
.css("zIndex")) this._storedZIndex
= this.helper
.css("zIndex");
2787 this.helper
.css("zIndex", o
.zIndex
);
2791 if(this.scrollParent
[0] != document
&& this.scrollParent
[0].tagName
!= 'HTML')
2792 this.overflowOffset
= this.scrollParent
.offset();
2795 this._trigger("start", event
, this._uiHash());
2797 //Recache the helper size
2798 if(!this._preserveHelperProportions
)
2799 this._cacheHelperProportions();
2802 //Post 'activate' events to possible containers
2804 for (var i
= this.containers
.length
- 1; i
>= 0; i
--) { this.containers
[i
]._trigger("activate", event
, self
._uiHash(this)); }
2807 //Prepare possible droppables
2809 $.ui
.ddmanager
.current
= this;
2811 if ($.ui
.ddmanager
&& !o
.dropBehaviour
)
2812 $.ui
.ddmanager
.prepareOffsets(this, event
);
2814 this.dragging
= true;
2816 this.helper
.addClass("ui-sortable-helper");
2817 this._mouseDrag(event
); //Execute the drag once - this causes the helper not to be visible before getting its correct position
2822 _mouseDrag: function(event
) {
2824 //Compute the helpers position
2825 this.position
= this._generatePosition(event
);
2826 this.positionAbs
= this._convertPositionTo("absolute");
2828 if (!this.lastPositionAbs
) {
2829 this.lastPositionAbs
= this.positionAbs
;
2833 if(this.options
.scroll
) {
2834 var o
= this.options
, scrolled
= false;
2835 if(this.scrollParent
[0] != document
&& this.scrollParent
[0].tagName
!= 'HTML') {
2837 if((this.overflowOffset
.top
+ this.scrollParent
[0].offsetHeight
) - event
.pageY
< o
.scrollSensitivity
)
2838 this.scrollParent
[0].scrollTop
= scrolled
= this.scrollParent
[0].scrollTop
+ o
.scrollSpeed
;
2839 else if(event
.pageY
- this.overflowOffset
.top
< o
.scrollSensitivity
)
2840 this.scrollParent
[0].scrollTop
= scrolled
= this.scrollParent
[0].scrollTop
- o
.scrollSpeed
;
2842 if((this.overflowOffset
.left
+ this.scrollParent
[0].offsetWidth
) - event
.pageX
< o
.scrollSensitivity
)
2843 this.scrollParent
[0].scrollLeft
= scrolled
= this.scrollParent
[0].scrollLeft
+ o
.scrollSpeed
;
2844 else if(event
.pageX
- this.overflowOffset
.left
< o
.scrollSensitivity
)
2845 this.scrollParent
[0].scrollLeft
= scrolled
= this.scrollParent
[0].scrollLeft
- o
.scrollSpeed
;
2849 if(event
.pageY
- $(document
).scrollTop() < o
.scrollSensitivity
)
2850 scrolled
= $(document
).scrollTop($(document
).scrollTop() - o
.scrollSpeed
);
2851 else if($(window
).height() - (event
.pageY
- $(document
).scrollTop()) < o
.scrollSensitivity
)
2852 scrolled
= $(document
).scrollTop($(document
).scrollTop() + o
.scrollSpeed
);
2854 if(event
.pageX
- $(document
).scrollLeft() < o
.scrollSensitivity
)
2855 scrolled
= $(document
).scrollLeft($(document
).scrollLeft() - o
.scrollSpeed
);
2856 else if($(window
).width() - (event
.pageX
- $(document
).scrollLeft()) < o
.scrollSensitivity
)
2857 scrolled
= $(document
).scrollLeft($(document
).scrollLeft() + o
.scrollSpeed
);
2861 if(scrolled
!== false && $.ui
.ddmanager
&& !o
.dropBehaviour
)
2862 $.ui
.ddmanager
.prepareOffsets(this, event
);
2865 //Regenerate the absolute position used for position checks
2866 this.positionAbs
= this._convertPositionTo("absolute");
2868 //Set the helper position
2869 if(!this.options
.axis
|| this.options
.axis
!= "y") this.helper
[0].style
.left
= this.position
.left
+'px';
2870 if(!this.options
.axis
|| this.options
.axis
!= "x") this.helper
[0].style
.top
= this.position
.top
+'px';
2873 for (var i
= this.items
.length
- 1; i
>= 0; i
--) {
2875 //Cache variables and intersection, continue if no intersection
2876 var item
= this.items
[i
], itemElement
= item
.item
[0], intersection
= this._intersectsWithPointer(item
);
2877 if (!intersection
) continue;
2879 if(itemElement
!= this.currentItem
[0] //cannot intersect with itself
2880 && this.placeholder
[intersection
== 1 ? "next" : "prev"]()[0] != itemElement
//no useless actions that have been done before
2881 && !$.ui
.contains(this.placeholder
[0], itemElement
) //no action if the item moved is the parent of the item checked
2882 && (this.options
.type
== 'semi-dynamic' ? !$.ui
.contains(this.element
[0], itemElement
) : true)
2885 this.direction
= intersection
== 1 ? "down" : "up";
2887 if (this.options
.tolerance
== "pointer" || this._intersectsWithSides(item
)) {
2888 this._rearrange(event
, item
);
2893 this._trigger("change", event
, this._uiHash());
2898 //Post events to containers
2899 this._contactContainers(event
);
2901 //Interconnect with droppables
2902 if($.ui
.ddmanager
) $.ui
.ddmanager
.drag(this, event
);
2905 this._trigger('sort', event
, this._uiHash());
2907 this.lastPositionAbs
= this.positionAbs
;
2912 _mouseStop: function(event
, noPropagation
) {
2916 //If we are using droppables, inform the manager about the drop
2917 if ($.ui
.ddmanager
&& !this.options
.dropBehaviour
)
2918 $.ui
.ddmanager
.drop(this, event
);
2920 if(this.options
.revert
) {
2922 var cur
= self
.placeholder
.offset();
2924 self
.reverting
= true;
2926 $(this.helper
).animate({
2927 left
: cur
.left
- this.offset
.parent
.left
- self
.margins
.left
+ (this.offsetParent
[0] == document
.body
? 0 : this.offsetParent
[0].scrollLeft
),
2928 top
: cur
.top
- this.offset
.parent
.top
- self
.margins
.top
+ (this.offsetParent
[0] == document
.body
? 0 : this.offsetParent
[0].scrollTop
)
2929 }, parseInt(this.options
.revert
, 10) || 500, function() {
2933 this._clear(event
, noPropagation
);
2940 cancel: function() {
2948 if(this.options
.helper
== "original")
2949 this.currentItem
.css(this._storedCSS
).removeClass("ui-sortable-helper");
2951 this.currentItem
.show();
2953 //Post deactivating events to containers
2954 for (var i
= this.containers
.length
- 1; i
>= 0; i
--){
2955 this.containers
[i
]._trigger("deactivate", null, self
._uiHash(this));
2956 if(this.containers
[i
].containerCache
.over
) {
2957 this.containers
[i
]._trigger("out", null, self
._uiHash(this));
2958 this.containers
[i
].containerCache
.over
= 0;
2964 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
2965 if(this.placeholder
[0].parentNode
) this.placeholder
[0].parentNode
.removeChild(this.placeholder
[0]);
2966 if(this.options
.helper
!= "original" && this.helper
&& this.helper
[0].parentNode
) this.helper
.remove();
2975 if(this.domPosition
.prev
) {
2976 $(this.domPosition
.prev
).after(this.currentItem
);
2978 $(this.domPosition
.parent
).prepend(this.currentItem
);
2985 serialize: function(o
) {
2987 var items
= this._getItemsAsjQuery(o
&& o
.connected
);
2988 var str
= []; o
= o
|| {};
2990 $(items
).each(function() {
2991 var res
= ($(o
.item
|| this).attr(o
.attribute
|| 'id') || '').match(o
.expression
|| (/(.+)[-=_](.+)/));
2992 if(res
) str
.push((o
.key
|| res
[1]+'[]')+'='+(o
.key
&& o
.expression
? res
[1] : res
[2]));
2995 return str
.join('&');
2999 toArray: function(o
) {
3001 var items
= this._getItemsAsjQuery(o
&& o
.connected
);
3002 var ret
= []; o
= o
|| {};
3004 items
.each(function() { ret
.push($(o
.item
|| this).attr(o
.attribute
|| 'id') || ''); });
3009 /* Be careful with the following core functions */
3010 _intersectsWith: function(item
) {
3012 var x1
= this.positionAbs
.left
,
3013 x2
= x1
+ this.helperProportions
.width
,
3014 y1
= this.positionAbs
.top
,
3015 y2
= y1
+ this.helperProportions
.height
;
3020 b
= t
+ item
.height
;
3022 var dyClick
= this.offset
.click
.top
,
3023 dxClick
= this.offset
.click
.left
;
3025 var isOverElement
= (y1
+ dyClick
) > t
&& (y1
+ dyClick
) < b
&& (x1
+ dxClick
) > l
&& (x1
+ dxClick
) < r
;
3027 if( this.options
.tolerance
== "pointer"
3028 || this.options
.forcePointerForContainers
3029 || (this.options
.tolerance
!= "pointer" && this.helperProportions
[this.floating
? 'width' : 'height'] > item
[this.floating
? 'width' : 'height'])
3031 return isOverElement
;
3034 return (l
< x1
+ (this.helperProportions
.width
/ 2) // Right Half
3035 && x2
- (this.helperProportions
.width
/ 2) < r
// Left Half
3036 && t
< y1
+ (this.helperProportions
.height
/ 2) // Bottom Half
3037 && y2
- (this.helperProportions
.height
/ 2) < b
); // Top Half
3042 _intersectsWithPointer: function(item
) {
3044 var isOverElementHeight
= $.ui
.isOverAxis(this.positionAbs
.top
+ this.offset
.click
.top
, item
.top
, item
.height
),
3045 isOverElementWidth
= $.ui
.isOverAxis(this.positionAbs
.left
+ this.offset
.click
.left
, item
.left
, item
.width
),
3046 isOverElement
= isOverElementHeight
&& isOverElementWidth
,
3047 verticalDirection
= this._getDragVerticalDirection(),
3048 horizontalDirection
= this._getDragHorizontalDirection();
3053 return this.floating
?
3054 ( ((horizontalDirection
&& horizontalDirection
== "right") || verticalDirection
== "down") ? 2 : 1 )
3055 : ( verticalDirection
&& (verticalDirection
== "down" ? 2 : 1) );
3059 _intersectsWithSides: function(item
) {
3061 var isOverBottomHalf
= $.ui
.isOverAxis(this.positionAbs
.top
+ this.offset
.click
.top
, item
.top
+ (item
.height
/2), item
.height
),
3062 isOverRightHalf
= $.ui
.isOverAxis(this.positionAbs
.left
+ this.offset
.click
.left
, item
.left
+ (item
.width
/2), item
.width
),
3063 verticalDirection
= this._getDragVerticalDirection(),
3064 horizontalDirection
= this._getDragHorizontalDirection();
3066 if (this.floating
&& horizontalDirection
) {
3067 return ((horizontalDirection
== "right" && isOverRightHalf
) || (horizontalDirection
== "left" && !isOverRightHalf
));
3069 return verticalDirection
&& ((verticalDirection
== "down" && isOverBottomHalf
) || (verticalDirection
== "up" && !isOverBottomHalf
));
3074 _getDragVerticalDirection: function() {
3075 var delta
= this.positionAbs
.top
- this.lastPositionAbs
.top
;
3076 return delta
!= 0 && (delta
> 0 ? "down" : "up");
3079 _getDragHorizontalDirection: function() {
3080 var delta
= this.positionAbs
.left
- this.lastPositionAbs
.left
;
3081 return delta
!= 0 && (delta
> 0 ? "right" : "left");
3084 refresh: function(event
) {
3085 this._refreshItems(event
);
3086 this.refreshPositions();
3089 _connectWith: function() {
3090 var options
= this.options
;
3091 return options
.connectWith
.constructor == String
3092 ? [options
.connectWith
]
3093 : options
.connectWith
;
3096 _getItemsAsjQuery: function(connected
) {
3101 var connectWith
= this._connectWith();
3103 if(connectWith
&& connected
) {
3104 for (var i
= connectWith
.length
- 1; i
>= 0; i
--){
3105 var cur
= $(connectWith
[i
]);
3106 for (var j
= cur
.length
- 1; j
>= 0; j
--){
3107 var inst
= $.data(cur
[j
], 'sortable');
3108 if(inst
&& inst
!= this && !inst
.options
.disabled
) {
3109 queries
.push([$.isFunction(inst
.options
.items
) ? inst
.options
.items
.call(inst
.element
) : $(inst
.options
.items
, inst
.element
).not(".ui-sortable-helper"), inst
]);
3115 queries
.push([$.isFunction(this.options
.items
) ? this.options
.items
.call(this.element
, null, { options
: this.options
, item
: this.currentItem
}) : $(this.options
.items
, this.element
).not(".ui-sortable-helper"), this]);
3117 for (var i
= queries
.length
- 1; i
>= 0; i
--){
3118 queries
[i
][0].each(function() {
3127 _removeCurrentsFromItems: function() {
3129 var list
= this.currentItem
.find(":data(sortable-item)");
3131 for (var i
=0; i
< this.items
.length
; i
++) {
3133 for (var j
=0; j
< list
.length
; j
++) {
3134 if(list
[j
] == this.items
[i
].item
[0])
3135 this.items
.splice(i
,1);
3142 _refreshItems: function(event
) {
3145 this.containers
= [this];
3146 var items
= this.items
;
3148 var queries
= [[$.isFunction(this.options
.items
) ? this.options
.items
.call(this.element
[0], event
, { item
: this.currentItem
}) : $(this.options
.items
, this.element
), this]];
3149 var connectWith
= this._connectWith();
3152 for (var i
= connectWith
.length
- 1; i
>= 0; i
--){
3153 var cur
= $(connectWith
[i
]);
3154 for (var j
= cur
.length
- 1; j
>= 0; j
--){
3155 var inst
= $.data(cur
[j
], 'sortable');
3156 if(inst
&& inst
!= this && !inst
.options
.disabled
) {
3157 queries
.push([$.isFunction(inst
.options
.items
) ? inst
.options
.items
.call(inst
.element
[0], event
, { item
: this.currentItem
}) : $(inst
.options
.items
, inst
.element
), inst
]);
3158 this.containers
.push(inst
);
3164 for (var i
= queries
.length
- 1; i
>= 0; i
--) {
3165 var targetData
= queries
[i
][1];
3166 var _queries
= queries
[i
][0];
3168 for (var j
=0, queriesLength
= _queries
.length
; j
< queriesLength
; j
++) {
3169 var item
= $(_queries
[j
]);
3171 item
.data('sortable-item', targetData
); // Data for target checking (mouse manager)
3175 instance
: targetData
,
3176 width
: 0, height
: 0,
3184 refreshPositions: function(fast
) {
3186 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
3187 if(this.offsetParent
&& this.helper
) {
3188 this.offset
.parent
= this._getParentOffset();
3191 for (var i
= this.items
.length
- 1; i
>= 0; i
--){
3192 var item
= this.items
[i
];
3194 //We ignore calculating positions of all connected containers when we're not over them
3195 if(item
.instance
!= this.currentContainer
&& this.currentContainer
&& item
.item
[0] != this.currentItem
[0])
3198 var t
= this.options
.toleranceElement
? $(this.options
.toleranceElement
, item
.item
) : item
.item
;
3201 item
.width
= t
.outerWidth();
3202 item
.height
= t
.outerHeight();
3210 if(this.options
.custom
&& this.options
.custom
.refreshContainers
) {
3211 this.options
.custom
.refreshContainers
.call(this);
3213 for (var i
= this.containers
.length
- 1; i
>= 0; i
--){
3214 var p
= this.containers
[i
].element
.offset();
3215 this.containers
[i
].containerCache
.left
= p
.left
;
3216 this.containers
[i
].containerCache
.top
= p
.top
;
3217 this.containers
[i
].containerCache
.width
= this.containers
[i
].element
.outerWidth();
3218 this.containers
[i
].containerCache
.height
= this.containers
[i
].element
.outerHeight();
3224 _createPlaceholder: function(that
) {
3226 var self
= that
|| this, o
= self
.options
;
3228 if(!o
.placeholder
|| o
.placeholder
.constructor == String
) {
3229 var className
= o
.placeholder
;
3231 element: function() {
3233 var el
= $(document
.createElement(self
.currentItem
[0].nodeName
))
3234 .addClass(className
|| self
.currentItem
[0].className
+" ui-sortable-placeholder")
3235 .removeClass("ui-sortable-helper")[0];
3238 el
.style
.visibility
= "hidden";
3242 update: function(container
, p
) {
3244 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
3245 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
3246 if(className
&& !o
.forcePlaceholderSize
) return;
3248 //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
3249 if(!p
.height()) { p
.height(self
.currentItem
.innerHeight() - parseInt(self
.currentItem
.css('paddingTop')||0, 10) - parseInt(self
.currentItem
.css('paddingBottom')||0, 10)); };
3250 if(!p
.width()) { p
.width(self
.currentItem
.innerWidth() - parseInt(self
.currentItem
.css('paddingLeft')||0, 10) - parseInt(self
.currentItem
.css('paddingRight')||0, 10)); };
3255 //Create the placeholder
3256 self
.placeholder
= $(o
.placeholder
.element
.call(self
.element
, self
.currentItem
));
3258 //Append it after the actual current item
3259 self
.currentItem
.after(self
.placeholder
);
3261 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
3262 o
.placeholder
.update(self
, self
.placeholder
);
3266 _contactContainers: function(event
) {
3267 for (var i
= this.containers
.length
- 1; i
>= 0; i
--){
3269 if(this._intersectsWith(this.containers
[i
].containerCache
)) {
3270 if(!this.containers
[i
].containerCache
.over
) {
3272 if(this.currentContainer
!= this.containers
[i
]) {
3274 //When entering a new container, we will find the item with the least distance and append our item near it
3275 var dist
= 10000; var itemWithLeastDistance
= null; var base
= this.positionAbs
[this.containers
[i
].floating
? 'left' : 'top'];
3276 for (var j
= this.items
.length
- 1; j
>= 0; j
--) {
3277 if(!$.ui
.contains(this.containers
[i
].element
[0], this.items
[j
].item
[0])) continue;
3278 var cur
= this.items
[j
][this.containers
[i
].floating
? 'left' : 'top'];
3279 if(Math
.abs(cur
- base
) < dist
) {
3280 dist
= Math
.abs(cur
- base
); itemWithLeastDistance
= this.items
[j
];
3284 if(!itemWithLeastDistance
&& !this.options
.dropOnEmpty
) //Check if dropOnEmpty is enabled
3287 this.currentContainer
= this.containers
[i
];
3288 itemWithLeastDistance
? this._rearrange(event
, itemWithLeastDistance
, null, true) : this._rearrange(event
, null, this.containers
[i
].element
, true);
3289 this._trigger("change", event
, this._uiHash());
3290 this.containers
[i
]._trigger("change", event
, this._uiHash(this));
3292 //Update the placeholder
3293 this.options
.placeholder
.update(this.currentContainer
, this.placeholder
);
3297 this.containers
[i
]._trigger("over", event
, this._uiHash(this));
3298 this.containers
[i
].containerCache
.over
= 1;
3301 if(this.containers
[i
].containerCache
.over
) {
3302 this.containers
[i
]._trigger("out", event
, this._uiHash(this));
3303 this.containers
[i
].containerCache
.over
= 0;
3310 _createHelper: function(event
) {
3312 var o
= this.options
;
3313 var helper
= $.isFunction(o
.helper
) ? $(o
.helper
.apply(this.element
[0], [event
, this.currentItem
])) : (o
.helper
== 'clone' ? this.currentItem
.clone() : this.currentItem
);
3315 if(!helper
.parents('body').length
) //Add the helper to the DOM if that didn't happen already
3316 $(o
.appendTo
!= 'parent' ? o
.appendTo
: this.currentItem
[0].parentNode
)[0].appendChild(helper
[0]);
3318 if(helper
[0] == this.currentItem
[0])
3319 this._storedCSS
= { width
: this.currentItem
[0].style
.width
, height
: this.currentItem
[0].style
.height
, position
: this.currentItem
.css("position"), top
: this.currentItem
.css("top"), left
: this.currentItem
.css("left") };
3321 if(helper
[0].style
.width
== '' || o
.forceHelperSize
) helper
.width(this.currentItem
.width());
3322 if(helper
[0].style
.height
== '' || o
.forceHelperSize
) helper
.height(this.currentItem
.height());
3328 _adjustOffsetFromHelper: function(obj
) {
3329 if(obj
.left
!= undefined) this.offset
.click
.left
= obj
.left
+ this.margins
.left
;
3330 if(obj
.right
!= undefined) this.offset
.click
.left
= this.helperProportions
.width
- obj
.right
+ this.margins
.left
;
3331 if(obj
.top
!= undefined) this.offset
.click
.top
= obj
.top
+ this.margins
.top
;
3332 if(obj
.bottom
!= undefined) this.offset
.click
.top
= this.helperProportions
.height
- obj
.bottom
+ this.margins
.top
;
3335 _getParentOffset: function() {
3338 //Get the offsetParent and cache its position
3339 this.offsetParent
= this.helper
.offsetParent();
3340 var po
= this.offsetParent
.offset();
3342 // This is a special case where we need to modify a offset calculated on start, since the following happened:
3343 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
3344 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
3345 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
3346 if(this.cssPosition
== 'absolute' && this.scrollParent
[0] != document
&& $.ui
.contains(this.scrollParent
[0], this.offsetParent
[0])) {
3347 po
.left
+= this.scrollParent
.scrollLeft();
3348 po
.top
+= this.scrollParent
.scrollTop();
3351 if((this.offsetParent
[0] == document
.body
) //This needs to be actually done for all browsers, since pageX/pageY includes this information
3352 || (this.offsetParent
[0].tagName
&& this.offsetParent
[0].tagName
.toLowerCase() == 'html' && $.browser
.msie
)) //Ugly IE fix
3353 po
= { top
: 0, left
: 0 };
3356 top
: po
.top
+ (parseInt(this.offsetParent
.css("borderTopWidth"),10) || 0),
3357 left
: po
.left
+ (parseInt(this.offsetParent
.css("borderLeftWidth"),10) || 0)
3362 _getRelativeOffset: function() {
3364 if(this.cssPosition
== "relative") {
3365 var p
= this.currentItem
.position();
3367 top
: p
.top
- (parseInt(this.helper
.css("top"),10) || 0) + this.scrollParent
.scrollTop(),
3368 left
: p
.left
- (parseInt(this.helper
.css("left"),10) || 0) + this.scrollParent
.scrollLeft()
3371 return { top
: 0, left
: 0 };
3376 _cacheMargins: function() {
3378 left
: (parseInt(this.currentItem
.css("marginLeft"),10) || 0),
3379 top
: (parseInt(this.currentItem
.css("marginTop"),10) || 0)
3383 _cacheHelperProportions: function() {
3384 this.helperProportions
= {
3385 width
: this.helper
.outerWidth(),
3386 height
: this.helper
.outerHeight()
3390 _setContainment: function() {
3392 var o
= this.options
;
3393 if(o
.containment
== 'parent') o
.containment
= this.helper
[0].parentNode
;
3394 if(o
.containment
== 'document' || o
.containment
== 'window') this.containment
= [
3395 0 - this.offset
.relative
.left
- this.offset
.parent
.left
,
3396 0 - this.offset
.relative
.top
- this.offset
.parent
.top
,
3397 $(o
.containment
== 'document' ? document
: window
).width() - this.helperProportions
.width
- this.margins
.left
,
3398 ($(o
.containment
== 'document' ? document
: window
).height() || document
.body
.parentNode
.scrollHeight
) - this.helperProportions
.height
- this.margins
.top
3401 if(!(/^(document|window|parent)$/).test(o
.containment
)) {
3402 var ce
= $(o
.containment
)[0];
3403 var co
= $(o
.containment
).offset();
3404 var over
= ($(ce
).css("overflow") != 'hidden');
3406 this.containment
= [
3407 co
.left
+ (parseInt($(ce
).css("borderLeftWidth"),10) || 0) + (parseInt($(ce
).css("paddingLeft"),10) || 0) - this.margins
.left
,
3408 co
.top
+ (parseInt($(ce
).css("borderTopWidth"),10) || 0) + (parseInt($(ce
).css("paddingTop"),10) || 0) - this.margins
.top
,
3409 co
.left
+(over
? Math
.max(ce
.scrollWidth
,ce
.offsetWidth
) : ce
.offsetWidth
) - (parseInt($(ce
).css("borderLeftWidth"),10) || 0) - (parseInt($(ce
).css("paddingRight"),10) || 0) - this.helperProportions
.width
- this.margins
.left
,
3410 co
.top
+(over
? Math
.max(ce
.scrollHeight
,ce
.offsetHeight
) : ce
.offsetHeight
) - (parseInt($(ce
).css("borderTopWidth"),10) || 0) - (parseInt($(ce
).css("paddingBottom"),10) || 0) - this.helperProportions
.height
- this.margins
.top
3416 _convertPositionTo: function(d
, pos
) {
3418 if(!pos
) pos
= this.position
;
3419 var mod
= d
== "absolute" ? 1 : -1;
3420 var o
= this.options
, scroll
= this.cssPosition
== 'absolute' && !(this.scrollParent
[0] != document
&& $.ui
.contains(this.scrollParent
[0], this.offsetParent
[0])) ? this.offsetParent
: this.scrollParent
, scrollIsRootNode
= (/(html|body)/i).test(scroll
[0].tagName
);
3424 pos
.top
// The absolute mouse position
3425 + this.offset
.relative
.top
* mod
// Only for relative positioned nodes: Relative offset from element to offset parent
3426 + this.offset
.parent
.top
* mod
// The offsetParent's offset without borders (offset + border)
3427 - ($.browser
.safari
&& this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollTop() : ( scrollIsRootNode
? 0 : scroll
.scrollTop() ) ) * mod
)
3430 pos
.left
// The absolute mouse position
3431 + this.offset
.relative
.left
* mod
// Only for relative positioned nodes: Relative offset from element to offset parent
3432 + this.offset
.parent
.left
* mod
// The offsetParent's offset without borders (offset + border)
3433 - ($.browser
.safari
&& this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollLeft() : scrollIsRootNode
? 0 : scroll
.scrollLeft() ) * mod
)
3439 _generatePosition: function(event
) {
3441 var o
= this.options
, scroll
= this.cssPosition
== 'absolute' && !(this.scrollParent
[0] != document
&& $.ui
.contains(this.scrollParent
[0], this.offsetParent
[0])) ? this.offsetParent
: this.scrollParent
, scrollIsRootNode
= (/(html|body)/i).test(scroll
[0].tagName
);
3443 // This is another very weird special case that only happens for relative elements:
3444 // 1. If the css position is relative
3445 // 2. and the scroll parent is the document or similar to the offset parent
3446 // we have to refresh the relative offset during the scroll so there are no jumps
3447 if(this.cssPosition
== 'relative' && !(this.scrollParent
[0] != document
&& this.scrollParent
[0] != this.offsetParent
[0])) {
3448 this.offset
.relative
= this._getRelativeOffset();
3451 var pageX
= event
.pageX
;
3452 var pageY
= event
.pageY
;
3455 * - Position constraining -
3456 * Constrain the position to a mix of grid, containment.
3459 if(this.originalPosition
) { //If we are not dragging yet, we won't check for options
3461 if(this.containment
) {
3462 if(event
.pageX
- this.offset
.click
.left
< this.containment
[0]) pageX
= this.containment
[0] + this.offset
.click
.left
;
3463 if(event
.pageY
- this.offset
.click
.top
< this.containment
[1]) pageY
= this.containment
[1] + this.offset
.click
.top
;
3464 if(event
.pageX
- this.offset
.click
.left
> this.containment
[2]) pageX
= this.containment
[2] + this.offset
.click
.left
;
3465 if(event
.pageY
- this.offset
.click
.top
> this.containment
[3]) pageY
= this.containment
[3] + this.offset
.click
.top
;
3469 var top
= this.originalPageY
+ Math
.round((pageY
- this.originalPageY
) / o
.grid
[1]) * o
.grid
[1];
3470 pageY
= this.containment
? (!(top
- this.offset
.click
.top
< this.containment
[1] || top
- this.offset
.click
.top
> this.containment
[3]) ? top
: (!(top
- this.offset
.click
.top
< this.containment
[1]) ? top
- o
.grid
[1] : top
+ o
.grid
[1])) : top
;
3472 var left
= this.originalPageX
+ Math
.round((pageX
- this.originalPageX
) / o
.grid
[0]) * o
.grid
[0];
3473 pageX
= this.containment
? (!(left
- this.offset
.click
.left
< this.containment
[0] || left
- this.offset
.click
.left
> this.containment
[2]) ? left
: (!(left
- this.offset
.click
.left
< this.containment
[0]) ? left
- o
.grid
[0] : left
+ o
.grid
[0])) : left
;
3480 pageY
// The absolute mouse position
3481 - this.offset
.click
.top
// Click offset (relative to the element)
3482 - this.offset
.relative
.top
// Only for relative positioned nodes: Relative offset from element to offset parent
3483 - this.offset
.parent
.top
// The offsetParent's offset without borders (offset + border)
3484 + ($.browser
.safari
&& this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollTop() : ( scrollIsRootNode
? 0 : scroll
.scrollTop() ) ))
3487 pageX
// The absolute mouse position
3488 - this.offset
.click
.left
// Click offset (relative to the element)
3489 - this.offset
.relative
.left
// Only for relative positioned nodes: Relative offset from element to offset parent
3490 - this.offset
.parent
.left
// The offsetParent's offset without borders (offset + border)
3491 + ($.browser
.safari
&& this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollLeft() : scrollIsRootNode
? 0 : scroll
.scrollLeft() ))
3497 _rearrange: function(event
, i
, a
, hardRefresh
) {
3499 a
? a
[0].appendChild(this.placeholder
[0]) : i
.item
[0].parentNode
.insertBefore(this.placeholder
[0], (this.direction
== 'down' ? i
.item
[0] : i
.item
[0].nextSibling
));
3501 //Various things done here to improve the performance:
3502 // 1. we create a setTimeout, that calls refreshPositions
3503 // 2. on the instance, we have a counter variable, that get's higher after every append
3504 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
3505 // 4. this lets only the last addition to the timeout stack through
3506 this.counter
= this.counter
? ++this.counter
: 1;
3507 var self
= this, counter
= this.counter
;
3509 window
.setTimeout(function() {
3510 if(counter
== self
.counter
) self
.refreshPositions(!hardRefresh
); //Precompute after each DOM insertion, NOT on mousemove
3515 _clear: function(event
, noPropagation
) {
3517 this.reverting
= false;
3518 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
3519 // everything else normalized again
3520 var delayedTriggers
= [], self
= this;
3522 // We first have to update the dom position of the actual currentItem
3523 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
3524 if(!this._noFinalSort
&& this.currentItem
[0].parentNode
) this.placeholder
.before(this.currentItem
);
3525 this._noFinalSort
= null;
3527 if(this.helper
[0] == this.currentItem
[0]) {
3528 for(var i
in this._storedCSS
) {
3529 if(this._storedCSS
[i
] == 'auto' || this._storedCSS
[i
] == 'static') this._storedCSS
[i
] = '';
3531 this.currentItem
.css(this._storedCSS
).removeClass("ui-sortable-helper");
3533 this.currentItem
.show();
3536 if(this.fromOutside
&& !noPropagation
) delayedTriggers
.push(function(event
) { this._trigger("receive", event
, this._uiHash(this.fromOutside
)); });
3537 if((this.fromOutside
|| this.domPosition
.prev
!= this.currentItem
.prev().not(".ui-sortable-helper")[0] || this.domPosition
.parent
!= this.currentItem
.parent()[0]) && !noPropagation
) delayedTriggers
.push(function(event
) { this._trigger("update", event
, this._uiHash()); }); //Trigger update callback if the DOM position has changed
3538 if(!$.ui
.contains(this.element
[0], this.currentItem
[0])) { //Node was moved out of the current element
3539 if(!noPropagation
) delayedTriggers
.push(function(event
) { this._trigger("remove", event
, this._uiHash()); });
3540 for (var i
= this.containers
.length
- 1; i
>= 0; i
--){
3541 if($.ui
.contains(this.containers
[i
].element
[0], this.currentItem
[0]) && !noPropagation
) {
3542 delayedTriggers
.push((function(c
) { return function(event
) { c
._trigger("receive", event
, this._uiHash(this)); }; }).call(this, this.containers
[i
]));
3543 delayedTriggers
.push((function(c
) { return function(event
) { c
._trigger("update", event
, this._uiHash(this)); }; }).call(this, this.containers
[i
]));
3548 //Post events to containers
3549 for (var i
= this.containers
.length
- 1; i
>= 0; i
--){
3550 if(!noPropagation
) delayedTriggers
.push((function(c
) { return function(event
) { c
._trigger("deactivate", event
, this._uiHash(this)); }; }).call(this, this.containers
[i
]));
3551 if(this.containers
[i
].containerCache
.over
) {
3552 delayedTriggers
.push((function(c
) { return function(event
) { c
._trigger("out", event
, this._uiHash(this)); }; }).call(this, this.containers
[i
]));
3553 this.containers
[i
].containerCache
.over
= 0;
3557 //Do what was originally in plugins
3558 if(this._storedCursor
) $('body').css("cursor", this._storedCursor
); //Reset cursor
3559 if(this._storedOpacity
) this.helper
.css("opacity", this._storedOpacity
); //Reset cursor
3560 if(this._storedZIndex
) this.helper
.css("zIndex", this._storedZIndex
== 'auto' ? '' : this._storedZIndex
); //Reset z-index
3562 this.dragging
= false;
3563 if(this.cancelHelperRemoval
) {
3564 if(!noPropagation
) {
3565 this._trigger("beforeStop", event
, this._uiHash());
3566 for (var i
=0; i
< delayedTriggers
.length
; i
++) { delayedTriggers
[i
].call(this, event
); }; //Trigger all delayed events
3567 this._trigger("stop", event
, this._uiHash());
3572 if(!noPropagation
) this._trigger("beforeStop", event
, this._uiHash());
3574 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3575 this.placeholder
[0].parentNode
.removeChild(this.placeholder
[0]);
3577 if(this.helper
[0] != this.currentItem
[0]) this.helper
.remove(); this.helper
= null;
3579 if(!noPropagation
) {
3580 for (var i
=0; i
< delayedTriggers
.length
; i
++) { delayedTriggers
[i
].call(this, event
); }; //Trigger all delayed events
3581 this._trigger("stop", event
, this._uiHash());
3584 this.fromOutside
= false;
3589 _trigger: function() {
3590 if ($.widget
.prototype._trigger
.apply(this, arguments
) === false) {
3595 _uiHash: function(inst
) {
3596 var self
= inst
|| this;
3598 helper
: self
.helper
,
3599 placeholder
: self
.placeholder
|| $([]),
3600 position
: self
.position
,
3601 absolutePosition
: self
.positionAbs
, //deprecated
3602 offset
: self
.positionAbs
,
3603 item
: self
.currentItem
,
3604 sender
: inst
? inst
.element
: null
3610 $.extend($.ui
.sortable
, {
3611 getter
: "serialize toArray",
3613 eventPrefix
: "sort",
3617 cancel
: ":input,option",
3625 forcePlaceholderSize
: false,
3626 forceHelperSize
: false,
3635 scrollSensitivity
: 20,
3638 tolerance
: "intersect",
3645 * jQuery UI Accordion 1.7.1
3647 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
3648 * Dual licensed under the MIT (MIT-LICENSE.txt)
3649 * and GPL (GPL-LICENSE.txt) licenses.
3651 * http://docs.jquery.com/UI/Accordion
3658 $.widget("ui.accordion", {
3662 var o
= this.options
, self
= this;
3665 // if the user set the alwaysOpen option on init
3666 // then we need to set the collapsible option
3667 // if they set both on init, collapsible will take priority
3668 if (o
.collapsible
== $.ui
.accordion
.defaults
.collapsible
&&
3669 o
.alwaysOpen
!= $.ui
.accordion
.defaults
.alwaysOpen
) {
3670 o
.collapsible
= !o
.alwaysOpen
;
3673 if ( o
.navigation
) {
3674 var current
= this.element
.find("a").filter(o
.navigationFilter
);
3675 if ( current
.length
) {
3676 if ( current
.filter(o
.header
).length
) {
3677 this.active
= current
;
3679 this.active
= current
.parent().parent().prev();
3680 current
.addClass("ui-accordion-content-active");
3685 this.element
.addClass("ui-accordion ui-widget ui-helper-reset");
3687 // in lack of child-selectors in CSS we need to mark top-LIs in a UL-accordion for some IE-fix
3688 if (this.element
[0].nodeName
== "UL") {
3689 this.element
.children("li").addClass("ui-accordion-li-fix");
3692 this.headers
= this.element
.find(o
.header
).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all")
3693 .bind("mouseenter.accordion", function(){ $(this).addClass('ui-state-hover'); })
3694 .bind("mouseleave.accordion", function(){ $(this).removeClass('ui-state-hover'); })
3695 .bind("focus.accordion", function(){ $(this).addClass('ui-state-focus'); })
3696 .bind("blur.accordion", function(){ $(this).removeClass('ui-state-focus'); });
3700 .addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");
3702 this.active
= this._findActive(this.active
|| o
.active
).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");
3703 this.active
.next().addClass('ui-accordion-content-active');
3705 //Append icon elements
3706 $("<span/>").addClass("ui-icon " + o
.icons
.header
).prependTo(this.headers
);
3707 this.active
.find(".ui-icon").toggleClass(o
.icons
.header
).toggleClass(o
.icons
.headerSelected
);
3709 // IE7-/Win - Extra vertical space in lists fixed
3710 if ($.browser
.msie
) {
3711 this.element
.find('a').css('zoom', '1');
3717 this.element
.attr('role','tablist');
3721 .bind('keydown', function(event
) { return self
._keydown(event
); })
3723 .attr('role','tabpanel');
3726 .not(this.active
|| "")
3727 .attr('aria-expanded','false')
3728 .attr("tabIndex", "-1")
3732 // make sure at least one header is in the tab order
3733 if (!this.active
.length
) {
3734 this.headers
.eq(0).attr('tabIndex','0');
3737 .attr('aria-expanded','true')
3738 .attr('tabIndex', '0');
3741 // only need links in taborder for Safari
3742 if (!$.browser
.safari
)
3743 this.headers
.find('a').attr('tabIndex','-1');
3746 this.headers
.bind((o
.event
) + ".accordion", function(event
) { return self
._clickHandler
.call(self
, event
, this); });
3751 destroy: function() {
3752 var o
= this.options
;
3755 .removeClass("ui-accordion ui-widget ui-helper-reset")
3757 .unbind('.accordion')
3758 .removeData('accordion');
3761 .unbind(".accordion")
3762 .removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top")
3763 .removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex");
3765 this.headers
.find("a").removeAttr("tabindex");
3766 this.headers
.children(".ui-icon").remove();
3767 var contents
= this.headers
.next().css("display", "").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");
3768 if (o
.autoHeight
|| o
.fillHeight
) {
3769 contents
.css("height", "");
3773 _setData: function(key
, value
) {
3774 if(key
== 'alwaysOpen') { key
= 'collapsible'; value
= !value
; }
3775 $.widget
.prototype._setData
.apply(this, arguments
);
3778 _keydown: function(event
) {
3780 var o
= this.options
, keyCode
= $.ui
.keyCode
;
3782 if (o
.disabled
|| event
.altKey
|| event
.ctrlKey
)
3785 var length
= this.headers
.length
;
3786 var currentIndex
= this.headers
.index(event
.target
);
3787 var toFocus
= false;
3789 switch(event
.keyCode
) {
3792 toFocus
= this.headers
[(currentIndex
+ 1) % length
];
3796 toFocus
= this.headers
[(currentIndex
- 1 + length
) % length
];
3800 return this._clickHandler({ target
: event
.target
}, event
.target
);
3804 $(event
.target
).attr('tabIndex','-1');
3805 $(toFocus
).attr('tabIndex','0');
3814 resize: function() {
3816 var o
= this.options
, maxHeight
;
3820 if($.browser
.msie
) { var defOverflow
= this.element
.parent().css('overflow'); this.element
.parent().css('overflow', 'hidden'); }
3821 maxHeight
= this.element
.parent().height();
3822 if($.browser
.msie
) { this.element
.parent().css('overflow', defOverflow
); }
3824 this.headers
.each(function() {
3825 maxHeight
-= $(this).outerHeight();
3829 this.headers
.next().each(function() {
3830 maxPadding
= Math
.max(maxPadding
, $(this).innerHeight() - $(this).height());
3831 }).height(Math
.max(0, maxHeight
- maxPadding
))
3832 .css('overflow', 'auto');
3834 } else if ( o
.autoHeight
) {
3836 this.headers
.next().each(function() {
3837 maxHeight
= Math
.max(maxHeight
, $(this).outerHeight());
3838 }).height(maxHeight
);
3843 activate: function(index
) {
3844 // call clickHandler with custom event
3845 var active
= this._findActive(index
)[0];
3846 this._clickHandler({ target
: active
}, active
);
3849 _findActive: function(selector
) {
3851 ? typeof selector
== "number"
3852 ? this.headers
.filter(":eq(" + selector
+ ")")
3853 : this.headers
.not(this.headers
.not(selector
))
3854 : selector
=== false
3856 : this.headers
.filter(":eq(0)");
3859 _clickHandler: function(event
, target
) {
3861 var o
= this.options
;
3862 if (o
.disabled
) return false;
3864 // called only when using activate(false) to close all parts programmatically
3865 if (!event
.target
&& o
.collapsible
) {
3866 this.active
.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
3867 .find(".ui-icon").removeClass(o
.icons
.headerSelected
).addClass(o
.icons
.header
);
3868 this.active
.next().addClass('ui-accordion-content-active');
3869 var toHide
= this.active
.next(),
3873 oldHeader
: o
.active
,
3877 toShow
= (this.active
= $([]));
3878 this._toggle(toShow
, toHide
, data
);
3882 // get the click target
3883 var clicked
= $(event
.currentTarget
|| target
);
3884 var clickedIsActive
= clicked
[0] == this.active
[0];
3886 // if animations are still active, or the active header is the target, ignore click
3887 if (this.running
|| (!o
.collapsible
&& clickedIsActive
)) {
3892 this.active
.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
3893 .find(".ui-icon").removeClass(o
.icons
.headerSelected
).addClass(o
.icons
.header
);
3894 this.active
.next().addClass('ui-accordion-content-active');
3895 if (!clickedIsActive
) {
3896 clicked
.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top")
3897 .find(".ui-icon").removeClass(o
.icons
.header
).addClass(o
.icons
.headerSelected
);
3898 clicked
.next().addClass('ui-accordion-content-active');
3901 // find elements to show and hide
3902 var toShow
= clicked
.next(),
3903 toHide
= this.active
.next(),
3906 newHeader
: clickedIsActive
&& o
.collapsible
? $([]) : clicked
,
3907 oldHeader
: this.active
,
3908 newContent
: clickedIsActive
&& o
.collapsible
? $([]) : toShow
.find('> *'),
3909 oldContent
: toHide
.find('> *')
3911 down
= this.headers
.index( this.active
[0] ) > this.headers
.index( clicked
[0] );
3913 this.active
= clickedIsActive
? $([]) : clicked
;
3914 this._toggle(toShow
, toHide
, data
, clickedIsActive
, down
);
3920 _toggle: function(toShow
, toHide
, data
, clickedIsActive
, down
) {
3922 var o
= this.options
, self
= this;
3924 this.toShow
= toShow
;
3925 this.toHide
= toHide
;
3928 var complete = function() { if(!self
) return; return self
._completed
.apply(self
, arguments
); };
3930 // trigger changestart event
3931 this._trigger("changestart", null, this.data
);
3933 // count elements to animate
3934 this.running
= toHide
.size() === 0 ? toShow
.size() : toHide
.size();
3938 var animOptions
= {};
3940 if ( o
.collapsible
&& clickedIsActive
) {
3946 autoHeight
: o
.autoHeight
|| o
.fillSpace
3954 autoHeight
: o
.autoHeight
|| o
.fillSpace
3959 o
.proxied
= o
.animated
;
3962 if (!o
.proxiedDuration
) {
3963 o
.proxiedDuration
= o
.duration
;
3966 o
.animated
= $.isFunction(o
.proxied
) ?
3967 o
.proxied(animOptions
) : o
.proxied
;
3969 o
.duration
= $.isFunction(o
.proxiedDuration
) ?
3970 o
.proxiedDuration(animOptions
) : o
.proxiedDuration
;
3972 var animations
= $.ui
.accordion
.animations
,
3973 duration
= o
.duration
,
3974 easing
= o
.animated
;
3976 if (!animations
[easing
]) {
3977 animations
[easing
] = function(options
) {
3978 this.slide(options
, {
3980 duration
: duration
|| 700
3985 animations
[easing
](animOptions
);
3989 if (o
.collapsible
&& clickedIsActive
) {
4000 toHide
.prev().attr('aria-expanded','false').attr("tabIndex", "-1").blur();
4001 toShow
.prev().attr('aria-expanded','true').attr("tabIndex", "0").focus();
4005 _completed: function(cancel
) {
4007 var o
= this.options
;
4009 this.running
= cancel
? 0 : --this.running
;
4010 if (this.running
) return;
4013 this.toShow
.add(this.toHide
).css({
4019 this._trigger('change', null, this.data
);
4025 $.extend($.ui
.accordion
, {
4029 alwaysOpen
: true, //deprecated, use collapsible
4036 header
: "> li > :first-child,> :not(li):even",
4038 header
: "ui-icon-triangle-1-e",
4039 headerSelected
: "ui-icon-triangle-1-s"
4042 navigationFilter: function() {
4043 return this.href
.toLowerCase() == location
.href
.toLowerCase();
4047 slide: function(options
, additions
) {
4048 options
= $.extend({
4051 }, options
, additions
);
4052 if ( !options
.toHide
.size() ) {
4053 options
.toShow
.animate({height
: "show"}, options
);
4056 if ( !options
.toShow
.size() ) {
4057 options
.toHide
.animate({height
: "hide"}, options
);
4060 var overflow
= options
.toShow
.css('overflow'),
4064 fxAttrs
= [ "height", "paddingTop", "paddingBottom" ],
4066 // fix width before calculating height of hidden element
4067 var s
= options
.toShow
;
4068 originalWidth
= s
[0].style
.width
;
4069 s
.width( parseInt(s
.parent().width(),10) - parseInt(s
.css("paddingLeft"),10) - parseInt(s
.css("paddingRight"),10) - (parseInt(s
.css("borderLeftWidth"),10) || 0) - (parseInt(s
.css("borderRightWidth"),10) || 0) );
4071 $.each(fxAttrs
, function(i
, prop
) {
4072 hideProps
[prop
] = 'hide';
4074 var parts
= ('' + $.css(options
.toShow
[0], prop
)).match(/^([\d+-.]+)(.*)$/);
4077 unit
: parts
[2] || 'px'
4080 options
.toShow
.css({ height
: 0, overflow
: 'hidden' }).show();
4081 options
.toHide
.filter(":hidden").each(options
.complete
).end().filter(":visible").animate(hideProps
,{
4082 step: function(now
, settings
) {
4083 // only calculate the percent when animating height
4084 // IE gets very inconsistent results when animating elements
4085 // with small values, which is common for padding
4086 if (settings
.prop
== 'height') {
4087 percentDone
= (settings
.now
- settings
.start
) / (settings
.end
- settings
.start
);
4090 options
.toShow
[0].style
[settings
.prop
] =
4091 (percentDone
* showProps
[settings
.prop
].value
) + showProps
[settings
.prop
].unit
;
4093 duration
: options
.duration
,
4094 easing
: options
.easing
,
4095 complete: function() {
4096 if ( !options
.autoHeight
) {
4097 options
.toShow
.css("height", "");
4099 options
.toShow
.css("width", originalWidth
);
4100 options
.toShow
.css({overflow
: overflow
});
4105 bounceslide: function(options
) {
4106 this.slide(options
, {
4107 easing
: options
.down
? "easeOutBounce" : "swing",
4108 duration
: options
.down
? 1000 : 200
4111 easeslide: function(options
) {
4112 this.slide(options
, {
4113 easing
: "easeinout",
4122 * jQuery UI Dialog 1.7.1
4124 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
4125 * Dual licensed under the MIT (MIT-LICENSE.txt)
4126 * and GPL (GPL-LICENSE.txt) licenses.
4128 * http://docs.jquery.com/UI/Dialog
4137 var setDataSwitch
= {
4138 dragStart
: "start.draggable",
4139 drag
: "drag.draggable",
4140 dragStop
: "stop.draggable",
4141 maxHeight
: "maxHeight.resizable",
4142 minHeight
: "minHeight.resizable",
4143 maxWidth
: "maxWidth.resizable",
4144 minWidth
: "minWidth.resizable",
4145 resizeStart
: "start.resizable",
4146 resize
: "drag.resizable",
4147 resizeStop
: "stop.resizable"
4153 'ui-widget-content ' +
4156 $.widget("ui.dialog", {
4159 this.originalTitle
= this.element
.attr('title');
4162 options
= this.options
,
4164 title
= options
.title
|| this.originalTitle
|| ' ',
4165 titleId
= $.ui
.dialog
.getTitleId(this.element
),
4167 uiDialog
= (this.uiDialog
= $('<div/>'))
4168 .appendTo(document
.body
)
4170 .addClass(uiDialogClasses
+ options
.dialogClass
)
4172 position
: 'absolute',
4174 zIndex
: options
.zIndex
4176 // setting tabIndex makes the div focusable
4177 // setting outline to 0 prevents a border on focus in Mozilla
4178 .attr('tabIndex', -1).css('outline', 0).keydown(function(event
) {
4179 (options
.closeOnEscape
&& event
.keyCode
4180 && event
.keyCode
== $.ui
.keyCode
.ESCAPE
&& self
.close(event
));
4184 'aria-labelledby': titleId
4186 .mousedown(function(event
) {
4187 self
.moveToTop(false, event
);
4190 uiDialogContent
= this.element
4192 .removeAttr('title')
4194 'ui-dialog-content ' +
4195 'ui-widget-content')
4196 .appendTo(uiDialog
),
4198 uiDialogTitlebar
= (this.uiDialogTitlebar
= $('<div></div>'))
4200 'ui-dialog-titlebar ' +
4201 'ui-widget-header ' +
4203 'ui-helper-clearfix'
4205 .prependTo(uiDialog
),
4207 uiDialogTitlebarClose
= $('<a href="#"/>')
4209 'ui-dialog-titlebar-close ' +
4212 .attr('role', 'button')
4215 uiDialogTitlebarClose
.addClass('ui-state-hover');
4218 uiDialogTitlebarClose
.removeClass('ui-state-hover');
4222 uiDialogTitlebarClose
.addClass('ui-state-focus');
4225 uiDialogTitlebarClose
.removeClass('ui-state-focus');
4227 .mousedown(function(ev
) {
4228 ev
.stopPropagation();
4230 .click(function(event
) {
4234 .appendTo(uiDialogTitlebar
),
4236 uiDialogTitlebarCloseText
= (this.uiDialogTitlebarCloseText
= $('<span/>'))
4239 'ui-icon-closethick'
4241 .text(options
.closeText
)
4242 .appendTo(uiDialogTitlebarClose
),
4244 uiDialogTitle
= $('<span/>')
4245 .addClass('ui-dialog-title')
4246 .attr('id', titleId
)
4248 .prependTo(uiDialogTitlebar
);
4250 uiDialogTitlebar
.find("*").add(uiDialogTitlebar
).disableSelection();
4252 (options
.draggable
&& $.fn
.draggable
&& this._makeDraggable());
4253 (options
.resizable
&& $.fn
.resizable
&& this._makeResizable());
4255 this._createButtons(options
.buttons
);
4256 this._isOpen
= false;
4258 (options
.bgiframe
&& $.fn
.bgiframe
&& uiDialog
.bgiframe());
4259 (options
.autoOpen
&& this.open());
4263 destroy: function() {
4264 (this.overlay
&& this.overlay
.destroy());
4265 this.uiDialog
.hide();
4268 .removeData('dialog')
4269 .removeClass('ui-dialog-content ui-widget-content')
4270 .hide().appendTo('body');
4271 this.uiDialog
.remove();
4273 (this.originalTitle
&& this.element
.attr('title', this.originalTitle
));
4276 close: function(event
) {
4279 if (false === self
._trigger('beforeclose', event
)) {
4283 (self
.overlay
&& self
.overlay
.destroy());
4284 self
.uiDialog
.unbind('keypress.ui-dialog');
4287 ? self
.uiDialog
.hide(self
.options
.hide
, function() {
4288 self
._trigger('close', event
);
4290 : self
.uiDialog
.hide() && self
._trigger('close', event
));
4292 $.ui
.dialog
.overlay
.resize();
4294 self
._isOpen
= false;
4297 isOpen: function() {
4298 return this._isOpen
;
4301 // the force parameter allows us to move modal dialogs to their correct
4303 moveToTop: function(force
, event
) {
4305 if ((this.options
.modal
&& !force
)
4306 || (!this.options
.stack
&& !this.options
.modal
)) {
4307 return this._trigger('focus', event
);
4310 if (this.options
.zIndex
> $.ui
.dialog
.maxZ
) {
4311 $.ui
.dialog
.maxZ
= this.options
.zIndex
;
4313 (this.overlay
&& this.overlay
.$el
.css('z-index', $.ui
.dialog
.overlay
.maxZ
= ++$.ui
.dialog
.maxZ
));
4315 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
4316 // http://ui.jquery.com/bugs/ticket/3193
4317 var saveScroll
= { scrollTop
: this.element
.attr('scrollTop'), scrollLeft
: this.element
.attr('scrollLeft') };
4318 this.uiDialog
.css('z-index', ++$.ui
.dialog
.maxZ
);
4319 this.element
.attr(saveScroll
);
4320 this._trigger('focus', event
);
4324 if (this._isOpen
) { return; }
4326 var options
= this.options
,
4327 uiDialog
= this.uiDialog
;
4329 this.overlay
= options
.modal
? new $.ui
.dialog
.overlay(this) : null;
4330 (uiDialog
.next().length
&& uiDialog
.appendTo('body'));
4332 this._position(options
.position
);
4333 uiDialog
.show(options
.show
);
4334 this.moveToTop(true);
4336 // prevent tabbing out of modal dialogs
4337 (options
.modal
&& uiDialog
.bind('keypress.ui-dialog', function(event
) {
4338 if (event
.keyCode
!= $.ui
.keyCode
.TAB
) {
4342 var tabbables
= $(':tabbable', this),
4343 first
= tabbables
.filter(':first')[0],
4344 last
= tabbables
.filter(':last')[0];
4346 if (event
.target
== last
&& !event
.shiftKey
) {
4347 setTimeout(function() {
4350 } else if (event
.target
== first
&& event
.shiftKey
) {
4351 setTimeout(function() {
4357 // set focus to the first tabbable element in the content area or the first button
4358 // if there are no tabbable elements, set focus on the dialog itself
4360 .add(uiDialog
.find('.ui-dialog-content :tabbable:first'))
4361 .add(uiDialog
.find('.ui-dialog-buttonpane :tabbable:first'))
4366 this._trigger('open');
4367 this._isOpen
= true;
4370 _createButtons: function(buttons
) {
4373 uiDialogButtonPane
= $('<div></div>')
4375 'ui-dialog-buttonpane ' +
4376 'ui-widget-content ' +
4377 'ui-helper-clearfix'
4380 // if we already have a button pane, remove it
4381 this.uiDialog
.find('.ui-dialog-buttonpane').remove();
4383 (typeof buttons
== 'object' && buttons
!== null &&
4384 $.each(buttons
, function() { return !(hasButtons
= true); }));
4386 $.each(buttons
, function(name
, fn
) {
4387 $('<button type="button"></button>')
4389 'ui-state-default ' +
4393 .click(function() { fn
.apply(self
.element
[0], arguments
); })
4396 $(this).addClass('ui-state-hover');
4399 $(this).removeClass('ui-state-hover');
4403 $(this).addClass('ui-state-focus');
4406 $(this).removeClass('ui-state-focus');
4408 .appendTo(uiDialogButtonPane
);
4410 uiDialogButtonPane
.appendTo(this.uiDialog
);
4414 _makeDraggable: function() {
4416 options
= this.options
,
4419 this.uiDialog
.draggable({
4420 cancel
: '.ui-dialog-content',
4421 handle
: '.ui-dialog-titlebar',
4422 containment
: 'document',
4424 heightBeforeDrag
= options
.height
;
4425 $(this).height($(this).height()).addClass("ui-dialog-dragging");
4426 (options
.dragStart
&& options
.dragStart
.apply(self
.element
[0], arguments
));
4429 (options
.drag
&& options
.drag
.apply(self
.element
[0], arguments
));
4432 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag
);
4433 (options
.dragStop
&& options
.dragStop
.apply(self
.element
[0], arguments
));
4434 $.ui
.dialog
.overlay
.resize();
4439 _makeResizable: function(handles
) {
4440 handles
= (handles
=== undefined ? this.options
.resizable
: handles
);
4442 options
= this.options
,
4443 resizeHandles
= typeof handles
== 'string'
4445 : 'n,e,s,w,se,sw,ne,nw';
4447 this.uiDialog
.resizable({
4448 cancel
: '.ui-dialog-content',
4449 alsoResize
: this.element
,
4450 maxWidth
: options
.maxWidth
,
4451 maxHeight
: options
.maxHeight
,
4452 minWidth
: options
.minWidth
,
4453 minHeight
: options
.minHeight
,
4455 $(this).addClass("ui-dialog-resizing");
4456 (options
.resizeStart
&& options
.resizeStart
.apply(self
.element
[0], arguments
));
4458 resize: function() {
4459 (options
.resize
&& options
.resize
.apply(self
.element
[0], arguments
));
4461 handles
: resizeHandles
,
4463 $(this).removeClass("ui-dialog-resizing");
4464 options
.height
= $(this).height();
4465 options
.width
= $(this).width();
4466 (options
.resizeStop
&& options
.resizeStop
.apply(self
.element
[0], arguments
));
4467 $.ui
.dialog
.overlay
.resize();
4470 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
4473 _position: function(pos
) {
4474 var wnd
= $(window
), doc
= $(document
),
4475 pTop
= doc
.scrollTop(), pLeft
= doc
.scrollLeft(),
4478 if ($.inArray(pos
, ['center','top','right','bottom','left']) >= 0) {
4480 pos
== 'right' || pos
== 'left' ? pos
: 'center',
4481 pos
== 'top' || pos
== 'bottom' ? pos
: 'middle'
4484 if (pos
.constructor != Array
) {
4485 pos
= ['center', 'middle'];
4487 if (pos
[0].constructor == Number
) {
4495 pLeft
+= wnd
.width() - this.uiDialog
.outerWidth();
4499 pLeft
+= (wnd
.width() - this.uiDialog
.outerWidth()) / 2;
4502 if (pos
[1].constructor == Number
) {
4510 pTop
+= wnd
.height() - this.uiDialog
.outerHeight();
4514 pTop
+= (wnd
.height() - this.uiDialog
.outerHeight()) / 2;
4518 // prevent the dialog from being too high (make sure the titlebar
4520 pTop
= Math
.max(pTop
, minTop
);
4521 this.uiDialog
.css({top
: pTop
, left
: pLeft
});
4524 _setData: function(key
, value
){
4525 (setDataSwitch
[key
] && this.uiDialog
.data(setDataSwitch
[key
], value
));
4528 this._createButtons(value
);
4531 this.uiDialogTitlebarCloseText
.text(value
);
4535 .removeClass(this.options
.dialogClass
)
4536 .addClass(uiDialogClasses
+ value
);
4540 ? this._makeDraggable()
4541 : this.uiDialog
.draggable('destroy'));
4544 this.uiDialog
.height(value
);
4547 this._position(value
);
4550 var uiDialog
= this.uiDialog
,
4551 isResizable
= this.uiDialog
.is(':data(resizable)');
4553 // currently resizable, becoming non-resizable
4554 (isResizable
&& !value
&& uiDialog
.resizable('destroy'));
4556 // currently resizable, changing handles
4557 (isResizable
&& typeof value
== 'string' &&
4558 uiDialog
.resizable('option', 'handles', value
));
4560 // currently non-resizable, becoming resizable
4561 (isResizable
|| this._makeResizable(value
));
4564 $(".ui-dialog-title", this.uiDialogTitlebar
).html(value
|| ' ');
4567 this.uiDialog
.width(value
);
4571 $.widget
.prototype._setData
.apply(this, arguments
);
4575 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
4576 * divs will both have width and height set, so we need to reset them
4578 var options
= this.options
;
4580 // reset content sizing
4587 // reset wrapper sizing
4588 // determine the height of all the non-content elements
4589 var nonContentHeight
= this.uiDialog
.css({
4591 width
: options
.width
4597 minHeight
: Math
.max(options
.minHeight
- nonContentHeight
, 0),
4598 height
: options
.height
== 'auto'
4600 : Math
.max(options
.height
- nonContentHeight
, 0)
4605 $.extend($.ui
.dialog
, {
4611 closeOnEscape
: true,
4636 getTitleId: function($el
) {
4637 return 'ui-dialog-title-' + ($el
.attr('id') || ++this.uuid
);
4640 overlay: function(dialog
) {
4641 this.$el
= $.ui
.dialog
.overlay
.create(dialog
);
4645 $.extend($.ui
.dialog
.overlay
, {
4648 events
: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
4649 function(event
) { return event
+ '.dialog-overlay'; }).join(' '),
4650 create: function(dialog
) {
4651 if (this.instances
.length
=== 0) {
4652 // prevent use of anchors and inputs
4653 // we use a setTimeout in case the overlay is created from an
4654 // event that we're going to be cancelling (see #2804)
4655 setTimeout(function() {
4656 $(document
).bind($.ui
.dialog
.overlay
.events
, function(event
) {
4657 var dialogZ
= $(event
.target
).parents('.ui-dialog').css('zIndex') || 0;
4658 return (dialogZ
> $.ui
.dialog
.overlay
.maxZ
);
4662 // allow closing by pressing the escape key
4663 $(document
).bind('keydown.dialog-overlay', function(event
) {
4664 (dialog
.options
.closeOnEscape
&& event
.keyCode
4665 && event
.keyCode
== $.ui
.keyCode
.ESCAPE
&& dialog
.close(event
));
4668 // handle window resize
4669 $(window
).bind('resize.dialog-overlay', $.ui
.dialog
.overlay
.resize
);
4672 var $el
= $('<div></div>').appendTo(document
.body
)
4673 .addClass('ui-widget-overlay').css({
4674 width
: this.width(),
4675 height
: this.height()
4678 (dialog
.options
.bgiframe
&& $.fn
.bgiframe
&& $el
.bgiframe());
4680 this.instances
.push($el
);
4684 destroy: function($el
) {
4685 this.instances
.splice($.inArray(this.instances
, $el
), 1);
4687 if (this.instances
.length
=== 0) {
4688 $([document
, window
]).unbind('.dialog-overlay');
4694 height: function() {
4696 if ($.browser
.msie
&& $.browser
.version
< 7) {
4697 var scrollHeight
= Math
.max(
4698 document
.documentElement
.scrollHeight
,
4699 document
.body
.scrollHeight
4701 var offsetHeight
= Math
.max(
4702 document
.documentElement
.offsetHeight
,
4703 document
.body
.offsetHeight
4706 if (scrollHeight
< offsetHeight
) {
4707 return $(window
).height() + 'px';
4709 return scrollHeight
+ 'px';
4711 // handle "good" browsers
4713 return $(document
).height() + 'px';
4719 if ($.browser
.msie
&& $.browser
.version
< 7) {
4720 var scrollWidth
= Math
.max(
4721 document
.documentElement
.scrollWidth
,
4722 document
.body
.scrollWidth
4724 var offsetWidth
= Math
.max(
4725 document
.documentElement
.offsetWidth
,
4726 document
.body
.offsetWidth
4729 if (scrollWidth
< offsetWidth
) {
4730 return $(window
).width() + 'px';
4732 return scrollWidth
+ 'px';
4734 // handle "good" browsers
4736 return $(document
).width() + 'px';
4740 resize: function() {
4741 /* If the dialog is draggable and the user drags it past the
4742 * right edge of the window, the document becomes wider so we
4743 * need to stretch the overlay. If the user then drags the
4744 * dialog back to the left, the document will become narrower,
4745 * so we need to shrink the overlay to the appropriate size.
4746 * This is handled by shrinking the overlay before setting it
4747 * to the full document size.
4749 var $overlays
= $([]);
4750 $.each($.ui
.dialog
.overlay
.instances
, function() {
4751 $overlays
= $overlays
.add(this);
4758 width
: $.ui
.dialog
.overlay
.width(),
4759 height
: $.ui
.dialog
.overlay
.height()
4764 $.extend($.ui
.dialog
.overlay
.prototype, {
4765 destroy: function() {
4766 $.ui
.dialog
.overlay
.destroy(this.$el
);
4772 * jQuery UI Slider 1.7.1
4774 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
4775 * Dual licensed under the MIT (MIT-LICENSE.txt)
4776 * and GPL (GPL-LICENSE.txt) licenses.
4778 * http://docs.jquery.com/UI/Slider
4786 $.widget("ui.slider", $.extend({}, $.ui
.mouse
, {
4790 var self
= this, o
= this.options
;
4791 this._keySliding
= false;
4792 this._handleIndex
= null;
4793 this._detectOrientation();
4797 .addClass("ui-slider"
4798 + " ui-slider-" + this.orientation
4800 + " ui-widget-content"
4801 + " ui-corner-all");
4807 if (o
.range
=== true) {
4808 this.range
= $('<div></div>');
4809 if (!o
.values
) o
.values
= [this._valueMin(), this._valueMin()];
4810 if (o
.values
.length
&& o
.values
.length
!= 2) {
4811 o
.values
= [o
.values
[0], o
.values
[0]];
4814 this.range
= $('<div></div>');
4818 .appendTo(this.element
)
4819 .addClass("ui-slider-range");
4821 if (o
.range
== "min" || o
.range
== "max") {
4822 this.range
.addClass("ui-slider-range-" + o
.range
);
4825 // note: this isn't the most fittingly semantic framework class for this element,
4826 // but worked best visually with a variety of themes
4827 this.range
.addClass("ui-widget-header");
4831 if ($(".ui-slider-handle", this.element
).length
== 0)
4832 $('<a href="#"></a>')
4833 .appendTo(this.element
)
4834 .addClass("ui-slider-handle");
4836 if (o
.values
&& o
.values
.length
) {
4837 while ($(".ui-slider-handle", this.element
).length
< o
.values
.length
)
4838 $('<a href="#"></a>')
4839 .appendTo(this.element
)
4840 .addClass("ui-slider-handle");
4843 this.handles
= $(".ui-slider-handle", this.element
)
4844 .addClass("ui-state-default"
4845 + " ui-corner-all");
4847 this.handle
= this.handles
.eq(0);
4849 this.handles
.add(this.range
).filter("a")
4850 .click(function(event
) { event
.preventDefault(); })
4851 .hover(function() { $(this).addClass('ui-state-hover'); }, function() { $(this).removeClass('ui-state-hover'); })
4852 .focus(function() { $(".ui-slider .ui-state-focus").removeClass('ui-state-focus'); $(this).addClass('ui-state-focus'); })
4853 .blur(function() { $(this).removeClass('ui-state-focus'); });
4855 this.handles
.each(function(i
) {
4856 $(this).data("index.ui-slider-handle", i
);
4859 this.handles
.keydown(function(event
) {
4863 var index
= $(this).data("index.ui-slider-handle");
4865 if (self
.options
.disabled
)
4868 switch (event
.keyCode
) {
4869 case $.ui
.keyCode
.HOME
:
4870 case $.ui
.keyCode
.END
:
4871 case $.ui
.keyCode
.UP
:
4872 case $.ui
.keyCode
.RIGHT
:
4873 case $.ui
.keyCode
.DOWN
:
4874 case $.ui
.keyCode
.LEFT
:
4876 if (!self
._keySliding
) {
4877 self
._keySliding
= true;
4878 $(this).addClass("ui-state-active");
4879 self
._start(event
, index
);
4884 var curVal
, newVal
, step
= self
._step();
4885 if (self
.options
.values
&& self
.options
.values
.length
) {
4886 curVal
= newVal
= self
.values(index
);
4888 curVal
= newVal
= self
.value();
4891 switch (event
.keyCode
) {
4892 case $.ui
.keyCode
.HOME
:
4893 newVal
= self
._valueMin();
4895 case $.ui
.keyCode
.END
:
4896 newVal
= self
._valueMax();
4898 case $.ui
.keyCode
.UP
:
4899 case $.ui
.keyCode
.RIGHT
:
4900 if(curVal
== self
._valueMax()) return;
4901 newVal
= curVal
+ step
;
4903 case $.ui
.keyCode
.DOWN
:
4904 case $.ui
.keyCode
.LEFT
:
4905 if(curVal
== self
._valueMin()) return;
4906 newVal
= curVal
- step
;
4910 self
._slide(event
, index
, newVal
);
4914 }).keyup(function(event
) {
4916 var index
= $(this).data("index.ui-slider-handle");
4918 if (self
._keySliding
) {
4919 self
._stop(event
, index
);
4920 self
._change(event
, index
);
4921 self
._keySliding
= false;
4922 $(this).removeClass("ui-state-active");
4927 this._refreshValue();
4931 destroy: function() {
4933 this.handles
.remove();
4934 this.range
.remove();
4937 .removeClass("ui-slider"
4938 + " ui-slider-horizontal"
4939 + " ui-slider-vertical"
4940 + " ui-slider-disabled"
4942 + " ui-widget-content"
4944 .removeData("slider")
4947 this._mouseDestroy();
4951 _mouseCapture: function(event
) {
4953 var o
= this.options
;
4958 this.elementSize
= {
4959 width
: this.element
.outerWidth(),
4960 height
: this.element
.outerHeight()
4962 this.elementOffset
= this.element
.offset();
4964 var position
= { x
: event
.pageX
, y
: event
.pageY
};
4965 var normValue
= this._normValueFromMouse(position
);
4967 var distance
= this._valueMax() - this._valueMin() + 1, closestHandle
;
4968 var self
= this, index
;
4969 this.handles
.each(function(i
) {
4970 var thisDistance
= Math
.abs(normValue
- self
.values(i
));
4971 if (distance
> thisDistance
) {
4972 distance
= thisDistance
;
4973 closestHandle
= $(this);
4978 // workaround for bug #3736 (if both handles of a range are at 0,
4979 // the first is always used as the one with least distance,
4980 // and moving it is obviously prevented by preventing negative ranges)
4981 if(o
.range
== true && this.values(1) == o
.min
) {
4982 closestHandle
= $(this.handles
[++index
]);
4985 this._start(event
, index
);
4987 self
._handleIndex
= index
;
4990 .addClass("ui-state-active")
4993 var offset
= closestHandle
.offset();
4994 var mouseOverHandle
= !$(event
.target
).parents().andSelf().is('.ui-slider-handle');
4995 this._clickOffset
= mouseOverHandle
? { left
: 0, top
: 0 } : {
4996 left
: event
.pageX
- offset
.left
- (closestHandle
.width() / 2),
4997 top
: event
.pageY
- offset
.top
4998 - (closestHandle
.height() / 2)
4999 - (parseInt(closestHandle
.css('borderTopWidth'),10) || 0)
5000 - (parseInt(closestHandle
.css('borderBottomWidth'),10) || 0)
5001 + (parseInt(closestHandle
.css('marginTop'),10) || 0)
5004 normValue
= this._normValueFromMouse(position
);
5005 this._slide(event
, index
, normValue
);
5010 _mouseStart: function(event
) {
5014 _mouseDrag: function(event
) {
5016 var position
= { x
: event
.pageX
, y
: event
.pageY
};
5017 var normValue
= this._normValueFromMouse(position
);
5019 this._slide(event
, this._handleIndex
, normValue
);
5025 _mouseStop: function(event
) {
5027 this.handles
.removeClass("ui-state-active");
5028 this._stop(event
, this._handleIndex
);
5029 this._change(event
, this._handleIndex
);
5030 this._handleIndex
= null;
5031 this._clickOffset
= null;
5037 _detectOrientation: function() {
5038 this.orientation
= this.options
.orientation
== 'vertical' ? 'vertical' : 'horizontal';
5041 _normValueFromMouse: function(position
) {
5043 var pixelTotal
, pixelMouse
;
5044 if ('horizontal' == this.orientation
) {
5045 pixelTotal
= this.elementSize
.width
;
5046 pixelMouse
= position
.x
- this.elementOffset
.left
- (this._clickOffset
? this._clickOffset
.left
: 0);
5048 pixelTotal
= this.elementSize
.height
;
5049 pixelMouse
= position
.y
- this.elementOffset
.top
- (this._clickOffset
? this._clickOffset
.top
: 0);
5052 var percentMouse
= (pixelMouse
/ pixelTotal
);
5053 if (percentMouse
> 1) percentMouse
= 1;
5054 if (percentMouse
< 0) percentMouse
= 0;
5055 if ('vertical' == this.orientation
)
5056 percentMouse
= 1 - percentMouse
;
5058 var valueTotal
= this._valueMax() - this._valueMin(),
5059 valueMouse
= percentMouse
* valueTotal
,
5060 valueMouseModStep
= valueMouse
% this.options
.step
,
5061 normValue
= this._valueMin() + valueMouse
- valueMouseModStep
;
5063 if (valueMouseModStep
> (this.options
.step
/ 2))
5064 normValue
+= this.options
.step
;
5066 // Since JavaScript has problems with large floats, round
5067 // the final value to 5 digits after the decimal point (see #4124)
5068 return parseFloat(normValue
.toFixed(5));
5072 _start: function(event
, index
) {
5074 handle
: this.handles
[index
],
5077 if (this.options
.values
&& this.options
.values
.length
) {
5078 uiHash
.value
= this.values(index
)
5079 uiHash
.values
= this.values()
5081 this._trigger("start", event
, uiHash
);
5084 _slide: function(event
, index
, newVal
) {
5086 var handle
= this.handles
[index
];
5088 if (this.options
.values
&& this.options
.values
.length
) {
5090 var otherVal
= this.values(index
? 0 : 1);
5092 if ((index
== 0 && newVal
>= otherVal
) || (index
== 1 && newVal
<= otherVal
))
5095 if (newVal
!= this.values(index
)) {
5096 var newValues
= this.values();
5097 newValues
[index
] = newVal
;
5098 // A slide can be canceled by returning false from the slide callback
5099 var allowed
= this._trigger("slide", event
, {
5100 handle
: this.handles
[index
],
5104 var otherVal
= this.values(index
? 0 : 1);
5105 if (allowed
!== false) {
5106 this.values(index
, newVal
, ( event
.type
== 'mousedown' && this.options
.animate
), true);
5112 if (newVal
!= this.value()) {
5113 // A slide can be canceled by returning false from the slide callback
5114 var allowed
= this._trigger("slide", event
, {
5115 handle
: this.handles
[index
],
5118 if (allowed
!== false) {
5119 this._setData('value', newVal
, ( event
.type
== 'mousedown' && this.options
.animate
));
5128 _stop: function(event
, index
) {
5130 handle
: this.handles
[index
],
5133 if (this.options
.values
&& this.options
.values
.length
) {
5134 uiHash
.value
= this.values(index
)
5135 uiHash
.values
= this.values()
5137 this._trigger("stop", event
, uiHash
);
5140 _change: function(event
, index
) {
5142 handle
: this.handles
[index
],
5145 if (this.options
.values
&& this.options
.values
.length
) {
5146 uiHash
.value
= this.values(index
)
5147 uiHash
.values
= this.values()
5149 this._trigger("change", event
, uiHash
);
5152 value: function(newValue
) {
5154 if (arguments
.length
) {
5155 this._setData("value", newValue
);
5156 this._change(null, 0);
5159 return this._value();
5163 values: function(index
, newValue
, animated
, noPropagation
) {
5165 if (arguments
.length
> 1) {
5166 this.options
.values
[index
] = newValue
;
5167 this._refreshValue(animated
);
5168 if(!noPropagation
) this._change(null, index
);
5171 if (arguments
.length
) {
5172 if (this.options
.values
&& this.options
.values
.length
) {
5173 return this._values(index
);
5175 return this.value();
5178 return this._values();
5183 _setData: function(key
, value
, animated
) {
5185 $.widget
.prototype._setData
.apply(this, arguments
);
5190 this._detectOrientation();
5193 .removeClass("ui-slider-horizontal ui-slider-vertical")
5194 .addClass("ui-slider-" + this.orientation
);
5195 this._refreshValue(animated
);
5198 this._refreshValue(animated
);
5205 var step
= this.options
.step
;
5209 _value: function() {
5211 var val
= this.options
.value
;
5212 if (val
< this._valueMin()) val
= this._valueMin();
5213 if (val
> this._valueMax()) val
= this._valueMax();
5219 _values: function(index
) {
5221 if (arguments
.length
) {
5222 var val
= this.options
.values
[index
];
5223 if (val
< this._valueMin()) val
= this._valueMin();
5224 if (val
> this._valueMax()) val
= this._valueMax();
5228 return this.options
.values
;
5233 _valueMin: function() {
5234 var valueMin
= this.options
.min
;
5238 _valueMax: function() {
5239 var valueMax
= this.options
.max
;
5243 _refreshValue: function(animate
) {
5245 var oRange
= this.options
.range
, o
= this.options
, self
= this;
5247 if (this.options
.values
&& this.options
.values
.length
) {
5249 this.handles
.each(function(i
, j
) {
5250 var valPercent
= (self
.values(i
) - self
._valueMin()) / (self
._valueMax() - self
._valueMin()) * 100;
5251 var _set
= {}; _set
[self
.orientation
== 'horizontal' ? 'left' : 'bottom'] = valPercent
+ '%';
5252 $(this).stop(1,1)[animate
? 'animate' : 'css'](_set
, o
.animate
);
5253 if (self
.options
.range
=== true) {
5254 if (self
.orientation
== 'horizontal') {
5255 (i
== 0) && self
.range
.stop(1,1)[animate
? 'animate' : 'css']({ left
: valPercent
+ '%' }, o
.animate
);
5256 (i
== 1) && self
.range
[animate
? 'animate' : 'css']({ width
: (valPercent
- lastValPercent
) + '%' }, { queue
: false, duration
: o
.animate
});
5258 (i
== 0) && self
.range
.stop(1,1)[animate
? 'animate' : 'css']({ bottom
: (valPercent
) + '%' }, o
.animate
);
5259 (i
== 1) && self
.range
[animate
? 'animate' : 'css']({ height
: (valPercent
- lastValPercent
) + '%' }, { queue
: false, duration
: o
.animate
});
5262 lastValPercent
= valPercent
;
5265 var value
= this.value(),
5266 valueMin
= this._valueMin(),
5267 valueMax
= this._valueMax(),
5268 valPercent
= valueMax
!= valueMin
5269 ? (value
- valueMin
) / (valueMax
- valueMin
) * 100
5271 var _set
= {}; _set
[self
.orientation
== 'horizontal' ? 'left' : 'bottom'] = valPercent
+ '%';
5272 this.handle
.stop(1,1)[animate
? 'animate' : 'css'](_set
, o
.animate
);
5274 (oRange
== "min") && (this.orientation
== "horizontal") && this.range
.stop(1,1)[animate
? 'animate' : 'css']({ width
: valPercent
+ '%' }, o
.animate
);
5275 (oRange
== "max") && (this.orientation
== "horizontal") && this.range
[animate
? 'animate' : 'css']({ width
: (100 - valPercent
) + '%' }, { queue
: false, duration
: o
.animate
});
5276 (oRange
== "min") && (this.orientation
== "vertical") && this.range
.stop(1,1)[animate
? 'animate' : 'css']({ height
: valPercent
+ '%' }, o
.animate
);
5277 (oRange
== "max") && (this.orientation
== "vertical") && this.range
[animate
? 'animate' : 'css']({ height
: (100 - valPercent
) + '%' }, { queue
: false, duration
: o
.animate
});
5284 $.extend($.ui
.slider
, {
5285 getter
: "value values",
5287 eventPrefix
: "slide",
5294 orientation
: 'horizontal',
5304 * jQuery UI Tabs 1.7.1
5306 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
5307 * Dual licensed under the MIT (MIT-LICENSE.txt)
5308 * and GPL (GPL-LICENSE.txt) licenses.
5310 * http://docs.jquery.com/UI/Tabs
5317 $.widget("ui.tabs", {
5320 if (this.options
.deselectable
!== undefined) {
5321 this.options
.collapsible
= this.options
.deselectable
;
5326 _setData: function(key
, value
) {
5327 if (key
== 'selected') {
5328 if (this.options
.collapsible
&& value
== this.options
.selected
) {
5334 this.options
[key
] = value
;
5335 if (key
== 'deselectable') {
5336 this.options
.collapsible
= value
;
5342 _tabId: function(a
) {
5343 return a
.title
&& a
.title
.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '') ||
5344 this.options
.idPrefix
+ $.data(a
);
5347 _sanitizeSelector: function(hash
) {
5348 return hash
.replace(/:/g, '\\:'); // we need
this because an id may contain a
":"
5351 _cookie: function() {
5352 var cookie
= this.cookie
|| (this.cookie
= this.options
.cookie
.name
|| 'ui-tabs-' + $.data(this.list
[0]));
5353 return $.cookie
.apply(null, [cookie
].concat($.makeArray(arguments
)));
5356 _ui: function(tab
, panel
) {
5360 index
: this.anchors
.index(tab
)
5364 _cleanup: function() {
5365 // restore all former loading tabs labels
5366 this.lis
.filter('.ui-state-processing').removeClass('ui-state-processing')
5367 .find('span:data(label.tabs)')
5370 el
.html(el
.data('label.tabs')).removeData('label.tabs');
5374 _tabify: function(init
) {
5376 this.list
= this.element
.children('ul:first');
5377 this.lis
= $('li:has(a[href])', this.list
);
5378 this.anchors
= this.lis
.map(function() { return $('a', this)[0]; });
5379 this.panels
= $([]);
5381 var self
= this, o
= this.options
;
5383 var fragmentId
= /^#.+/; // Safari 2 reports '#' for an empty hash
5384 this.anchors
.each(function(i
, a
) {
5385 var href
= $(a
).attr('href');
5387 // For dynamically created HTML that contains a hash as href IE < 8 expands
5388 // such href to the full page url with hash and then misinterprets tab as ajax.
5389 // Same consideration applies for an added tab with a fragment identifier
5390 // since a[href=#fragment-identifier] does unexpectedly not match.
5391 // Thus normalize href attribute...
5392 var hrefBase
= href
.split('#')[0], baseEl
;
5393 if (hrefBase
&& (hrefBase
=== location
.toString().split('#')[0] ||
5394 (baseEl
= $('base')[0]) && hrefBase
=== baseEl
.href
)) {
5400 if (fragmentId
.test(href
)) {
5401 self
.panels
= self
.panels
.add(self
._sanitizeSelector(href
));
5405 else if (href
!= '#') { // prevent loading the page itself if href is just "#"
5406 $.data(a
, 'href.tabs', href
); // required for restore on destroy
5408 // TODO until #3808 is fixed strip fragment identifier from url
5409 // (IE fails to load from such url)
5410 $.data(a
, 'load.tabs', href
.replace(/#.*$/, '')); // mutable data
5412 var id
= self
._tabId(a
);
5414 var $panel
= $('#' + id
);
5415 if (!$panel
.length
) {
5416 $panel
= $(o
.panelTemplate
).attr('id', id
).addClass('ui-tabs-panel ui-widget-content ui-corner-bottom')
5417 .insertAfter(self
.panels
[i
- 1] || self
.list
);
5418 $panel
.data('destroy.tabs', true);
5420 self
.panels
= self
.panels
.add($panel
);
5429 // initialization from scratch
5432 // attach necessary classes for styling
5433 this.element
.addClass('ui-tabs ui-widget ui-widget-content ui-corner-all');
5434 this.list
.addClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
5435 this.lis
.addClass('ui-state-default ui-corner-top');
5436 this.panels
.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom');
5439 // use "selected" option or try to retrieve:
5440 // 1. from fragment identifier in url
5442 // 3. from selected class attribute on <li>
5443 if (o
.selected
=== undefined) {
5444 if (location
.hash
) {
5445 this.anchors
.each(function(i
, a
) {
5446 if (a
.hash
== location
.hash
) {
5448 return false; // break
5452 if (typeof o
.selected
!= 'number' && o
.cookie
) {
5453 o
.selected
= parseInt(self
._cookie(), 10);
5455 if (typeof o
.selected
!= 'number' && this.lis
.filter('.ui-tabs-selected').length
) {
5456 o
.selected
= this.lis
.index(this.lis
.filter('.ui-tabs-selected'));
5458 o
.selected
= o
.selected
|| 0;
5460 else if (o
.selected
=== null) { // usage of null is deprecated, TODO remove in next release
5464 // sanity check - default to first tab...
5465 o
.selected
= ((o
.selected
>= 0 && this.anchors
[o
.selected
]) || o
.selected
< 0) ? o
.selected
: 0;
5467 // Take disabling tabs via class attribute from HTML
5468 // into account and update option properly.
5469 // A selected tab cannot become disabled.
5470 o
.disabled
= $.unique(o
.disabled
.concat(
5471 $.map(this.lis
.filter('.ui-state-disabled'),
5472 function(n
, i
) { return self
.lis
.index(n
); } )
5475 if ($.inArray(o
.selected
, o
.disabled
) != -1) {
5476 o
.disabled
.splice($.inArray(o
.selected
, o
.disabled
), 1);
5479 // highlight selected tab
5480 this.panels
.addClass('ui-tabs-hide');
5481 this.lis
.removeClass('ui-tabs-selected ui-state-active');
5482 if (o
.selected
>= 0 && this.anchors
.length
) { // check for length avoids error when initializing empty list
5483 this.panels
.eq(o
.selected
).removeClass('ui-tabs-hide');
5484 this.lis
.eq(o
.selected
).addClass('ui-tabs-selected ui-state-active');
5486 // seems to be expected behavior that the show callback is fired
5487 self
.element
.queue("tabs", function() {
5488 self
._trigger('show', null, self
._ui(self
.anchors
[o
.selected
], self
.panels
[o
.selected
]));
5491 this.load(o
.selected
);
5494 // clean up to avoid memory leaks in certain versions of IE 6
5495 $(window
).bind('unload', function() {
5496 self
.lis
.add(self
.anchors
).unbind('.tabs');
5497 self
.lis
= self
.anchors
= self
.panels
= null;
5501 // update selected after add/remove
5503 o
.selected
= this.lis
.index(this.lis
.filter('.ui-tabs-selected'));
5506 // update collapsible
5507 this.element
[o
.collapsible
? 'addClass' : 'removeClass']('ui-tabs-collapsible');
5509 // set or update cookie after init and add/remove respectively
5511 this._cookie(o
.selected
, o
.cookie
);
5515 for (var i
= 0, li
; (li
= this.lis
[i
]); i
++) {
5516 $(li
)[$.inArray(i
, o
.disabled
) != -1 &&
5517 !$(li
).hasClass('ui-tabs-selected') ? 'addClass' : 'removeClass']('ui-state-disabled');
5520 // reset cache if switching from cached to not cached
5521 if (o
.cache
=== false) {
5522 this.anchors
.removeData('cache.tabs');
5525 // remove all handlers before, tabify may run on existing tabs after add or option change
5526 this.lis
.add(this.anchors
).unbind('.tabs');
5528 if (o
.event
!= 'mouseover') {
5529 var addState = function(state
, el
) {
5530 if (el
.is(':not(.ui-state-disabled)')) {
5531 el
.addClass('ui-state-' + state
);
5534 var removeState = function(state
, el
) {
5535 el
.removeClass('ui-state-' + state
);
5537 this.lis
.bind('mouseover.tabs', function() {
5538 addState('hover', $(this));
5540 this.lis
.bind('mouseout.tabs', function() {
5541 removeState('hover', $(this));
5543 this.anchors
.bind('focus.tabs', function() {
5544 addState('focus', $(this).closest('li'));
5546 this.anchors
.bind('blur.tabs', function() {
5547 removeState('focus', $(this).closest('li'));
5551 // set up animations
5554 if ($.isArray(o
.fx
)) {
5559 hideFx
= showFx
= o
.fx
;
5563 // Reset certain styles left over from animation
5564 // and prevent IE's ClearType bug...
5565 function resetStyle($el
, fx
) {
5566 $el
.css({ display
: '' });
5567 if ($.browser
.msie
&& fx
.opacity
) {
5568 $el
[0].style
.removeAttribute('filter');
5573 var showTab
= showFx
?
5574 function(clicked
, $show
) {
5575 $(clicked
).closest('li').removeClass('ui-state-default').addClass('ui-tabs-selected ui-state-active');
5576 $show
.hide().removeClass('ui-tabs-hide') // avoid flicker that way
5577 .animate(showFx
, showFx
.duration
|| 'normal', function() {
5578 resetStyle($show
, showFx
);
5579 self
._trigger('show', null, self
._ui(clicked
, $show
[0]));
5582 function(clicked
, $show
) {
5583 $(clicked
).closest('li').removeClass('ui-state-default').addClass('ui-tabs-selected ui-state-active');
5584 $show
.removeClass('ui-tabs-hide');
5585 self
._trigger('show', null, self
._ui(clicked
, $show
[0]));
5588 // Hide a tab, $show is optional...
5589 var hideTab
= hideFx
?
5590 function(clicked
, $hide
) {
5591 $hide
.animate(hideFx
, hideFx
.duration
|| 'normal', function() {
5592 self
.lis
.removeClass('ui-tabs-selected ui-state-active').addClass('ui-state-default');
5593 $hide
.addClass('ui-tabs-hide');
5594 resetStyle($hide
, hideFx
);
5595 self
.element
.dequeue("tabs");
5598 function(clicked
, $hide
, $show
) {
5599 self
.lis
.removeClass('ui-tabs-selected ui-state-active').addClass('ui-state-default');
5600 $hide
.addClass('ui-tabs-hide');
5601 self
.element
.dequeue("tabs");
5604 // attach tab event handler, unbind to avoid duplicates from former tabifying...
5605 this.anchors
.bind(o
.event
+ '.tabs', function() {
5606 var el
= this, $li
= $(this).closest('li'), $hide
= self
.panels
.filter(':not(.ui-tabs-hide)'),
5607 $show
= $(self
._sanitizeSelector(this.hash
));
5609 // If tab is already selected and not collapsible or tab disabled or
5610 // or is already loading or click callback returns false stop here.
5611 // Check if click handler returns false last so that it is not executed
5612 // for a disabled or loading tab!
5613 if (($li
.hasClass('ui-tabs-selected') && !o
.collapsible
) ||
5614 $li
.hasClass('ui-state-disabled') ||
5615 $li
.hasClass('ui-state-processing') ||
5616 self
._trigger('select', null, self
._ui(this, $show
[0])) === false) {
5621 o
.selected
= self
.anchors
.index(this);
5625 // if tab may be closed
5626 if (o
.collapsible
) {
5627 if ($li
.hasClass('ui-tabs-selected')) {
5631 self
._cookie(o
.selected
, o
.cookie
);
5634 self
.element
.queue("tabs", function() {
5641 else if (!$hide
.length
) {
5643 self
._cookie(o
.selected
, o
.cookie
);
5646 self
.element
.queue("tabs", function() {
5650 self
.load(self
.anchors
.index(this)); // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
5658 self
._cookie(o
.selected
, o
.cookie
);
5664 self
.element
.queue("tabs", function() {
5668 self
.element
.queue("tabs", function() {
5672 self
.load(self
.anchors
.index(this));
5675 throw 'jQuery UI Tabs: Mismatching fragment identifier.';
5678 // Prevent IE from keeping other link focussed when using the back button
5679 // and remove dotted border from clicked link. This is controlled via CSS
5680 // in modern browsers; blur() removes focus from address bar in Firefox
5681 // which can become a usability and annoying problem with tabs('rotate').
5682 if ($.browser
.msie
) {
5688 // disable click in any case
5689 this.anchors
.bind('click.tabs', function(){return false;});
5693 destroy: function() {
5694 var o
= this.options
;
5698 this.element
.unbind('.tabs')
5699 .removeClass('ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible')
5700 .removeData('tabs');
5702 this.list
.removeClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
5704 this.anchors
.each(function() {
5705 var href
= $.data(this, 'href.tabs');
5709 var $this = $(this).unbind('.tabs');
5710 $.each(['href', 'load', 'cache'], function(i
, prefix
) {
5711 $this.removeData(prefix
+ '.tabs');
5715 this.lis
.unbind('.tabs').add(this.panels
).each(function() {
5716 if ($.data(this, 'destroy.tabs')) {
5720 $(this).removeClass([
5727 'ui-state-disabled',
5729 'ui-widget-content',
5737 this._cookie(null, o
.cookie
);
5741 add: function(url
, label
, index
) {
5742 if (index
=== undefined) {
5743 index
= this.anchors
.length
; // append by default
5746 var self
= this, o
= this.options
,
5747 $li
= $(o
.tabTemplate
.replace(/#\{href\}/g, url
).replace(/#\{label\}/g, label
)),
5748 id
= !url
.indexOf('#') ? url
.replace('#', '') : this._tabId($('a', $li
)[0]);
5750 $li
.addClass('ui-state-default ui-corner-top').data('destroy.tabs', true);
5752 // try to find an existing element before creating a new one
5753 var $panel
= $('#' + id
);
5754 if (!$panel
.length
) {
5755 $panel
= $(o
.panelTemplate
).attr('id', id
).data('destroy.tabs', true);
5757 $panel
.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide');
5759 if (index
>= this.lis
.length
) {
5760 $li
.appendTo(this.list
);
5761 $panel
.appendTo(this.list
[0].parentNode
);
5764 $li
.insertBefore(this.lis
[index
]);
5765 $panel
.insertBefore(this.panels
[index
]);
5768 o
.disabled
= $.map(o
.disabled
,
5769 function(n
, i
) { return n
>= index
? ++n
: n
; });
5773 if (this.anchors
.length
== 1) { // after tabify
5774 $li
.addClass('ui-tabs-selected ui-state-active');
5775 $panel
.removeClass('ui-tabs-hide');
5776 this.element
.queue("tabs", function() {
5777 self
._trigger('show', null, self
._ui(self
.anchors
[0], self
.panels
[0]));
5784 this._trigger('add', null, this._ui(this.anchors
[index
], this.panels
[index
]));
5787 remove: function(index
) {
5788 var o
= this.options
, $li
= this.lis
.eq(index
).remove(),
5789 $panel
= this.panels
.eq(index
).remove();
5791 // If selected tab was removed focus tab to the right or
5792 // in case the last tab was removed the tab to the left.
5793 if ($li
.hasClass('ui-tabs-selected') && this.anchors
.length
> 1) {
5794 this.select(index
+ (index
+ 1 < this.anchors
.length
? 1 : -1));
5797 o
.disabled
= $.map($.grep(o
.disabled
, function(n
, i
) { return n
!= index
; }),
5798 function(n
, i
) { return n
>= index
? --n
: n
; });
5803 this._trigger('remove', null, this._ui($li
.find('a')[0], $panel
[0]));
5806 enable: function(index
) {
5807 var o
= this.options
;
5808 if ($.inArray(index
, o
.disabled
) == -1) {
5812 this.lis
.eq(index
).removeClass('ui-state-disabled');
5813 o
.disabled
= $.grep(o
.disabled
, function(n
, i
) { return n
!= index
; });
5816 this._trigger('enable', null, this._ui(this.anchors
[index
], this.panels
[index
]));
5819 disable: function(index
) {
5820 var self
= this, o
= this.options
;
5821 if (index
!= o
.selected
) { // cannot disable already selected tab
5822 this.lis
.eq(index
).addClass('ui-state-disabled');
5824 o
.disabled
.push(index
);
5828 this._trigger('disable', null, this._ui(this.anchors
[index
], this.panels
[index
]));
5832 select: function(index
) {
5833 if (typeof index
== 'string') {
5834 index
= this.anchors
.index(this.anchors
.filter('[href$=' + index
+ ']'));
5836 else if (index
=== null) { // usage of null is deprecated, TODO remove in next release
5839 if (index
== -1 && this.options
.collapsible
) {
5840 index
= this.options
.selected
;
5843 this.anchors
.eq(index
).trigger(this.options
.event
+ '.tabs');
5846 load: function(index
) {
5847 var self
= this, o
= this.options
, a
= this.anchors
.eq(index
)[0], url
= $.data(a
, 'load.tabs');
5851 // not remote or from cache
5852 if (!url
|| this.element
.queue("tabs").length
!== 0 && $.data(a
, 'cache.tabs')) {
5853 this.element
.dequeue("tabs");
5857 // load remote from here on
5858 this.lis
.eq(index
).addClass('ui-state-processing');
5861 var span
= $('span', a
);
5862 span
.data('label.tabs', span
.html()).html(o
.spinner
);
5865 this.xhr
= $.ajax($.extend({}, o
.ajaxOptions
, {
5867 success: function(r
, s
) {
5868 $(self
._sanitizeSelector(a
.hash
)).html(r
);
5870 // take care of tab labels
5874 $.data(a
, 'cache.tabs', true); // if loaded once do not load them again
5878 self
._trigger('load', null, self
._ui(self
.anchors
[index
], self
.panels
[index
]));
5880 o
.ajaxOptions
.success(r
, s
);
5884 // last, so that load event is fired before show...
5885 self
.element
.dequeue("tabs");
5891 // stop possibly running animations
5892 this.element
.queue([]);
5893 this.panels
.stop(false, true);
5895 // terminate pending requests from other tabs
5901 // take care of tab labels
5906 url: function(index
, url
) {
5907 this.anchors
.eq(index
).removeData('cache.tabs').data('load.tabs', url
);
5910 length: function() {
5911 return this.anchors
.length
;
5916 $.extend($.ui
.tabs
, {
5922 cookie
: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
5926 fx
: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
5927 idPrefix
: 'ui-tabs-',
5928 panelTemplate
: '<div></div>',
5929 spinner
: '<em>Loading…</em>',
5930 tabTemplate
: '<li><a href="#{href}"><span>#{label}</span></a></li>'
5941 $.extend($.ui
.tabs
.prototype, {
5943 rotate: function(ms
, continuing
) {
5945 var self
= this, o
= this.options
;
5947 var rotate
= self
._rotate
|| (self
._rotate = function(e
) {
5948 clearTimeout(self
.rotation
);
5949 self
.rotation
= setTimeout(function() {
5951 self
.select( ++t
< self
.anchors
.length
? t
: 0 );
5955 e
.stopPropagation();
5959 var stop
= self
._unrotate
|| (self
._unrotate
= !continuing
?
5961 if (e
.clientX
) { // in case of a true click
5972 this.element
.bind('tabsshow', rotate
);
5973 this.anchors
.bind(o
.event
+ '.tabs', stop
);
5978 clearTimeout(self
.rotation
);
5979 this.element
.unbind('tabsshow', rotate
);
5980 this.anchors
.unbind(o
.event
+ '.tabs', stop
);
5981 delete this._rotate
;
5982 delete this._unrotate
;
5989 * jQuery UI Datepicker 1.7.1
5991 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
5992 * Dual licensed under the MIT (MIT-LICENSE.txt)
5993 * and GPL (GPL-LICENSE.txt) licenses.
5995 * http://docs.jquery.com/UI/Datepicker
6001 (function($) { // hide the namespace
6003 $.extend($.ui
, { datepicker
: { version
: "1.7.1" } });
6005 var PROP_NAME
= 'datepicker';
6007 /* Date picker manager.
6008 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
6009 Settings for (groups of) date pickers are maintained in an instance object,
6010 allowing multiple different settings on the same page. */
6012 function Datepicker() {
6013 this.debug
= false; // Change this to true to start debugging
6014 this._curInst
= null; // The current instance in use
6015 this._keyEvent
= false; // If the last event was a key event
6016 this._disabledInputs
= []; // List of date picker inputs that have been disabled
6017 this._datepickerShowing
= false; // True if the popup picker is showing , false if not
6018 this._inDialog
= false; // True if showing within a "dialog", false if not
6019 this._mainDivId
= 'ui-datepicker-div'; // The ID of the main datepicker division
6020 this._inlineClass
= 'ui-datepicker-inline'; // The name of the inline marker class
6021 this._appendClass
= 'ui-datepicker-append'; // The name of the append marker class
6022 this._triggerClass
= 'ui-datepicker-trigger'; // The name of the trigger marker class
6023 this._dialogClass
= 'ui-datepicker-dialog'; // The name of the dialog marker class
6024 this._disableClass
= 'ui-datepicker-disabled'; // The name of the disabled covering marker class
6025 this._unselectableClass
= 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
6026 this._currentClass
= 'ui-datepicker-current-day'; // The name of the current day marker class
6027 this._dayOverClass
= 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
6028 this.regional
= []; // Available regional settings, indexed by language code
6029 this.regional
[''] = { // Default regional settings
6030 closeText
: 'Done', // Display text for close link
6031 prevText
: 'Prev', // Display text for previous month link
6032 nextText
: 'Next', // Display text for next month link
6033 currentText
: 'Today', // Display text for current month link
6034 monthNames
: ['January','February','March','April','May','June',
6035 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
6036 monthNamesShort
: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
6037 dayNames
: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
6038 dayNamesShort
: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
6039 dayNamesMin
: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
6040 dateFormat
: 'mm/dd/yy', // See format options on parseDate
6041 firstDay
: 0, // The first day of the week, Sun = 0, Mon = 1, ...
6042 isRTL
: false // True if right-to-left language, false if left-to-right
6044 this._defaults
= { // Global defaults for all the date picker instances
6045 showOn
: 'focus', // 'focus' for popup on focus,
6046 // 'button' for trigger button, or 'both' for either
6047 showAnim
: 'show', // Name of jQuery animation for popup
6048 showOptions
: {}, // Options for enhanced animations
6049 defaultDate
: null, // Used when field is blank: actual date,
6050 // +/-number for offset from today, null for today
6051 appendText
: '', // Display text following the input box, e.g. showing the format
6052 buttonText
: '...', // Text for trigger button
6053 buttonImage
: '', // URL for trigger button image
6054 buttonImageOnly
: false, // True if the image appears alone, false if it appears on a button
6055 hideIfNoPrevNext
: false, // True to hide next/previous month links
6056 // if not applicable, false to just disable them
6057 navigationAsDateFormat
: false, // True if date formatting applied to prev/today/next links
6058 gotoCurrent
: false, // True if today link goes back to current selection instead
6059 changeMonth
: false, // True if month can be selected directly, false if only prev/next
6060 changeYear
: false, // True if year can be selected directly, false if only prev/next
6061 showMonthAfterYear
: false, // True if the year select precedes month, false for month then year
6062 yearRange
: '-10:+10', // Range of years to display in drop-down,
6063 // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn)
6064 showOtherMonths
: false, // True to show dates in other months, false to leave blank
6065 calculateWeek
: this.iso8601Week
, // How to calculate the week of the year,
6066 // takes a Date and returns the number of the week for it
6067 shortYearCutoff
: '+10', // Short year values < this are in the current century,
6068 // > this are in the previous century,
6069 // string value starting with '+' for current year + value
6070 minDate
: null, // The earliest selectable date, or null for no limit
6071 maxDate
: null, // The latest selectable date, or null for no limit
6072 duration
: 'normal', // Duration of display/closure
6073 beforeShowDay
: null, // Function that takes a date and returns an array with
6074 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
6075 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
6076 beforeShow
: null, // Function that takes an input field and
6077 // returns a set of custom settings for the date picker
6078 onSelect
: null, // Define a callback function when a date is selected
6079 onChangeMonthYear
: null, // Define a callback function when the month or year is changed
6080 onClose
: null, // Define a callback function when the datepicker is closed
6081 numberOfMonths
: 1, // Number of months to show at a time
6082 showCurrentAtPos
: 0, // The position in multipe months at which to show the current month (starting at 0)
6083 stepMonths
: 1, // Number of months to step back/forward
6084 stepBigMonths
: 12, // Number of months to step back/forward for the big links
6085 altField
: '', // Selector for an alternate field to store selected dates into
6086 altFormat
: '', // The date format to use for the alternate field
6087 constrainInput
: true, // The input is constrained by the current date format
6088 showButtonPanel
: false // True to show button panel, false to not show it
6090 $.extend(this._defaults
, this.regional
['']);
6091 this.dpDiv
= $('<div id="' + this._mainDivId
+ '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
6094 $.extend(Datepicker
.prototype, {
6095 /* Class name added to elements to indicate already configured with a date picker. */
6096 markerClassName
: 'hasDatepicker',
6098 /* Debug logging (if enabled). */
6101 console
.log
.apply('', arguments
);
6104 /* Override the default settings for all instances of the date picker.
6105 @param settings object - the new settings to use as defaults (anonymous object)
6106 @return the manager object */
6107 setDefaults: function(settings
) {
6108 extendRemove(this._defaults
, settings
|| {});
6112 /* Attach the date picker to a jQuery selection.
6113 @param target element - the target input field or division or span
6114 @param settings object - the new settings to use for this date picker instance (anonymous) */
6115 _attachDatepicker: function(target
, settings
) {
6116 // check for settings on the control itself - in namespace 'date:'
6117 var inlineSettings
= null;
6118 for (var attrName
in this._defaults
) {
6119 var attrValue
= target
.getAttribute('date:' + attrName
);
6121 inlineSettings
= inlineSettings
|| {};
6123 inlineSettings
[attrName
] = eval(attrValue
);
6125 inlineSettings
[attrName
] = attrValue
;
6129 var nodeName
= target
.nodeName
.toLowerCase();
6130 var inline
= (nodeName
== 'div' || nodeName
== 'span');
6132 target
.id
= 'dp' + (++this.uuid
);
6133 var inst
= this._newInst($(target
), inline
);
6134 inst
.settings
= $.extend({}, settings
|| {}, inlineSettings
|| {});
6135 if (nodeName
== 'input') {
6136 this._connectDatepicker(target
, inst
);
6137 } else if (inline
) {
6138 this._inlineDatepicker(target
, inst
);
6142 /* Create a new instance object. */
6143 _newInst: function(target
, inline
) {
6144 var id
= target
[0].id
.replace(/([:\[\]\.])/g, '\\\\$1'); // escape jQuery meta chars
6145 return {id
: id
, input
: target
, // associated target
6146 selectedDay
: 0, selectedMonth
: 0, selectedYear
: 0, // current selection
6147 drawMonth
: 0, drawYear
: 0, // month being drawn
6148 inline
: inline
, // is datepicker inline or not
6149 dpDiv
: (!inline
? this.dpDiv
: // presentation div
6150 $('<div class="' + this._inlineClass
+ ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
6153 /* Attach the date picker to an input field. */
6154 _connectDatepicker: function(target
, inst
) {
6155 var input
= $(target
);
6156 inst
.trigger
= $([]);
6157 if (input
.hasClass(this.markerClassName
))
6159 var appendText
= this._get(inst
, 'appendText');
6160 var isRTL
= this._get(inst
, 'isRTL');
6162 input
[isRTL
? 'before' : 'after']('<span class="' + this._appendClass
+ '">' + appendText
+ '</span>');
6163 var showOn
= this._get(inst
, 'showOn');
6164 if (showOn
== 'focus' || showOn
== 'both') // pop-up date picker when in the marked field
6165 input
.focus(this._showDatepicker
);
6166 if (showOn
== 'button' || showOn
== 'both') { // pop-up date picker when button clicked
6167 var buttonText
= this._get(inst
, 'buttonText');
6168 var buttonImage
= this._get(inst
, 'buttonImage');
6169 inst
.trigger
= $(this._get(inst
, 'buttonImageOnly') ?
6170 $('<img/>').addClass(this._triggerClass
).
6171 attr({ src
: buttonImage
, alt
: buttonText
, title
: buttonText
}) :
6172 $('<button type="button"></button>').addClass(this._triggerClass
).
6173 html(buttonImage
== '' ? buttonText
: $('<img/>').attr(
6174 { src
:buttonImage
, alt
:buttonText
, title
:buttonText
})));
6175 input
[isRTL
? 'before' : 'after'](inst
.trigger
);
6176 inst
.trigger
.click(function() {
6177 if ($.datepicker
._datepickerShowing
&& $.datepicker
._lastInput
== target
)
6178 $.datepicker
._hideDatepicker();
6180 $.datepicker
._showDatepicker(target
);
6184 input
.addClass(this.markerClassName
).keydown(this._doKeyDown
).keypress(this._doKeyPress
).
6185 bind("setData.datepicker", function(event
, key
, value
) {
6186 inst
.settings
[key
] = value
;
6187 }).bind("getData.datepicker", function(event
, key
) {
6188 return this._get(inst
, key
);
6190 $.data(target
, PROP_NAME
, inst
);
6193 /* Attach an inline date picker to a div. */
6194 _inlineDatepicker: function(target
, inst
) {
6195 var divSpan
= $(target
);
6196 if (divSpan
.hasClass(this.markerClassName
))
6198 divSpan
.addClass(this.markerClassName
).append(inst
.dpDiv
).
6199 bind("setData.datepicker", function(event
, key
, value
){
6200 inst
.settings
[key
] = value
;
6201 }).bind("getData.datepicker", function(event
, key
){
6202 return this._get(inst
, key
);
6204 $.data(target
, PROP_NAME
, inst
);
6205 this._setDate(inst
, this._getDefaultDate(inst
));
6206 this._updateDatepicker(inst
);
6207 this._updateAlternate(inst
);
6210 /* Pop-up the date picker in a "dialog" box.
6211 @param input element - ignored
6212 @param dateText string - the initial date to display (in the current format)
6213 @param onSelect function - the function(dateText) to call when a date is selected
6214 @param settings object - update the dialog date picker instance's settings (anonymous object)
6215 @param pos int[2] - coordinates for the dialog's position within the screen or
6216 event - with x/y coordinates or
6217 leave empty for default (screen centre)
6218 @return the manager object */
6219 _dialogDatepicker: function(input
, dateText
, onSelect
, settings
, pos
) {
6220 var inst
= this._dialogInst
; // internal instance
6222 var id
= 'dp' + (++this.uuid
);
6223 this._dialogInput
= $('<input type="text" id="' + id
+
6224 '" size="1" style="position: absolute; top: -100px;"/>');
6225 this._dialogInput
.keydown(this._doKeyDown
);
6226 $('body').append(this._dialogInput
);
6227 inst
= this._dialogInst
= this._newInst(this._dialogInput
, false);
6229 $.data(this._dialogInput
[0], PROP_NAME
, inst
);
6231 extendRemove(inst
.settings
, settings
|| {});
6232 this._dialogInput
.val(dateText
);
6234 this._pos
= (pos
? (pos
.length
? pos
: [pos
.pageX
, pos
.pageY
]) : null);
6236 var browserWidth
= window
.innerWidth
|| document
.documentElement
.clientWidth
|| document
.body
.clientWidth
;
6237 var browserHeight
= window
.innerHeight
|| document
.documentElement
.clientHeight
|| document
.body
.clientHeight
;
6238 var scrollX
= document
.documentElement
.scrollLeft
|| document
.body
.scrollLeft
;
6239 var scrollY
= document
.documentElement
.scrollTop
|| document
.body
.scrollTop
;
6240 this._pos
= // should use actual width/height below
6241 [(browserWidth
/ 2) - 100 + scrollX
, (browserHeight
/ 2) - 150 + scrollY
];
6244 // move input on screen for focus, but hidden behind dialog
6245 this._dialogInput
.css('left', this._pos
[0] + 'px').css('top', this._pos
[1] + 'px');
6246 inst
.settings
.onSelect
= onSelect
;
6247 this._inDialog
= true;
6248 this.dpDiv
.addClass(this._dialogClass
);
6249 this._showDatepicker(this._dialogInput
[0]);
6251 $.blockUI(this.dpDiv
);
6252 $.data(this._dialogInput
[0], PROP_NAME
, inst
);
6256 /* Detach a datepicker from its control.
6257 @param target element - the target input field or division or span */
6258 _destroyDatepicker: function(target
) {
6259 var $target
= $(target
);
6260 var inst
= $.data(target
, PROP_NAME
);
6261 if (!$target
.hasClass(this.markerClassName
)) {
6264 var nodeName
= target
.nodeName
.toLowerCase();
6265 $.removeData(target
, PROP_NAME
);
6266 if (nodeName
== 'input') {
6267 inst
.trigger
.remove();
6268 $target
.siblings('.' + this._appendClass
).remove().end().
6269 removeClass(this.markerClassName
).
6270 unbind('focus', this._showDatepicker
).
6271 unbind('keydown', this._doKeyDown
).
6272 unbind('keypress', this._doKeyPress
);
6273 } else if (nodeName
== 'div' || nodeName
== 'span')
6274 $target
.removeClass(this.markerClassName
).empty();
6277 /* Enable the date picker to a jQuery selection.
6278 @param target element - the target input field or division or span */
6279 _enableDatepicker: function(target
) {
6280 var $target
= $(target
);
6281 var inst
= $.data(target
, PROP_NAME
);
6282 if (!$target
.hasClass(this.markerClassName
)) {
6285 var nodeName
= target
.nodeName
.toLowerCase();
6286 if (nodeName
== 'input') {
6287 target
.disabled
= false;
6288 inst
.trigger
.filter("button").
6289 each(function() { this.disabled
= false; }).end().
6291 css({opacity
: '1.0', cursor
: ''});
6293 else if (nodeName
== 'div' || nodeName
== 'span') {
6294 var inline
= $target
.children('.' + this._inlineClass
);
6295 inline
.children().removeClass('ui-state-disabled');
6297 this._disabledInputs
= $.map(this._disabledInputs
,
6298 function(value
) { return (value
== target
? null : value
); }); // delete entry
6301 /* Disable the date picker to a jQuery selection.
6302 @param target element - the target input field or division or span */
6303 _disableDatepicker: function(target
) {
6304 var $target
= $(target
);
6305 var inst
= $.data(target
, PROP_NAME
);
6306 if (!$target
.hasClass(this.markerClassName
)) {
6309 var nodeName
= target
.nodeName
.toLowerCase();
6310 if (nodeName
== 'input') {
6311 target
.disabled
= true;
6312 inst
.trigger
.filter("button").
6313 each(function() { this.disabled
= true; }).end().
6315 css({opacity
: '0.5', cursor
: 'default'});
6317 else if (nodeName
== 'div' || nodeName
== 'span') {
6318 var inline
= $target
.children('.' + this._inlineClass
);
6319 inline
.children().addClass('ui-state-disabled');
6321 this._disabledInputs
= $.map(this._disabledInputs
,
6322 function(value
) { return (value
== target
? null : value
); }); // delete entry
6323 this._disabledInputs
[this._disabledInputs
.length
] = target
;
6326 /* Is the first field in a jQuery collection disabled as a datepicker?
6327 @param target element - the target input field or division or span
6328 @return boolean - true if disabled, false if enabled */
6329 _isDisabledDatepicker: function(target
) {
6333 for (var i
= 0; i
< this._disabledInputs
.length
; i
++) {
6334 if (this._disabledInputs
[i
] == target
)
6340 /* Retrieve the instance data for the target control.
6341 @param target element - the target input field or division or span
6342 @return object - the associated instance data
6343 @throws error if a jQuery problem getting data */
6344 _getInst: function(target
) {
6346 return $.data(target
, PROP_NAME
);
6349 throw 'Missing instance data for this datepicker';
6353 /* Update the settings for a date picker attached to an input field or division.
6354 @param target element - the target input field or division or span
6355 @param name object - the new settings to update or
6356 string - the name of the setting to change or
6357 @param value any - the new value for the setting (omit if above is an object) */
6358 _optionDatepicker: function(target
, name
, value
) {
6359 var settings
= name
|| {};
6360 if (typeof name
== 'string') {
6362 settings
[name
] = value
;
6364 var inst
= this._getInst(target
);
6366 if (this._curInst
== inst
) {
6367 this._hideDatepicker(null);
6369 extendRemove(inst
.settings
, settings
);
6370 var date
= new Date();
6371 extendRemove(inst
, {rangeStart
: null, // start of range
6372 endDay
: null, endMonth
: null, endYear
: null, // end of range
6373 selectedDay
: date
.getDate(), selectedMonth
: date
.getMonth(),
6374 selectedYear
: date
.getFullYear(), // starting point
6375 currentDay
: date
.getDate(), currentMonth
: date
.getMonth(),
6376 currentYear
: date
.getFullYear(), // current selection
6377 drawMonth
: date
.getMonth(), drawYear
: date
.getFullYear()}); // month being drawn
6378 this._updateDatepicker(inst
);
6382 // change method deprecated
6383 _changeDatepicker: function(target
, name
, value
) {
6384 this._optionDatepicker(target
, name
, value
);
6387 /* Redraw the date picker attached to an input field or division.
6388 @param target element - the target input field or division or span */
6389 _refreshDatepicker: function(target
) {
6390 var inst
= this._getInst(target
);
6392 this._updateDatepicker(inst
);
6396 /* Set the dates for a jQuery selection.
6397 @param target element - the target input field or division or span
6398 @param date Date - the new date
6399 @param endDate Date - the new end date for a range (optional) */
6400 _setDateDatepicker: function(target
, date
, endDate
) {
6401 var inst
= this._getInst(target
);
6403 this._setDate(inst
, date
, endDate
);
6404 this._updateDatepicker(inst
);
6405 this._updateAlternate(inst
);
6409 /* Get the date(s) for the first entry in a jQuery selection.
6410 @param target element - the target input field or division or span
6411 @return Date - the current date or
6412 Date[2] - the current dates for a range */
6413 _getDateDatepicker: function(target
) {
6414 var inst
= this._getInst(target
);
6415 if (inst
&& !inst
.inline
)
6416 this._setDateFromField(inst
);
6417 return (inst
? this._getDate(inst
) : null);
6420 /* Handle keystrokes. */
6421 _doKeyDown: function(event
) {
6422 var inst
= $.datepicker
._getInst(event
.target
);
6424 var isRTL
= inst
.dpDiv
.is('.ui-datepicker-rtl');
6425 inst
._keyEvent
= true;
6426 if ($.datepicker
._datepickerShowing
)
6427 switch (event
.keyCode
) {
6428 case 9: $.datepicker
._hideDatepicker(null, '');
6429 break; // hide on tab out
6430 case 13: var sel
= $('td.' + $.datepicker
._dayOverClass
+
6431 ', td.' + $.datepicker
._currentClass
, inst
.dpDiv
);
6433 $.datepicker
._selectDay(event
.target
, inst
.selectedMonth
, inst
.selectedYear
, sel
[0]);
6435 $.datepicker
._hideDatepicker(null, $.datepicker
._get(inst
, 'duration'));
6436 return false; // don't submit the form
6437 break; // select the value on enter
6438 case 27: $.datepicker
._hideDatepicker(null, $.datepicker
._get(inst
, 'duration'));
6439 break; // hide on escape
6440 case 33: $.datepicker
._adjustDate(event
.target
, (event
.ctrlKey
?
6441 -$.datepicker
._get(inst
, 'stepBigMonths') :
6442 -$.datepicker
._get(inst
, 'stepMonths')), 'M');
6443 break; // previous month/year on page up/+ ctrl
6444 case 34: $.datepicker
._adjustDate(event
.target
, (event
.ctrlKey
?
6445 +$.datepicker
._get(inst
, 'stepBigMonths') :
6446 +$.datepicker
._get(inst
, 'stepMonths')), 'M');
6447 break; // next month/year on page down/+ ctrl
6448 case 35: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._clearDate(event
.target
);
6449 handled
= event
.ctrlKey
|| event
.metaKey
;
6450 break; // clear on ctrl or command +end
6451 case 36: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._gotoToday(event
.target
);
6452 handled
= event
.ctrlKey
|| event
.metaKey
;
6453 break; // current on ctrl or command +home
6454 case 37: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._adjustDate(event
.target
, (isRTL
? +1 : -1), 'D');
6455 handled
= event
.ctrlKey
|| event
.metaKey
;
6456 // -1 day on ctrl or command +left
6457 if (event
.originalEvent
.altKey
) $.datepicker
._adjustDate(event
.target
, (event
.ctrlKey
?
6458 -$.datepicker
._get(inst
, 'stepBigMonths') :
6459 -$.datepicker
._get(inst
, 'stepMonths')), 'M');
6460 // next month/year on alt +left on Mac
6462 case 38: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._adjustDate(event
.target
, -7, 'D');
6463 handled
= event
.ctrlKey
|| event
.metaKey
;
6464 break; // -1 week on ctrl or command +up
6465 case 39: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._adjustDate(event
.target
, (isRTL
? -1 : +1), 'D');
6466 handled
= event
.ctrlKey
|| event
.metaKey
;
6467 // +1 day on ctrl or command +right
6468 if (event
.originalEvent
.altKey
) $.datepicker
._adjustDate(event
.target
, (event
.ctrlKey
?
6469 +$.datepicker
._get(inst
, 'stepBigMonths') :
6470 +$.datepicker
._get(inst
, 'stepMonths')), 'M');
6471 // next month/year on alt +right
6473 case 40: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._adjustDate(event
.target
, +7, 'D');
6474 handled
= event
.ctrlKey
|| event
.metaKey
;
6475 break; // +1 week on ctrl or command +down
6476 default: handled
= false;
6478 else if (event
.keyCode
== 36 && event
.ctrlKey
) // display the date picker on ctrl+home
6479 $.datepicker
._showDatepicker(this);
6484 event
.preventDefault();
6485 event
.stopPropagation();
6489 /* Filter entered characters - based on date format. */
6490 _doKeyPress: function(event
) {
6491 var inst
= $.datepicker
._getInst(event
.target
);
6492 if ($.datepicker
._get(inst
, 'constrainInput')) {
6493 var chars
= $.datepicker
._possibleChars($.datepicker
._get(inst
, 'dateFormat'));
6494 var chr
= String
.fromCharCode(event
.charCode
== undefined ? event
.keyCode
: event
.charCode
);
6495 return event
.ctrlKey
|| (chr
< ' ' || !chars
|| chars
.indexOf(chr
) > -1);
6499 /* Pop-up the date picker for a given input field.
6500 @param input element - the input field attached to the date picker or
6501 event - if triggered by focus */
6502 _showDatepicker: function(input
) {
6503 input
= input
.target
|| input
;
6504 if (input
.nodeName
.toLowerCase() != 'input') // find from button/image trigger
6505 input
= $('input', input
.parentNode
)[0];
6506 if ($.datepicker
._isDisabledDatepicker(input
) || $.datepicker
._lastInput
== input
) // already here
6508 var inst
= $.datepicker
._getInst(input
);
6509 var beforeShow
= $.datepicker
._get(inst
, 'beforeShow');
6510 extendRemove(inst
.settings
, (beforeShow
? beforeShow
.apply(input
, [input
, inst
]) : {}));
6511 $.datepicker
._hideDatepicker(null, '');
6512 $.datepicker
._lastInput
= input
;
6513 $.datepicker
._setDateFromField(inst
);
6514 if ($.datepicker
._inDialog
) // hide cursor
6516 if (!$.datepicker
._pos
) { // position below input
6517 $.datepicker
._pos
= $.datepicker
._findPos(input
);
6518 $.datepicker
._pos
[1] += input
.offsetHeight
; // add the height
6520 var isFixed
= false;
6521 $(input
).parents().each(function() {
6522 isFixed
|= $(this).css('position') == 'fixed';
6525 if (isFixed
&& $.browser
.opera
) { // correction for Opera when fixed and scrolled
6526 $.datepicker
._pos
[0] -= document
.documentElement
.scrollLeft
;
6527 $.datepicker
._pos
[1] -= document
.documentElement
.scrollTop
;
6529 var offset
= {left
: $.datepicker
._pos
[0], top
: $.datepicker
._pos
[1]};
6530 $.datepicker
._pos
= null;
6531 inst
.rangeStart
= null;
6532 // determine sizing offscreen
6533 inst
.dpDiv
.css({position
: 'absolute', display
: 'block', top
: '-1000px'});
6534 $.datepicker
._updateDatepicker(inst
);
6535 // fix width for dynamic number of date pickers
6536 // and adjust position before showing
6537 offset
= $.datepicker
._checkOffset(inst
, offset
, isFixed
);
6538 inst
.dpDiv
.css({position
: ($.datepicker
._inDialog
&& $.blockUI
?
6539 'static' : (isFixed
? 'fixed' : 'absolute')), display
: 'none',
6540 left
: offset
.left
+ 'px', top
: offset
.top
+ 'px'});
6542 var showAnim
= $.datepicker
._get(inst
, 'showAnim') || 'show';
6543 var duration
= $.datepicker
._get(inst
, 'duration');
6544 var postProcess = function() {
6545 $.datepicker
._datepickerShowing
= true;
6546 if ($.browser
.msie
&& parseInt($.browser
.version
,10) < 7) // fix IE < 7 select problems
6547 $('iframe.ui-datepicker-cover').css({width
: inst
.dpDiv
.width() + 4,
6548 height
: inst
.dpDiv
.height() + 4});
6550 if ($.effects
&& $.effects
[showAnim
])
6551 inst
.dpDiv
.show(showAnim
, $.datepicker
._get(inst
, 'showOptions'), duration
, postProcess
);
6553 inst
.dpDiv
[showAnim
](duration
, postProcess
);
6556 if (inst
.input
[0].type
!= 'hidden')
6557 inst
.input
[0].focus();
6558 $.datepicker
._curInst
= inst
;
6562 /* Generate the date picker content. */
6563 _updateDatepicker: function(inst
) {
6564 var dims
= {width
: inst
.dpDiv
.width() + 4,
6565 height
: inst
.dpDiv
.height() + 4};
6567 inst
.dpDiv
.empty().append(this._generateHTML(inst
))
6568 .find('iframe.ui-datepicker-cover').
6569 css({width
: dims
.width
, height
: dims
.height
})
6571 .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
6572 .bind('mouseout', function(){
6573 $(this).removeClass('ui-state-hover');
6574 if(this.className
.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
6575 if(this.className
.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
6577 .bind('mouseover', function(){
6578 if (!self
._isDisabledDatepicker( inst
.inline
? inst
.dpDiv
.parent()[0] : inst
.input
[0])) {
6579 $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
6580 $(this).addClass('ui-state-hover');
6581 if(this.className
.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
6582 if(this.className
.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
6586 .find('.' + this._dayOverClass
+ ' a')
6587 .trigger('mouseover')
6589 var numMonths
= this._getNumberOfMonths(inst
);
6590 var cols
= numMonths
[1];
6593 inst
.dpDiv
.addClass('ui-datepicker-multi-' + cols
).css('width', (width
* cols
) + 'em');
6595 inst
.dpDiv
.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
6597 inst
.dpDiv
[(numMonths
[0] != 1 || numMonths
[1] != 1 ? 'add' : 'remove') +
6598 'Class']('ui-datepicker-multi');
6599 inst
.dpDiv
[(this._get(inst
, 'isRTL') ? 'add' : 'remove') +
6600 'Class']('ui-datepicker-rtl');
6601 if (inst
.input
&& inst
.input
[0].type
!= 'hidden' && inst
== $.datepicker
._curInst
)
6602 $(inst
.input
[0]).focus();
6605 /* Check positioning to remain on screen. */
6606 _checkOffset: function(inst
, offset
, isFixed
) {
6607 var dpWidth
= inst
.dpDiv
.outerWidth();
6608 var dpHeight
= inst
.dpDiv
.outerHeight();
6609 var inputWidth
= inst
.input
? inst
.input
.outerWidth() : 0;
6610 var inputHeight
= inst
.input
? inst
.input
.outerHeight() : 0;
6611 var viewWidth
= (window
.innerWidth
|| document
.documentElement
.clientWidth
|| document
.body
.clientWidth
) + $(document
).scrollLeft();
6612 var viewHeight
= (window
.innerHeight
|| document
.documentElement
.clientHeight
|| document
.body
.clientHeight
) + $(document
).scrollTop();
6614 offset
.left
-= (this._get(inst
, 'isRTL') ? (dpWidth
- inputWidth
) : 0);
6615 offset
.left
-= (isFixed
&& offset
.left
== inst
.input
.offset().left
) ? $(document
).scrollLeft() : 0;
6616 offset
.top
-= (isFixed
&& offset
.top
== (inst
.input
.offset().top
+ inputHeight
)) ? $(document
).scrollTop() : 0;
6618 // now check if datepicker is showing outside window viewport - move to a better place if so.
6619 offset
.left
-= (offset
.left
+ dpWidth
> viewWidth
&& viewWidth
> dpWidth
) ? Math
.abs(offset
.left
+ dpWidth
- viewWidth
) : 0;
6620 offset
.top
-= (offset
.top
+ dpHeight
> viewHeight
&& viewHeight
> dpHeight
) ? Math
.abs(offset
.top
+ dpHeight
+ inputHeight
*2 - viewHeight
) : 0;
6625 /* Find an object's position on the screen. */
6626 _findPos: function(obj
) {
6627 while (obj
&& (obj
.type
== 'hidden' || obj
.nodeType
!= 1)) {
6628 obj
= obj
.nextSibling
;
6630 var position
= $(obj
).offset();
6631 return [position
.left
, position
.top
];
6634 /* Hide the date picker from view.
6635 @param input element - the input field attached to the date picker
6636 @param duration string - the duration over which to close the date picker */
6637 _hideDatepicker: function(input
, duration
) {
6638 var inst
= this._curInst
;
6639 if (!inst
|| (input
&& inst
!= $.data(input
, PROP_NAME
)))
6642 this._selectDate('#' + inst
.id
, this._formatDate(inst
,
6643 inst
.currentDay
, inst
.currentMonth
, inst
.currentYear
));
6644 inst
.stayOpen
= false;
6645 if (this._datepickerShowing
) {
6646 duration
= (duration
!= null ? duration
: this._get(inst
, 'duration'));
6647 var showAnim
= this._get(inst
, 'showAnim');
6648 var postProcess = function() {
6649 $.datepicker
._tidyDialog(inst
);
6651 if (duration
!= '' && $.effects
&& $.effects
[showAnim
])
6652 inst
.dpDiv
.hide(showAnim
, $.datepicker
._get(inst
, 'showOptions'),
6653 duration
, postProcess
);
6655 inst
.dpDiv
[(duration
== '' ? 'hide' : (showAnim
== 'slideDown' ? 'slideUp' :
6656 (showAnim
== 'fadeIn' ? 'fadeOut' : 'hide')))](duration
, postProcess
);
6658 this._tidyDialog(inst
);
6659 var onClose
= this._get(inst
, 'onClose');
6661 onClose
.apply((inst
.input
? inst
.input
[0] : null),
6662 [(inst
.input
? inst
.input
.val() : ''), inst
]); // trigger custom callback
6663 this._datepickerShowing
= false;
6664 this._lastInput
= null;
6665 if (this._inDialog
) {
6666 this._dialogInput
.css({ position
: 'absolute', left
: '0', top
: '-100px' });
6669 $('body').append(this.dpDiv
);
6672 this._inDialog
= false;
6674 this._curInst
= null;
6677 /* Tidy up after a dialog display. */
6678 _tidyDialog: function(inst
) {
6679 inst
.dpDiv
.removeClass(this._dialogClass
).unbind('.ui-datepicker-calendar');
6682 /* Close date picker if clicked elsewhere. */
6683 _checkExternalClick: function(event
) {
6684 if (!$.datepicker
._curInst
)
6686 var $target
= $(event
.target
);
6687 if (($target
.parents('#' + $.datepicker
._mainDivId
).length
== 0) &&
6688 !$target
.hasClass($.datepicker
.markerClassName
) &&
6689 !$target
.hasClass($.datepicker
._triggerClass
) &&
6690 $.datepicker
._datepickerShowing
&& !($.datepicker
._inDialog
&& $.blockUI
))
6691 $.datepicker
._hideDatepicker(null, '');
6694 /* Adjust one of the date sub-fields. */
6695 _adjustDate: function(id
, offset
, period
) {
6697 var inst
= this._getInst(target
[0]);
6698 if (this._isDisabledDatepicker(target
[0])) {
6701 this._adjustInstDate(inst
, offset
+
6702 (period
== 'M' ? this._get(inst
, 'showCurrentAtPos') : 0), // undo positioning
6704 this._updateDatepicker(inst
);
6707 /* Action for current link. */
6708 _gotoToday: function(id
) {
6710 var inst
= this._getInst(target
[0]);
6711 if (this._get(inst
, 'gotoCurrent') && inst
.currentDay
) {
6712 inst
.selectedDay
= inst
.currentDay
;
6713 inst
.drawMonth
= inst
.selectedMonth
= inst
.currentMonth
;
6714 inst
.drawYear
= inst
.selectedYear
= inst
.currentYear
;
6717 var date
= new Date();
6718 inst
.selectedDay
= date
.getDate();
6719 inst
.drawMonth
= inst
.selectedMonth
= date
.getMonth();
6720 inst
.drawYear
= inst
.selectedYear
= date
.getFullYear();
6722 this._notifyChange(inst
);
6723 this._adjustDate(target
);
6726 /* Action for selecting a new month/year. */
6727 _selectMonthYear: function(id, select, period) {
6729 var inst = this._getInst(target[0]);
6730 inst._selectingMonthYear = false;
6731 inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
6732 inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
6733 parseInt(select.options[select.selectedIndex].value,10);
6734 this._notifyChange(inst);
6735 this._adjustDate(target);
6738 /* Restore input focus after not changing month/year. */
6739 _clickMonthYear: function(id) {
6741 var inst = this._getInst(target[0]);
6742 if (inst.input && inst._selectingMonthYear && !$.browser.msie)
6743 inst.input[0].focus();
6744 inst._selectingMonthYear = !inst._selectingMonthYear;
6747 /* Action for selecting a day. */
6748 _selectDay: function(id
, month
, year
, td
) {
6750 if ($(td
).hasClass(this._unselectableClass
) || this._isDisabledDatepicker(target
[0])) {
6753 var inst
= this._getInst(target
[0]);
6754 inst
.selectedDay
= inst
.currentDay
= $('a', td
).html();
6755 inst
.selectedMonth
= inst
.currentMonth
= month
;
6756 inst
.selectedYear
= inst
.currentYear
= year
;
6757 if (inst
.stayOpen
) {
6758 inst
.endDay
= inst
.endMonth
= inst
.endYear
= null;
6760 this._selectDate(id
, this._formatDate(inst
,
6761 inst
.currentDay
, inst
.currentMonth
, inst
.currentYear
));
6762 if (inst
.stayOpen
) {
6763 inst
.rangeStart
= this._daylightSavingAdjust(
6764 new Date(inst
.currentYear
, inst
.currentMonth
, inst
.currentDay
));
6765 this._updateDatepicker(inst
);
6769 /* Erase the input field and hide the date picker. */
6770 _clearDate: function(id
) {
6772 var inst
= this._getInst(target
[0]);
6773 inst
.stayOpen
= false;
6774 inst
.endDay
= inst
.endMonth
= inst
.endYear
= inst
.rangeStart
= null;
6775 this._selectDate(target
, '');
6778 /* Update the input field with the selected date. */
6779 _selectDate: function(id
, dateStr
) {
6781 var inst
= this._getInst(target
[0]);
6782 dateStr
= (dateStr
!= null ? dateStr
: this._formatDate(inst
));
6784 inst
.input
.val(dateStr
);
6785 this._updateAlternate(inst
);
6786 var onSelect
= this._get(inst
, 'onSelect');
6788 onSelect
.apply((inst
.input
? inst
.input
[0] : null), [dateStr
, inst
]); // trigger custom callback
6789 else if (inst
.input
)
6790 inst
.input
.trigger('change'); // fire the change event
6792 this._updateDatepicker(inst
);
6793 else if (!inst
.stayOpen
) {
6794 this._hideDatepicker(null, this._get(inst
, 'duration'));
6795 this._lastInput
= inst
.input
[0];
6796 if (typeof(inst
.input
[0]) != 'object')
6797 inst
.input
[0].focus(); // restore focus
6798 this._lastInput
= null;
6802 /* Update any alternate field to synchronise with the main field. */
6803 _updateAlternate: function(inst
) {
6804 var altField
= this._get(inst
, 'altField');
6805 if (altField
) { // update alternate field too
6806 var altFormat
= this._get(inst
, 'altFormat') || this._get(inst
, 'dateFormat');
6807 var date
= this._getDate(inst
);
6808 dateStr
= this.formatDate(altFormat
, date
, this._getFormatConfig(inst
));
6809 $(altField
).each(function() { $(this).val(dateStr
); });
6813 /* Set as beforeShowDay function to prevent selection of weekends.
6814 @param date Date - the date to customise
6815 @return [boolean, string] - is this date selectable?, what is its CSS class? */
6816 noWeekends: function(date
) {
6817 var day
= date
.getDay();
6818 return [(day
> 0 && day
< 6), ''];
6821 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
6822 @param date Date - the date to get the week for
6823 @return number - the number of the week within the year that contains this date */
6824 iso8601Week: function(date
) {
6825 var checkDate
= new Date(date
.getFullYear(), date
.getMonth(), date
.getDate());
6826 var firstMon
= new Date(checkDate
.getFullYear(), 1 - 1, 4); // First week always contains 4 Jan
6827 var firstDay
= firstMon
.getDay() || 7; // Day of week: Mon = 1, ..., Sun = 7
6828 firstMon
.setDate(firstMon
.getDate() + 1 - firstDay
); // Preceding Monday
6829 if (firstDay
< 4 && checkDate
< firstMon
) { // Adjust first three days in year if necessary
6830 checkDate
.setDate(checkDate
.getDate() - 3); // Generate for previous year
6831 return $.datepicker
.iso8601Week(checkDate
);
6832 } else if (checkDate
> new Date(checkDate
.getFullYear(), 12 - 1, 28)) { // Check last three days in year
6833 firstDay
= new Date(checkDate
.getFullYear() + 1, 1 - 1, 4).getDay() || 7;
6834 if (firstDay
> 4 && (checkDate
.getDay() || 7) < firstDay
- 3) { // Adjust if necessary
6838 return Math
.floor(((checkDate
- firstMon
) / 86400000) / 7) + 1; // Weeks to given date
6841 /* Parse a string value into a date object.
6842 See formatDate below for the possible formats.
6844 @param format string - the expected format of the date
6845 @param value string - the date in the above format
6846 @param settings Object - attributes include:
6847 shortYearCutoff number - the cutoff year for determining the century (optional)
6848 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
6849 dayNames string[7] - names of the days from Sunday (optional)
6850 monthNamesShort string[12] - abbreviated names of the months (optional)
6851 monthNames string[12] - names of the months (optional)
6852 @return Date - the extracted date value or null if value is blank */
6853 parseDate: function (format
, value
, settings
) {
6854 if (format
== null || value
== null)
6855 throw 'Invalid arguments';
6856 value
= (typeof value
== 'object' ? value
.toString() : value
+ '');
6859 var shortYearCutoff
= (settings
? settings
.shortYearCutoff
: null) || this._defaults
.shortYearCutoff
;
6860 var dayNamesShort
= (settings
? settings
.dayNamesShort
: null) || this._defaults
.dayNamesShort
;
6861 var dayNames
= (settings
? settings
.dayNames
: null) || this._defaults
.dayNames
;
6862 var monthNamesShort
= (settings
? settings
.monthNamesShort
: null) || this._defaults
.monthNamesShort
;
6863 var monthNames
= (settings
? settings
.monthNames
: null) || this._defaults
.monthNames
;
6868 var literal
= false;
6869 // Check whether a format character is doubled
6870 var lookAhead = function(match
) {
6871 var matches
= (iFormat
+ 1 < format
.length
&& format
.charAt(iFormat
+ 1) == match
);
6876 // Extract a number from the string value
6877 var getNumber = function(match
) {
6879 var origSize
= (match
== '@' ? 14 : (match
== 'y' ? 4 : (match
== 'o' ? 3 : 2)));
6880 var size
= origSize
;
6882 while (size
> 0 && iValue
< value
.length
&&
6883 value
.charAt(iValue
) >= '0' && value
.charAt(iValue
) <= '9') {
6884 num
= num
* 10 + parseInt(value
.charAt(iValue
++),10);
6887 if (size
== origSize
)
6888 throw 'Missing number at position ' + iValue
;
6891 // Extract a name from the string value and convert to an index
6892 var getName = function(match
, shortNames
, longNames
) {
6893 var names
= (lookAhead(match
) ? longNames
: shortNames
);
6895 for (var j
= 0; j
< names
.length
; j
++)
6896 size
= Math
.max(size
, names
[j
].length
);
6899 while (size
> 0 && iValue
< value
.length
) {
6900 name
+= value
.charAt(iValue
++);
6901 for (var i
= 0; i
< names
.length
; i
++)
6902 if (name
== names
[i
])
6906 throw 'Unknown name at position ' + iInit
;
6908 // Confirm that a literal character matches the string value
6909 var checkLiteral = function() {
6910 if (value
.charAt(iValue
) != format
.charAt(iFormat
))
6911 throw 'Unexpected literal at position ' + iValue
;
6915 for (var iFormat
= 0; iFormat
< format
.length
; iFormat
++) {
6917 if (format
.charAt(iFormat
) == "'" && !lookAhead("'"))
6922 switch (format
.charAt(iFormat
)) {
6924 day
= getNumber('d');
6927 getName('D', dayNamesShort
, dayNames
);
6930 doy
= getNumber('o');
6933 month
= getNumber('m');
6936 month
= getName('M', monthNamesShort
, monthNames
);
6939 year
= getNumber('y');
6942 var date
= new Date(getNumber('@'));
6943 year
= date
.getFullYear();
6944 month
= date
.getMonth() + 1;
6945 day
= date
.getDate();
6958 year
= new Date().getFullYear();
6959 else if (year
< 100)
6960 year
+= new Date().getFullYear() - new Date().getFullYear() % 100 +
6961 (year
<= shortYearCutoff
? 0 : -100);
6966 var dim
= this._getDaysInMonth(year
, month
- 1);
6973 var date
= this._daylightSavingAdjust(new Date(year
, month
- 1, day
));
6974 if (date
.getFullYear() != year
|| date
.getMonth() + 1 != month
|| date
.getDate() != day
)
6975 throw 'Invalid date'; // E.g. 31/02/*
6979 /* Standard date formats. */
6980 ATOM
: 'yy-mm-dd', // RFC 3339 (ISO 8601)
6981 COOKIE
: 'D, dd M yy',
6982 ISO_8601
: 'yy-mm-dd',
6983 RFC_822
: 'D, d M y',
6984 RFC_850
: 'DD, dd-M-y',
6985 RFC_1036
: 'D, d M y',
6986 RFC_1123
: 'D, d M yy',
6987 RFC_2822
: 'D, d M yy',
6988 RSS
: 'D, d M y', // RFC 822
6990 W3C
: 'yy-mm-dd', // ISO 8601
6992 /* Format a date object into a string value.
6993 The format can be combinations of the following:
6994 d - day of month (no leading zero)
6995 dd - day of month (two digit)
6996 o - day of year (no leading zeros)
6997 oo - day of year (three digit)
7000 m - month of year (no leading zero)
7001 mm - month of year (two digit)
7002 M - month name short
7003 MM - month name long
7004 y - year (two digit)
7005 yy - year (four digit)
7006 @ - Unix timestamp (ms since 01/01/1970)
7007 '...' - literal text
7010 @param format string - the desired format of the date
7011 @param date Date - the date value to format
7012 @param settings Object - attributes include:
7013 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
7014 dayNames string[7] - names of the days from Sunday (optional)
7015 monthNamesShort string[12] - abbreviated names of the months (optional)
7016 monthNames string[12] - names of the months (optional)
7017 @return string - the date in the above format */
7018 formatDate: function (format
, date
, settings
) {
7021 var dayNamesShort
= (settings
? settings
.dayNamesShort
: null) || this._defaults
.dayNamesShort
;
7022 var dayNames
= (settings
? settings
.dayNames
: null) || this._defaults
.dayNames
;
7023 var monthNamesShort
= (settings
? settings
.monthNamesShort
: null) || this._defaults
.monthNamesShort
;
7024 var monthNames
= (settings
? settings
.monthNames
: null) || this._defaults
.monthNames
;
7025 // Check whether a format character is doubled
7026 var lookAhead = function(match
) {
7027 var matches
= (iFormat
+ 1 < format
.length
&& format
.charAt(iFormat
+ 1) == match
);
7032 // Format a number, with leading zero if necessary
7033 var formatNumber = function(match
, value
, len
) {
7034 var num
= '' + value
;
7035 if (lookAhead(match
))
7036 while (num
.length
< len
)
7040 // Format a name, short or long as requested
7041 var formatName = function(match
, value
, shortNames
, longNames
) {
7042 return (lookAhead(match
) ? longNames
[value
] : shortNames
[value
]);
7045 var literal
= false;
7047 for (var iFormat
= 0; iFormat
< format
.length
; iFormat
++) {
7049 if (format
.charAt(iFormat
) == "'" && !lookAhead("'"))
7052 output
+= format
.charAt(iFormat
);
7054 switch (format
.charAt(iFormat
)) {
7056 output
+= formatNumber('d', date
.getDate(), 2);
7059 output
+= formatName('D', date
.getDay(), dayNamesShort
, dayNames
);
7062 var doy
= date
.getDate();
7063 for (var m
= date
.getMonth() - 1; m
>= 0; m
--)
7064 doy
+= this._getDaysInMonth(date
.getFullYear(), m
);
7065 output
+= formatNumber('o', doy
, 3);
7068 output
+= formatNumber('m', date
.getMonth() + 1, 2);
7071 output
+= formatName('M', date
.getMonth(), monthNamesShort
, monthNames
);
7074 output
+= (lookAhead('y') ? date
.getFullYear() :
7075 (date
.getYear() % 100 < 10 ? '0' : '') + date
.getYear() % 100);
7078 output
+= date
.getTime();
7087 output
+= format
.charAt(iFormat
);
7093 /* Extract all possible characters from the date format. */
7094 _possibleChars: function (format
) {
7096 var literal
= false;
7097 for (var iFormat
= 0; iFormat
< format
.length
; iFormat
++)
7099 if (format
.charAt(iFormat
) == "'" && !lookAhead("'"))
7102 chars
+= format
.charAt(iFormat
);
7104 switch (format
.charAt(iFormat
)) {
7105 case 'd': case 'm': case 'y': case '@':
7106 chars
+= '0123456789';
7109 return null; // Accept anything
7117 chars
+= format
.charAt(iFormat
);
7122 /* Get a setting value, defaulting if necessary. */
7123 _get: function(inst
, name
) {
7124 return inst
.settings
[name
] !== undefined ?
7125 inst
.settings
[name
] : this._defaults
[name
];
7128 /* Parse existing date and initialise date picker. */
7129 _setDateFromField: function(inst
) {
7130 var dateFormat
= this._get(inst
, 'dateFormat');
7131 var dates
= inst
.input
? inst
.input
.val() : null;
7132 inst
.endDay
= inst
.endMonth
= inst
.endYear
= null;
7133 var date
= defaultDate
= this._getDefaultDate(inst
);
7134 var settings
= this._getFormatConfig(inst
);
7136 date
= this.parseDate(dateFormat
, dates
, settings
) || defaultDate
;
7141 inst
.selectedDay
= date
.getDate();
7142 inst
.drawMonth
= inst
.selectedMonth
= date
.getMonth();
7143 inst
.drawYear
= inst
.selectedYear
= date
.getFullYear();
7144 inst
.currentDay
= (dates
? date
.getDate() : 0);
7145 inst
.currentMonth
= (dates
? date
.getMonth() : 0);
7146 inst
.currentYear
= (dates
? date
.getFullYear() : 0);
7147 this._adjustInstDate(inst
);
7150 /* Retrieve the default date shown on opening. */
7151 _getDefaultDate: function(inst
) {
7152 var date
= this._determineDate(this._get(inst
, 'defaultDate'), new Date());
7153 var minDate
= this._getMinMaxDate(inst
, 'min', true);
7154 var maxDate
= this._getMinMaxDate(inst
, 'max');
7155 date
= (minDate
&& date
< minDate
? minDate
: date
);
7156 date
= (maxDate
&& date
> maxDate
? maxDate
: date
);
7160 /* A date may be specified as an exact value or a relative one. */
7161 _determineDate: function(date
, defaultDate
) {
7162 var offsetNumeric = function(offset
) {
7163 var date
= new Date();
7164 date
.setDate(date
.getDate() + offset
);
7167 var offsetString = function(offset
, getDaysInMonth
) {
7168 var date
= new Date();
7169 var year
= date
.getFullYear();
7170 var month
= date
.getMonth();
7171 var day
= date
.getDate();
7172 var pattern
= /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
7173 var matches
= pattern
.exec(offset
);
7175 switch (matches
[2] || 'd') {
7176 case 'd' : case 'D' :
7177 day
+= parseInt(matches
[1],10); break;
7178 case 'w' : case 'W' :
7179 day
+= parseInt(matches
[1],10) * 7; break;
7180 case 'm' : case 'M' :
7181 month
+= parseInt(matches
[1],10);
7182 day
= Math
.min(day
, getDaysInMonth(year
, month
));
7184 case 'y': case 'Y' :
7185 year
+= parseInt(matches
[1],10);
7186 day
= Math
.min(day
, getDaysInMonth(year
, month
));
7189 matches
= pattern
.exec(offset
);
7191 return new Date(year
, month
, day
);
7193 date
= (date
== null ? defaultDate
:
7194 (typeof date
== 'string' ? offsetString(date
, this._getDaysInMonth
) :
7195 (typeof date
== 'number' ? (isNaN(date
) ? defaultDate
: offsetNumeric(date
)) : date
)));
7196 date
= (date
&& date
.toString() == 'Invalid Date' ? defaultDate
: date
);
7201 date
.setMilliseconds(0);
7203 return this._daylightSavingAdjust(date
);
7206 /* Handle switch to/from daylight saving.
7207 Hours may be non-zero on daylight saving cut-over:
7208 > 12 when midnight changeover, but then cannot generate
7209 midnight datetime, so jump to 1AM, otherwise reset.
7210 @param date (Date) the date to check
7211 @return (Date) the corrected date */
7212 _daylightSavingAdjust: function(date
) {
7213 if (!date
) return null;
7214 date
.setHours(date
.getHours() > 12 ? date
.getHours() + 2 : 0);
7218 /* Set the date(s) directly. */
7219 _setDate: function(inst
, date
, endDate
) {
7220 var clear
= !(date
);
7221 var origMonth
= inst
.selectedMonth
;
7222 var origYear
= inst
.selectedYear
;
7223 date
= this._determineDate(date
, new Date());
7224 inst
.selectedDay
= inst
.currentDay
= date
.getDate();
7225 inst
.drawMonth
= inst
.selectedMonth
= inst
.currentMonth
= date
.getMonth();
7226 inst
.drawYear
= inst
.selectedYear
= inst
.currentYear
= date
.getFullYear();
7227 if (origMonth
!= inst
.selectedMonth
|| origYear
!= inst
.selectedYear
)
7228 this._notifyChange(inst
);
7229 this._adjustInstDate(inst
);
7231 inst
.input
.val(clear
? '' : this._formatDate(inst
));
7235 /* Retrieve the date(s) directly. */
7236 _getDate: function(inst
) {
7237 var startDate
= (!inst
.currentYear
|| (inst
.input
&& inst
.input
.val() == '') ? null :
7238 this._daylightSavingAdjust(new Date(
7239 inst
.currentYear
, inst
.currentMonth
, inst
.currentDay
)));
7243 /* Generate the HTML for the current state of the date picker. */
7244 _generateHTML: function(inst
) {
7245 var today
= new Date();
7246 today
= this._daylightSavingAdjust(
7247 new Date(today
.getFullYear(), today
.getMonth(), today
.getDate())); // clear time
7248 var isRTL
= this._get(inst
, 'isRTL');
7249 var showButtonPanel
= this._get(inst
, 'showButtonPanel');
7250 var hideIfNoPrevNext
= this._get(inst
, 'hideIfNoPrevNext');
7251 var navigationAsDateFormat
= this._get(inst
, 'navigationAsDateFormat');
7252 var numMonths
= this._getNumberOfMonths(inst
);
7253 var showCurrentAtPos
= this._get(inst
, 'showCurrentAtPos');
7254 var stepMonths
= this._get(inst
, 'stepMonths');
7255 var stepBigMonths
= this._get(inst
, 'stepBigMonths');
7256 var isMultiMonth
= (numMonths
[0] != 1 || numMonths
[1] != 1);
7257 var currentDate
= this._daylightSavingAdjust((!inst
.currentDay
? new Date(9999, 9, 9) :
7258 new Date(inst
.currentYear
, inst
.currentMonth
, inst
.currentDay
)));
7259 var minDate
= this._getMinMaxDate(inst
, 'min', true);
7260 var maxDate
= this._getMinMaxDate(inst
, 'max');
7261 var drawMonth
= inst
.drawMonth
- showCurrentAtPos
;
7262 var drawYear
= inst
.drawYear
;
7263 if (drawMonth
< 0) {
7268 var maxDraw
= this._daylightSavingAdjust(new Date(maxDate
.getFullYear(),
7269 maxDate
.getMonth() - numMonths
[1] + 1, maxDate
.getDate()));
7270 maxDraw
= (minDate
&& maxDraw
< minDate
? minDate
: maxDraw
);
7271 while (this._daylightSavingAdjust(new Date(drawYear
, drawMonth
, 1)) > maxDraw
) {
7273 if (drawMonth
< 0) {
7279 inst
.drawMonth
= drawMonth
;
7280 inst
.drawYear
= drawYear
;
7281 var prevText
= this._get(inst
, 'prevText');
7282 prevText
= (!navigationAsDateFormat
? prevText
: this.formatDate(prevText
,
7283 this._daylightSavingAdjust(new Date(drawYear
, drawMonth
- stepMonths
, 1)),
7284 this._getFormatConfig(inst
)));
7285 var prev
= (this._canAdjustMonth(inst
, -1, drawYear
, drawMonth
) ?
7286 '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst
.id
+ '\', -' + stepMonths
+ ', \'M\');"' +
7287 ' title="' + prevText
+ '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL
? 'e' : 'w') + '">' + prevText
+ '</span></a>' :
7288 (hideIfNoPrevNext
? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText
+'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL
? 'e' : 'w') + '">' + prevText
+ '</span></a>'));
7289 var nextText
= this._get(inst
, 'nextText');
7290 nextText
= (!navigationAsDateFormat
? nextText
: this.formatDate(nextText
,
7291 this._daylightSavingAdjust(new Date(drawYear
, drawMonth
+ stepMonths
, 1)),
7292 this._getFormatConfig(inst
)));
7293 var next
= (this._canAdjustMonth(inst
, +1, drawYear
, drawMonth
) ?
7294 '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst
.id
+ '\', +' + stepMonths
+ ', \'M\');"' +
7295 ' title="' + nextText
+ '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL
? 'w' : 'e') + '">' + nextText
+ '</span></a>' :
7296 (hideIfNoPrevNext
? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText
+ '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL
? 'w' : 'e') + '">' + nextText
+ '</span></a>'));
7297 var currentText
= this._get(inst
, 'currentText');
7298 var gotoDate
= (this._get(inst
, 'gotoCurrent') && inst
.currentDay
? currentDate
: today
);
7299 currentText
= (!navigationAsDateFormat
? currentText
:
7300 this.formatDate(currentText
, gotoDate
, this._getFormatConfig(inst
)));
7301 var controls
= (!inst
.inline
? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery.datepicker._hideDatepicker();">' + this._get(inst
, 'closeText') + '</button>' : '');
7302 var buttonPanel
= (showButtonPanel
) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL
? controls
: '') +
7303 (this._isInRange(inst
, gotoDate
) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery.datepicker._gotoToday(\'#' + inst
.id
+ '\');"' +
7304 '>' + currentText
+ '</button>' : '') + (isRTL
? '' : controls
) + '</div>' : '';
7305 var firstDay
= parseInt(this._get(inst
, 'firstDay'),10);
7306 firstDay
= (isNaN(firstDay
) ? 0 : firstDay
);
7307 var dayNames
= this._get(inst
, 'dayNames');
7308 var dayNamesShort
= this._get(inst
, 'dayNamesShort');
7309 var dayNamesMin
= this._get(inst
, 'dayNamesMin');
7310 var monthNames
= this._get(inst
, 'monthNames');
7311 var monthNamesShort
= this._get(inst
, 'monthNamesShort');
7312 var beforeShowDay
= this._get(inst
, 'beforeShowDay');
7313 var showOtherMonths
= this._get(inst
, 'showOtherMonths');
7314 var calculateWeek
= this._get(inst
, 'calculateWeek') || this.iso8601Week
;
7315 var endDate
= inst
.endDay
? this._daylightSavingAdjust(
7316 new Date(inst
.endYear
, inst
.endMonth
, inst
.endDay
)) : currentDate
;
7317 var defaultDate
= this._getDefaultDate(inst
);
7319 for (var row
= 0; row
< numMonths
[0]; row
++) {
7321 for (var col
= 0; col
< numMonths
[1]; col
++) {
7322 var selectedDate
= this._daylightSavingAdjust(new Date(drawYear
, drawMonth
, inst
.selectedDay
));
7323 var cornerClass
= ' ui-corner-all';
7326 calender
+= '<div class="ui-datepicker-group ui-datepicker-group-';
7328 case 0: calender
+= 'first'; cornerClass
= ' ui-corner-' + (isRTL
? 'right' : 'left'); break;
7329 case numMonths
[1]-1: calender
+= 'last'; cornerClass
= ' ui-corner-' + (isRTL
? 'left' : 'right'); break;
7330 default: calender
+= 'middle'; cornerClass
= ''; break;
7334 calender
+= '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass
+ '">' +
7335 (/all|left/.test(cornerClass
) && row
== 0 ? (isRTL
? next
: prev
) : '') +
7336 (/all|right/.test(cornerClass
) && row
== 0 ? (isRTL
? prev
: next
) : '') +
7337 this._generateMonthYearHeader(inst
, drawMonth
, drawYear
, minDate
, maxDate
,
7338 selectedDate
, row
> 0 || col
> 0, monthNames
, monthNamesShort
) + // draw month headers
7339 '</div><table class="ui-datepicker-calendar"><thead>' +
7342 for (var dow
= 0; dow
< 7; dow
++) { // days of the week
7343 var day
= (dow
+ firstDay
) % 7;
7344 thead
+= '<th' + ((dow
+ firstDay
+ 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
7345 '<span title="' + dayNames
[day
] + '">' + dayNamesMin
[day
] + '</span></th>';
7347 calender
+= thead
+ '</tr></thead><tbody>';
7348 var daysInMonth
= this._getDaysInMonth(drawYear
, drawMonth
);
7349 if (drawYear
== inst
.selectedYear
&& drawMonth
== inst
.selectedMonth
)
7350 inst
.selectedDay
= Math
.min(inst
.selectedDay
, daysInMonth
);
7351 var leadDays
= (this._getFirstDayOfMonth(drawYear
, drawMonth
) - firstDay
+ 7) % 7;
7352 var numRows
= (isMultiMonth
? 6 : Math
.ceil((leadDays
+ daysInMonth
) / 7)); // calculate the number of rows to generate
7353 var printDate
= this._daylightSavingAdjust(new Date(drawYear
, drawMonth
, 1 - leadDays
));
7354 for (var dRow
= 0; dRow
< numRows
; dRow
++) { // create date picker rows
7357 for (var dow
= 0; dow
< 7; dow
++) { // create date picker days
7358 var daySettings
= (beforeShowDay
?
7359 beforeShowDay
.apply((inst
.input
? inst
.input
[0] : null), [printDate
]) : [true, '']);
7360 var otherMonth
= (printDate
.getMonth() != drawMonth
);
7361 var unselectable
= otherMonth
|| !daySettings
[0] ||
7362 (minDate
&& printDate
< minDate
) || (maxDate
&& printDate
> maxDate
);
7363 tbody
+= '<td class="' +
7364 ((dow
+ firstDay
+ 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
7365 (otherMonth
? ' ui-datepicker-other-month' : '') + // highlight days from other months
7366 ((printDate
.getTime() == selectedDate
.getTime() && drawMonth
== inst
.selectedMonth
&& inst
._keyEvent
) || // user pressed key
7367 (defaultDate
.getTime() == printDate
.getTime() && defaultDate
.getTime() == selectedDate
.getTime()) ?
7368 // or defaultDate is current printedDate and defaultDate is selectedDate
7369 ' ' + this._dayOverClass
: '') + // highlight selected day
7370 (unselectable
? ' ' + this._unselectableClass
+ ' ui-state-disabled': '') + // highlight unselectable days
7371 (otherMonth
&& !showOtherMonths
? '' : ' ' + daySettings
[1] + // highlight custom dates
7372 (printDate
.getTime() >= currentDate
.getTime() && printDate
.getTime() <= endDate
.getTime() ? // in current range
7373 ' ' + this._currentClass
: '') + // highlight selected day
7374 (printDate
.getTime() == today
.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
7375 ((!otherMonth
|| showOtherMonths
) && daySettings
[2] ? ' title="' + daySettings
[2] + '"' : '') + // cell title
7376 (unselectable
? '' : ' onclick="DP_jQuery.datepicker._selectDay(\'#' +
7377 inst
.id
+ '\',' + drawMonth
+ ',' + drawYear
+ ', this);return false;"') + '>' + // actions
7378 (otherMonth
? (showOtherMonths
? printDate
.getDate() : ' ') : // display for other months
7379 (unselectable
? '<span class="ui-state-default">' + printDate
.getDate() + '</span>' : '<a class="ui-state-default' +
7380 (printDate
.getTime() == today
.getTime() ? ' ui-state-highlight' : '') +
7381 (printDate
.getTime() >= currentDate
.getTime() && printDate
.getTime() <= endDate
.getTime() ? // in current range
7382 ' ui-state-active' : '') + // highlight selected day
7383 '" href="#">' + printDate
.getDate() + '</a>')) + '</td>'; // display for this month
7384 printDate
.setDate(printDate
.getDate() + 1);
7385 printDate
= this._daylightSavingAdjust(printDate
);
7387 calender
+= tbody
+ '</tr>';
7390 if (drawMonth
> 11) {
7394 calender
+= '</tbody></table>' + (isMultiMonth
? '</div>' +
7395 ((numMonths
[0] > 0 && col
== numMonths
[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
7400 html
+= buttonPanel
+ ($.browser
.msie
&& parseInt($.browser
.version
,10) < 7 && !inst
.inline
?
7401 '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
7402 inst
._keyEvent
= false;
7406 /* Generate the month and year header. */
7407 _generateMonthYearHeader: function(inst
, drawMonth
, drawYear
, minDate
, maxDate
,
7408 selectedDate
, secondary
, monthNames
, monthNamesShort
) {
7409 minDate
= (inst
.rangeStart
&& minDate
&& selectedDate
< minDate
? selectedDate
: minDate
);
7410 var changeMonth
= this._get(inst
, 'changeMonth');
7411 var changeYear
= this._get(inst
, 'changeYear');
7412 var showMonthAfterYear
= this._get(inst
, 'showMonthAfterYear');
7413 var html
= '<div class="ui-datepicker-title">';
7416 if (secondary
|| !changeMonth
)
7417 monthHtml
+= '<span class="ui-datepicker-month">' + monthNames
[drawMonth
] + '</span> ';
7419 var inMinYear
= (minDate
&& minDate
.getFullYear() == drawYear
);
7420 var inMaxYear
= (maxDate
&& maxDate
.getFullYear() == drawYear
);
7421 monthHtml
+= '<select class="ui-datepicker-month" ' +
7422 'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst
.id
+ '\', this, \'M\');" ' +
7423 'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst
.id
+ '\');"' +
7425 for (var month
= 0; month
< 12; month
++) {
7426 if ((!inMinYear
|| month
>= minDate
.getMonth()) &&
7427 (!inMaxYear
|| month
<= maxDate
.getMonth()))
7428 monthHtml
+= '<option value="' + month
+ '"' +
7429 (month
== drawMonth
? ' selected="selected"' : '') +
7430 '>' + monthNamesShort
[month
] + '</option>';
7432 monthHtml
+= '</select>';
7434 if (!showMonthAfterYear
)
7435 html
+= monthHtml
+ ((secondary
|| changeMonth
|| changeYear
) && (!(changeMonth
&& changeYear
)) ? ' ' : '');
7437 if (secondary
|| !changeYear
)
7438 html
+= '<span class="ui-datepicker-year">' + drawYear
+ '</span>';
7440 // determine range of years to display
7441 var years
= this._get(inst
, 'yearRange').split(':');
7444 if (years
.length
!= 2) {
7445 year
= drawYear
- 10;
7446 endYear
= drawYear
+ 10;
7447 } else if (years
[0].charAt(0) == '+' || years
[0].charAt(0) == '-') {
7448 year
= drawYear
+ parseInt(years
[0], 10);
7449 endYear
= drawYear
+ parseInt(years
[1], 10);
7451 year
= parseInt(years
[0], 10);
7452 endYear
= parseInt(years
[1], 10);
7454 year
= (minDate
? Math
.max(year
, minDate
.getFullYear()) : year
);
7455 endYear
= (maxDate
? Math
.min(endYear
, maxDate
.getFullYear()) : endYear
);
7456 html
+= '<select class="ui-datepicker-year" ' +
7457 'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst
.id
+ '\', this, \'Y\');" ' +
7458 'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst
.id
+ '\');"' +
7460 for (; year
<= endYear
; year
++) {
7461 html
+= '<option value="' + year
+ '"' +
7462 (year
== drawYear
? ' selected="selected"' : '') +
7463 '>' + year
+ '</option>';
7465 html
+= '</select>';
7467 if (showMonthAfterYear
)
7468 html
+= (secondary
|| changeMonth
|| changeYear
? ' ' : '') + monthHtml
;
7469 html
+= '</div>'; // Close datepicker_header
7473 /* Adjust one of the date sub-fields. */
7474 _adjustInstDate: function(inst
, offset
, period
) {
7475 var year
= inst
.drawYear
+ (period
== 'Y' ? offset
: 0);
7476 var month
= inst
.drawMonth
+ (period
== 'M' ? offset
: 0);
7477 var day
= Math
.min(inst
.selectedDay
, this._getDaysInMonth(year
, month
)) +
7478 (period
== 'D' ? offset
: 0);
7479 var date
= this._daylightSavingAdjust(new Date(year
, month
, day
));
7480 // ensure it is within the bounds set
7481 var minDate
= this._getMinMaxDate(inst
, 'min', true);
7482 var maxDate
= this._getMinMaxDate(inst
, 'max');
7483 date
= (minDate
&& date
< minDate
? minDate
: date
);
7484 date
= (maxDate
&& date
> maxDate
? maxDate
: date
);
7485 inst
.selectedDay
= date
.getDate();
7486 inst
.drawMonth
= inst
.selectedMonth
= date
.getMonth();
7487 inst
.drawYear
= inst
.selectedYear
= date
.getFullYear();
7488 if (period
== 'M' || period
== 'Y')
7489 this._notifyChange(inst
);
7492 /* Notify change of month/year. */
7493 _notifyChange: function(inst) {
7494 var onChange = this._get(inst, 'onChangeMonthYear');
7496 onChange.apply((inst.input ? inst.input[0] : null),
7497 [inst.selectedYear, inst.selectedMonth + 1, inst]);
7500 /* Determine the number of months to show. */
7501 _getNumberOfMonths: function(inst
) {
7502 var numMonths
= this._get(inst
, 'numberOfMonths');
7503 return (numMonths
== null ? [1, 1] : (typeof numMonths
== 'number' ? [1, numMonths
] : numMonths
));
7506 /* Determine the current maximum date - ensure no time components are set - may be overridden for a range. */
7507 _getMinMaxDate: function(inst
, minMax
, checkRange
) {
7508 var date
= this._determineDate(this._get(inst
, minMax
+ 'Date'), null);
7509 return (!checkRange
|| !inst
.rangeStart
? date
:
7510 (!date
|| inst
.rangeStart
> date
? inst
.rangeStart
: date
));
7513 /* Find the number of days in a given month. */
7514 _getDaysInMonth: function(year
, month
) {
7515 return 32 - new Date(year
, month
, 32).getDate();
7518 /* Find the day of the week of the first of a month. */
7519 _getFirstDayOfMonth: function(year
, month
) {
7520 return new Date(year
, month
, 1).getDay();
7523 /* Determines if we should allow a "next/prev" month display change. */
7524 _canAdjustMonth: function(inst, offset, curYear, curMonth) {
7525 var numMonths = this._getNumberOfMonths(inst);
7526 var date = this._daylightSavingAdjust(new Date(
7527 curYear, curMonth + (offset < 0 ? offset : numMonths[1]), 1));
7529 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
7530 return this._isInRange(inst, date);
7533 /* Is the given date in the accepted range? */
7534 _isInRange: function(inst
, date
) {
7535 // during range selection, use minimum of selected date and range start
7536 var newMinDate
= (!inst
.rangeStart
? null : this._daylightSavingAdjust(
7537 new Date(inst
.selectedYear
, inst
.selectedMonth
, inst
.selectedDay
)));
7538 newMinDate
= (newMinDate
&& inst
.rangeStart
< newMinDate
? inst
.rangeStart
: newMinDate
);
7539 var minDate
= newMinDate
|| this._getMinMaxDate(inst
, 'min');
7540 var maxDate
= this._getMinMaxDate(inst
, 'max');
7541 return ((!minDate
|| date
>= minDate
) && (!maxDate
|| date
<= maxDate
));
7544 /* Provide the configuration settings for formatting/parsing. */
7545 _getFormatConfig: function(inst) {
7546 var shortYearCutoff = this._get(inst, 'shortYearCutoff');
7547 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
7548 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
7549 return {shortYearCutoff: shortYearCutoff,
7550 dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
7551 monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
7554 /* Format the given date for display. */
7555 _formatDate: function(inst
, day
, month
, year
) {
7557 inst
.currentDay
= inst
.selectedDay
;
7558 inst
.currentMonth
= inst
.selectedMonth
;
7559 inst
.currentYear
= inst
.selectedYear
;
7561 var date
= (day
? (typeof day
== 'object' ? day
:
7562 this._daylightSavingAdjust(new Date(year
, month
, day
))) :
7563 this._daylightSavingAdjust(new Date(inst
.currentYear
, inst
.currentMonth
, inst
.currentDay
)));
7564 return this.formatDate(this._get(inst
, 'dateFormat'), date
, this._getFormatConfig(inst
));
7568 /* jQuery extend now ignores nulls! */
7569 function extendRemove(target
, props
) {
7570 $.extend(target
, props
);
7571 for (var name
in props
)
7572 if (props
[name
] == null || props
[name
] == undefined)
7573 target
[name
] = props
[name
];
7577 /* Determine whether an object is an array. */
7578 function isArray(a
) {
7579 return (a
&& (($.browser
.safari
&& typeof a
== 'object' && a
.length
) ||
7580 (a
.constructor && a
.constructor.toString().match(/\Array\(\)/))));
7583 /* Invoke the datepicker functionality.
7584 @param options string - a command, optionally followed by additional parameters or
7585 Object - settings for attaching new datepicker functionality
7586 @return jQuery object */
7587 $.fn
.datepicker = function(options
){
7589 /* Initialise the date picker. */
7590 if (!$.datepicker
.initialized
) {
7591 $(document
).mousedown($.datepicker
._checkExternalClick
).
7592 find('body').append($.datepicker
.dpDiv
);
7593 $.datepicker
.initialized
= true;
7596 var otherArgs
= Array
.prototype.slice
.call(arguments
, 1);
7597 if (typeof options
== 'string' && (options
== 'isDisabled' || options
== 'getDate'))
7598 return $.datepicker
['_' + options
+ 'Datepicker'].
7599 apply($.datepicker
, [this[0]].concat(otherArgs
));
7600 return this.each(function() {
7601 typeof options
== 'string' ?
7602 $.datepicker
['_' + options
+ 'Datepicker'].
7603 apply($.datepicker
, [this].concat(otherArgs
)) :
7604 $.datepicker
._attachDatepicker(this, options
);
7608 $.datepicker
= new Datepicker(); // singleton instance
7609 $.datepicker
.initialized
= false;
7610 $.datepicker
.uuid
= new Date().getTime();
7611 $.datepicker
.version
= "1.7.1";
7613 // Workaround for #4055
7614 // Add another global to avoid noConflict issues with inline event handlers
7615 window
.DP_jQuery
= $;
7619 * jQuery UI Progressbar 1.7.1
7621 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
7622 * Dual licensed under the MIT (MIT-LICENSE.txt)
7623 * and GPL (GPL-LICENSE.txt) licenses.
7625 * http://docs.jquery.com/UI/Progressbar
7632 $.widget("ui.progressbar", {
7637 .addClass("ui-progressbar"
7639 + " ui-widget-content"
7642 role
: "progressbar",
7643 "aria-valuemin": this._valueMin(),
7644 "aria-valuemax": this._valueMax(),
7645 "aria-valuenow": this._value()
7648 this.valueDiv
= $('<div class="ui-progressbar-value ui-widget-header ui-corner-left"></div>').appendTo(this.element
);
7650 this._refreshValue();
7654 destroy: function() {
7657 .removeClass("ui-progressbar"
7659 + " ui-widget-content"
7662 .removeAttr("aria-valuemin")
7663 .removeAttr("aria-valuemax")
7664 .removeAttr("aria-valuenow")
7665 .removeData("progressbar")
7666 .unbind(".progressbar");
7668 this.valueDiv
.remove();
7670 $.widget
.prototype.destroy
.apply(this, arguments
);
7674 value: function(newValue
) {
7675 arguments
.length
&& this._setData("value", newValue
);
7676 return this._value();
7679 _setData: function(key
, value
) {
7683 this.options
.value
= value
;
7684 this._refreshValue();
7685 this._trigger('change', null, {});
7689 $.widget
.prototype._setData
.apply(this, arguments
);
7693 _value: function() {
7695 var val
= this.options
.value
;
7696 if (val
< this._valueMin()) val
= this._valueMin();
7697 if (val
> this._valueMax()) val
= this._valueMax();
7703 _valueMin: function() {
7708 _valueMax: function() {
7713 _refreshValue: function() {
7714 var value
= this.value();
7715 this.valueDiv
[value
== this._valueMax() ? 'addClass' : 'removeClass']("ui-corner-right");
7716 this.valueDiv
.width(value
+ '%');
7717 this.element
.attr("aria-valuenow", value
);
7722 $.extend($.ui
.progressbar
, {
7731 * jQuery UI Effects 1.7.1
7733 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
7734 * Dual licensed under the MIT (MIT-LICENSE.txt)
7735 * and GPL (GPL-LICENSE.txt) licenses.
7737 * http://docs.jquery.com/UI/Effects/
7739 ;jQuery
.effects
|| (function($) {
7744 // Saves a set of properties in a data storage
7745 save: function(element
, set) {
7746 for(var i
=0; i
< set.length
; i
++) {
7747 if(set[i
] !== null) element
.data("ec.storage."+set[i
], element
[0].style
[set[i
]]);
7751 // Restores a set of previously saved properties from a data storage
7752 restore: function(element
, set) {
7753 for(var i
=0; i
< set.length
; i
++) {
7754 if(set[i
] !== null) element
.css(set[i
], element
.data("ec.storage."+set[i
]));
7758 setMode: function(el
, mode
) {
7759 if (mode
== 'toggle') mode
= el
.is(':hidden') ? 'show' : 'hide'; // Set for toggle
7763 getBaseline: function(origin
, original
) { // Translates a [top,left] array into a baseline value
7764 // this should be a little more flexible in the future to handle a string & hash
7766 switch (origin
[0]) {
7767 case 'top': y
= 0; break;
7768 case 'middle': y
= 0.5; break;
7769 case 'bottom': y
= 1; break;
7770 default: y
= origin
[0] / original
.height
;
7772 switch (origin
[1]) {
7773 case 'left': x
= 0; break;
7774 case 'center': x
= 0.5; break;
7775 case 'right': x
= 1; break;
7776 default: x
= origin
[1] / original
.width
;
7778 return {x
: x
, y
: y
};
7781 // Wraps the element around a wrapper that copies position properties
7782 createWrapper: function(element
) {
7784 //if the element is already wrapped, return it
7785 if (element
.parent().is('.ui-effects-wrapper'))
7786 return element
.parent();
7788 //Cache width,height and float properties of the element, and create a wrapper around it
7789 var props
= { width
: element
.outerWidth(true), height
: element
.outerHeight(true), 'float': element
.css('float') };
7790 element
.wrap('<div class="ui-effects-wrapper" style="font-size:100%;background:transparent;border:none;margin:0;padding:0"></div>');
7791 var wrapper
= element
.parent();
7793 //Transfer the positioning of the element to the wrapper
7794 if (element
.css('position') == 'static') {
7795 wrapper
.css({ position
: 'relative' });
7796 element
.css({ position
: 'relative'} );
7798 var top
= element
.css('top'); if(isNaN(parseInt(top
,10))) top
= 'auto';
7799 var left
= element
.css('left'); if(isNaN(parseInt(left
,10))) left
= 'auto';
7800 wrapper
.css({ position
: element
.css('position'), top
: top
, left
: left
, zIndex
: element
.css('z-index') }).show();
7801 element
.css({position
: 'relative', top
: 0, left
: 0 });
7808 removeWrapper: function(element
) {
7809 if (element
.parent().is('.ui-effects-wrapper'))
7810 return element
.parent().replaceWith(element
);
7814 setTransition: function(element
, list
, factor
, value
) {
7815 value
= value
|| {};
7816 $.each(list
, function(i
, x
){
7817 unit
= element
.cssUnit(x
);
7818 if (unit
[0] > 0) value
[x
] = unit
[0] * factor
+ unit
[1];
7823 //Base function to animate from one class to another in a seamless transition
7824 animateClass: function(value
, duration
, easing
, callback
) {
7826 var cb
= (typeof easing
== "function" ? easing
: (callback
? callback
: null));
7827 var ea
= (typeof easing
== "string" ? easing
: null);
7829 return this.each(function() {
7831 var offset
= {}; var that
= $(this); var oldStyleAttr
= that
.attr("style") || '';
7832 if(typeof oldStyleAttr
== 'object') oldStyleAttr
= oldStyleAttr
["cssText"]; /* Stupidly in IE, style is a object.. */
7833 if(value
.toggle
) { that
.hasClass(value
.toggle
) ? value
.remove
= value
.toggle
: value
.add
= value
.toggle
; }
7835 //Let's get a style offset
7836 var oldStyle
= $.extend({}, (document
.defaultView
? document
.defaultView
.getComputedStyle(this,null) : this.currentStyle
));
7837 if(value
.add
) that
.addClass(value
.add
); if(value
.remove
) that
.removeClass(value
.remove
);
7838 var newStyle
= $.extend({}, (document
.defaultView
? document
.defaultView
.getComputedStyle(this,null) : this.currentStyle
));
7839 if(value
.add
) that
.removeClass(value
.add
); if(value
.remove
) that
.addClass(value
.remove
);
7841 // The main function to form the object for animation
7842 for(var n
in newStyle
) {
7843 if( typeof newStyle
[n
] != "function" && newStyle
[n
] /* No functions and null properties */
7844 && n
.indexOf("Moz") == -1 && n
.indexOf("length") == -1 /* No mozilla spezific render properties. */
7845 && newStyle
[n
] != oldStyle
[n
] /* Only values that have changed are used for the animation */
7846 && (n
.match(/color/i) || (!n
.match(/color/i) && !isNaN(parseInt(newStyle
[n
],10)))) /* Only things that can be parsed to integers or colors */
7847 && (oldStyle
.position
!= "static" || (oldStyle
.position
== "static" && !n
.match(/left|top|bottom|right/))) /* No need for positions when dealing with static positions */
7848 ) offset
[n
] = newStyle
[n
];
7851 that
.animate(offset
, duration
, ea
, function() { // Animate the newly constructed offset object
7852 // Change style attribute back to original. For stupid IE, we need to clear the damn object.
7853 if(typeof $(this).attr("style") == 'object') { $(this).attr("style")["cssText"] = ""; $(this).attr("style")["cssText"] = oldStyleAttr
; } else $(this).attr("style", oldStyleAttr
);
7854 if(value
.add
) $(this).addClass(value
.add
); if(value
.remove
) $(this).removeClass(value
.remove
);
7855 if(cb
) cb
.apply(this, arguments
);
7863 function _normalizeArguments(a
, m
) {
7865 var o
= a
[1] && a
[1].constructor == Object
? a
[1] : {}; if(m
) o
.mode
= m
;
7866 var speed
= a
[1] && a
[1].constructor != Object
? a
[1] : (o
.duration
? o
.duration
: a
[2]); //either comes from options.duration or the secon/third argument
7867 speed
= $.fx
.off
? 0 : typeof speed
=== "number" ? speed
: $.fx
.speeds
[speed
] || $.fx
.speeds
._default
;
7868 var callback
= o
.callback
|| ( $.isFunction(a
[1]) && a
[1] ) || ( $.isFunction(a
[2]) && a
[2] ) || ( $.isFunction(a
[3]) && a
[3] );
7870 return [a
[0], o
, speed
, callback
];
7874 //Extend the methods of jQuery
7880 __toggle
: $.fn
.toggle
,
7881 _addClass
: $.fn
.addClass
,
7882 _removeClass
: $.fn
.removeClass
,
7883 _toggleClass
: $.fn
.toggleClass
,
7885 // New effect methods
7886 effect: function(fx
, options
, speed
, callback
) {
7887 return $.effects
[fx
] ? $.effects
[fx
].call(this, {method
: fx
, options
: options
|| {}, duration
: speed
, callback
: callback
}) : null;
7891 if(!arguments
[0] || (arguments
[0].constructor == Number
|| (/(slow|normal|fast)/).test(arguments
[0])))
7892 return this._show
.apply(this, arguments
);
7894 return this.effect
.apply(this, _normalizeArguments(arguments
, 'show'));
7899 if(!arguments
[0] || (arguments
[0].constructor == Number
|| (/(slow|normal|fast)/).test(arguments
[0])))
7900 return this._hide
.apply(this, arguments
);
7902 return this.effect
.apply(this, _normalizeArguments(arguments
, 'hide'));
7907 if(!arguments
[0] || (arguments
[0].constructor == Number
|| (/(slow|normal|fast)/).test(arguments
[0])) || (arguments
[0].constructor == Function
))
7908 return this.__toggle
.apply(this, arguments
);
7910 return this.effect
.apply(this, _normalizeArguments(arguments
, 'toggle'));
7914 addClass: function(classNames
, speed
, easing
, callback
) {
7915 return speed
? $.effects
.animateClass
.apply(this, [{ add
: classNames
},speed
,easing
,callback
]) : this._addClass(classNames
);
7917 removeClass: function(classNames
,speed
,easing
,callback
) {
7918 return speed
? $.effects
.animateClass
.apply(this, [{ remove
: classNames
},speed
,easing
,callback
]) : this._removeClass(classNames
);
7920 toggleClass: function(classNames
,speed
,easing
,callback
) {
7921 return ( (typeof speed
!== "boolean") && speed
) ? $.effects
.animateClass
.apply(this, [{ toggle
: classNames
},speed
,easing
,callback
]) : this._toggleClass(classNames
, speed
);
7923 morph: function(remove
,add
,speed
,easing
,callback
) {
7924 return $.effects
.animateClass
.apply(this, [{ add
: add
, remove
: remove
},speed
,easing
,callback
]);
7926 switchClass: function() {
7927 return this.morph
.apply(this, arguments
);
7931 cssUnit: function(key
) {
7932 var style
= this.css(key
), val
= [];
7933 $.each( ['em','px','%','pt'], function(i
, unit
){
7934 if(style
.indexOf(unit
) > 0)
7935 val
= [parseFloat(style
), unit
];
7942 * jQuery Color Animations
7943 * Copyright 2007 John Resig
7944 * Released under the MIT and GPL licenses.
7947 // We override the animation for all of these color styles
7948 $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'], function(i
,attr
){
7949 $.fx
.step
[attr
] = function(fx
) {
7950 if ( fx
.state
== 0 ) {
7951 fx
.start
= getColor( fx
.elem
, attr
);
7952 fx
.end
= getRGB( fx
.end
);
7955 fx
.elem
.style
[attr
] = "rgb(" + [
7956 Math
.max(Math
.min( parseInt((fx
.pos
* (fx
.end
[0] - fx
.start
[0])) + fx
.start
[0],10), 255), 0),
7957 Math
.max(Math
.min( parseInt((fx
.pos
* (fx
.end
[1] - fx
.start
[1])) + fx
.start
[1],10), 255), 0),
7958 Math
.max(Math
.min( parseInt((fx
.pos
* (fx
.end
[2] - fx
.start
[2])) + fx
.start
[2],10), 255), 0)
7963 // Color Conversion functions from highlightFade
7964 // By Blair Mitchelmore
7965 // http://jquery.offput.ca/highlightFade/
7967 // Parse strings looking for color tuples [255,255,255]
7968 function getRGB(color
) {
7971 // Check if we're already dealing with an array of colors
7972 if ( color
&& color
.constructor == Array
&& color
.length
== 3 )
7975 // Look for rgb(num,num,num)
7976 if (result
= /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color
))
7977 return [parseInt(result
[1],10), parseInt(result
[2],10), parseInt(result
[3],10)];
7979 // Look for rgb(num%,num%,num%)
7980 if (result
= /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color
))
7981 return [parseFloat(result
[1])*2.55, parseFloat(result
[2])*2.55, parseFloat(result
[3])*2.55];
7984 if (result
= /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color
))
7985 return [parseInt(result
[1],16), parseInt(result
[2],16), parseInt(result
[3],16)];
7988 if (result
= /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color
))
7989 return [parseInt(result
[1]+result
[1],16), parseInt(result
[2]+result
[2],16), parseInt(result
[3]+result
[3],16)];
7991 // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
7992 if (result
= /rgba\(0, 0, 0, 0\)/.exec(color
))
7993 return colors
['transparent'];
7995 // Otherwise, we're most likely dealing with a named color
7996 return colors
[$.trim(color
).toLowerCase()];
7999 function getColor(elem
, attr
) {
8003 color
= $.curCSS(elem
, attr
);
8005 // Keep going until we find an element that has color, or we hit the body
8006 if ( color
!= '' && color
!= 'transparent' || $.nodeName(elem
, "body") )
8009 attr
= "backgroundColor";
8010 } while ( elem
= elem
.parentNode
);
8012 return getRGB(color
);
8015 // Some named colors to work with
8016 // From Interface by Stefan Petre
8017 // http://interface.eyecon.ro/
8021 azure
:[240,255,255],
8022 beige
:[245,245,220],
8028 darkcyan
:[0,139,139],
8029 darkgrey
:[169,169,169],
8030 darkgreen
:[0,100,0],
8031 darkkhaki
:[189,183,107],
8032 darkmagenta
:[139,0,139],
8033 darkolivegreen
:[85,107,47],
8034 darkorange
:[255,140,0],
8035 darkorchid
:[153,50,204],
8037 darksalmon
:[233,150,122],
8038 darkviolet
:[148,0,211],
8039 fuchsia
:[255,0,255],
8043 khaki
:[240,230,140],
8044 lightblue
:[173,216,230],
8045 lightcyan
:[224,255,255],
8046 lightgreen
:[144,238,144],
8047 lightgrey
:[211,211,211],
8048 lightpink
:[255,182,193],
8049 lightyellow
:[255,255,224],
8051 magenta
:[255,0,255],
8060 silver
:[192,192,192],
8061 white
:[255,255,255],
8063 transparent
: [255,255,255]
8067 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
8069 * Uses the built in easing capabilities added In jQuery 1.1
8070 * to offer multiple easing options
8072 * TERMS OF USE - jQuery Easing
8074 * Open source under the BSD License.
8076 * Copyright 2008 George McGinley Smith
8077 * All rights reserved.
8079 * Redistribution and use in source and binary forms, with or without modification,
8080 * are permitted provided that the following conditions are met:
8082 * Redistributions of source code must retain the above copyright notice, this list of
8083 * conditions and the following disclaimer.
8084 * Redistributions in binary form must reproduce the above copyright notice, this list
8085 * of conditions and the following disclaimer in the documentation and/or other materials
8086 * provided with the distribution.
8088 * Neither the name of the author nor the names of contributors may be used to endorse
8089 * or promote products derived from this software without specific prior written permission.
8091 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
8092 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
8093 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
8094 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
8095 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
8096 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
8097 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
8098 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
8099 * OF THE POSSIBILITY OF SUCH DAMAGE.
8103 // t: current time, b: begInnIng value, c: change In value, d: duration
8104 $.easing
.jswing
= $.easing
.swing
;
8109 swing: function (x
, t
, b
, c
, d
) {
8110 //alert($.easing.default);
8111 return $.easing
[$.easing
.def
](x
, t
, b
, c
, d
);
8113 easeInQuad: function (x
, t
, b
, c
, d
) {
8114 return c
*(t
/=d
)*t
+ b
;
8116 easeOutQuad: function (x
, t
, b
, c
, d
) {
8117 return -c
*(t
/=d
)*(t
-2) + b
;
8119 easeInOutQuad: function (x
, t
, b
, c
, d
) {
8120 if ((t
/=d/2) < 1) return c
/2*t
*t
+ b
;
8121 return -c
/2 * ((--t
)*(t
-2) - 1) + b
;
8123 easeInCubic: function (x
, t
, b
, c
, d
) {
8124 return c
*(t
/=d
)*t
*t
+ b
;
8126 easeOutCubic: function (x
, t
, b
, c
, d
) {
8127 return c
*((t
=t
/d
-1)*t
*t
+ 1) + b
;
8129 easeInOutCubic: function (x
, t
, b
, c
, d
) {
8130 if ((t
/=d/2) < 1) return c
/2*t
*t
*t
+ b
;
8131 return c
/2*((t
-=2)*t
*t
+ 2) + b
;
8133 easeInQuart: function (x
, t
, b
, c
, d
) {
8134 return c
*(t
/=d
)*t
*t
*t
+ b
;
8136 easeOutQuart: function (x
, t
, b
, c
, d
) {
8137 return -c
* ((t
=t
/d
-1)*t
*t
*t
- 1) + b
;
8139 easeInOutQuart: function (x
, t
, b
, c
, d
) {
8140 if ((t
/=d/2) < 1) return c
/2*t
*t
*t
*t
+ b
;
8141 return -c
/2 * ((t
-=2)*t
*t
*t
- 2) + b
;
8143 easeInQuint: function (x
, t
, b
, c
, d
) {
8144 return c
*(t
/=d
)*t
*t
*t
*t
+ b
;
8146 easeOutQuint: function (x
, t
, b
, c
, d
) {
8147 return c
*((t
=t
/d
-1)*t
*t
*t
*t
+ 1) + b
;
8149 easeInOutQuint: function (x
, t
, b
, c
, d
) {
8150 if ((t
/=d/2) < 1) return c
/2*t
*t
*t
*t
*t
+ b
;
8151 return c
/2*((t
-=2)*t
*t
*t
*t
+ 2) + b
;
8153 easeInSine: function (x
, t
, b
, c
, d
) {
8154 return -c
* Math
.cos(t
/d * (Math.PI/2)) + c
+ b
;
8156 easeOutSine: function (x
, t
, b
, c
, d
) {
8157 return c
* Math
.sin(t
/d * (Math.PI/2)) + b
;
8159 easeInOutSine: function (x
, t
, b
, c
, d
) {
8160 return -c
/2 * (Math.cos(Math.PI*t/d) - 1) + b
;
8162 easeInExpo: function (x
, t
, b
, c
, d
) {
8163 return (t
==0) ? b
: c
* Math
.pow(2, 10 * (t
/d
- 1)) + b
;
8165 easeOutExpo: function (x
, t
, b
, c
, d
) {
8166 return (t
==d
) ? b
+c
: c
* (-Math
.pow(2, -10 * t
/d
) + 1) + b
;
8168 easeInOutExpo: function (x
, t
, b
, c
, d
) {
8170 if (t
==d
) return b
+c
;
8171 if ((t
/=d/2) < 1) return c
/2 * Math
.pow(2, 10 * (t
- 1)) + b
;
8172 return c
/2 * (-Math
.pow(2, -10 * --t
) + 2) + b
;
8174 easeInCirc: function (x
, t
, b
, c
, d
) {
8175 return -c
* (Math
.sqrt(1 - (t
/=d
)*t
) - 1) + b
;
8177 easeOutCirc: function (x
, t
, b
, c
, d
) {
8178 return c
* Math
.sqrt(1 - (t
=t
/d
-1)*t
) + b
;
8180 easeInOutCirc: function (x
, t
, b
, c
, d
) {
8181 if ((t
/=d/2) < 1) return -c
/2 * (Math
.sqrt(1 - t
*t
) - 1) + b
;
8182 return c
/2 * (Math
.sqrt(1 - (t
-=2)*t
) + 1) + b
;
8184 easeInElastic: function (x
, t
, b
, c
, d
) {
8185 var s
=1.70158;var p
=0;var a
=c
;
8186 if (t
==0) return b
; if ((t
/=d
)==1) return b
+c
; if (!p
) p
=d
*.3;
8187 if (a
< Math
.abs(c
)) { a
=c
; var s
=p
/4; }
8188 else var s
= p
/(2*Math.PI) * Math.asin (c/a);
8189 return -(a
*Math
.pow(2,10*(t
-=1)) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
)) + b
;
8191 easeOutElastic: function (x
, t
, b
, c
, d
) {
8192 var s
=1.70158;var p
=0;var a
=c
;
8193 if (t
==0) return b
; if ((t
/=d
)==1) return b
+c
; if (!p
) p
=d
*.3;
8194 if (a
< Math
.abs(c
)) { a
=c
; var s
=p
/4; }
8195 else var s
= p
/(2*Math.PI) * Math.asin (c/a);
8196 return a
*Math
.pow(2,-10*t
) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
) + c
+ b
;
8198 easeInOutElastic: function (x
, t
, b
, c
, d
) {
8199 var s
=1.70158;var p
=0;var a
=c
;
8200 if (t
==0) return b
; if ((t
/=d/2)==2) return b
+c
; if (!p
) p
=d
*(.3*1.5);
8201 if (a
< Math
.abs(c
)) { a
=c
; var s
=p
/4; }
8202 else var s
= p
/(2*Math.PI) * Math.asin (c/a);
8203 if (t
< 1) return -.5*(a
*Math
.pow(2,10*(t
-=1)) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
)) + b
;
8204 return a
*Math
.pow(2,-10*(t
-=1)) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
)*.5 + c
+ b
;
8206 easeInBack: function (x
, t
, b
, c
, d
, s
) {
8207 if (s
== undefined) s
= 1.70158;
8208 return c
*(t
/=d
)*t
*((s
+1)*t
- s
) + b
;
8210 easeOutBack: function (x
, t
, b
, c
, d
, s
) {
8211 if (s
== undefined) s
= 1.70158;
8212 return c
*((t
=t
/d
-1)*t
*((s
+1)*t
+ s
) + 1) + b
;
8214 easeInOutBack: function (x
, t
, b
, c
, d
, s
) {
8215 if (s
== undefined) s
= 1.70158;
8216 if ((t
/=d/2) < 1) return c
/2*(t
*t
*(((s
*=(1.525))+1)*t
- s
)) + b
;
8217 return c
/2*((t
-=2)*t
*(((s
*=(1.525))+1)*t
+ s
) + 2) + b
;
8219 easeInBounce: function (x
, t
, b
, c
, d
) {
8220 return c
- $.easing
.easeOutBounce (x
, d
-t
, 0, c
, d
) + b
;
8222 easeOutBounce: function (x
, t
, b
, c
, d
) {
8223 if ((t
/=d) < (1/2.75)) {
8224 return c
*(7.5625*t
*t
) + b
;
8225 } else if (t
< (2/2.75)) {
8226 return c
*(7.5625*(t
-=(1.5/2.75))*t
+ .75) + b
;
8227 } else if (t
< (2.5/2.75)) {
8228 return c
*(7.5625*(t
-=(2.25/2.75))*t
+ .9375) + b
;
8230 return c
*(7.5625*(t
-=(2.625/2.75))*t
+ .984375) + b
;
8233 easeInOutBounce: function (x
, t
, b
, c
, d
) {
8234 if (t
< d
/2) return $.easing
.easeInBounce (x
, t
*2, 0, c
, d
) * .5 + b
;
8235 return $.easing
.easeOutBounce (x
, t
*2-d
, 0, c
, d
) * .5 + c
*.5 + b
;
8241 * TERMS OF USE - EASING EQUATIONS
8243 * Open source under the BSD License.
8245 * Copyright 2001 Robert Penner
8246 * All rights reserved.
8248 * Redistribution and use in source and binary forms, with or without modification,
8249 * are permitted provided that the following conditions are met:
8251 * Redistributions of source code must retain the above copyright notice, this list of
8252 * conditions and the following disclaimer.
8253 * Redistributions in binary form must reproduce the above copyright notice, this list
8254 * of conditions and the following disclaimer in the documentation and/or other materials
8255 * provided with the distribution.
8257 * Neither the name of the author nor the names of contributors may be used to endorse
8258 * or promote products derived from this software without specific prior written permission.
8260 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
8261 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
8262 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
8263 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
8264 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
8265 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
8266 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
8267 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
8268 * OF THE POSSIBILITY OF SUCH DAMAGE.
8274 * jQuery UI Effects Blind 1.7.1
8276 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
8277 * Dual licensed under the MIT (MIT-LICENSE.txt)
8278 * and GPL (GPL-LICENSE.txt) licenses.
8280 * http://docs.jquery.com/UI/Effects/Blind
8287 $.effects
.blind = function(o
) {
8289 return this.queue(function() {
8292 var el
= $(this), props
= ['position','top','left'];
8295 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'hide'); // Set Mode
8296 var direction
= o
.options
.direction
|| 'vertical'; // Default direction
8299 $.effects
.save(el
, props
); el
.show(); // Save & Show
8300 var wrapper
= $.effects
.createWrapper(el
).css({overflow
:'hidden'}); // Create Wrapper
8301 var ref
= (direction
== 'vertical') ? 'height' : 'width';
8302 var distance
= (direction
== 'vertical') ? wrapper
.height() : wrapper
.width();
8303 if(mode
== 'show') wrapper
.css(ref
, 0); // Shift
8307 animation
[ref
] = mode
== 'show' ? distance
: 0;
8310 wrapper
.animate(animation
, o
.duration
, o
.options
.easing
, function() {
8311 if(mode
== 'hide') el
.hide(); // Hide
8312 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
8313 if(o
.callback
) o
.callback
.apply(el
[0], arguments
); // Callback
8323 * jQuery UI Effects Bounce 1.7.1
8325 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
8326 * Dual licensed under the MIT (MIT-LICENSE.txt)
8327 * and GPL (GPL-LICENSE.txt) licenses.
8329 * http://docs.jquery.com/UI/Effects/Bounce
8336 $.effects
.bounce = function(o
) {
8338 return this.queue(function() {
8341 var el
= $(this), props
= ['position','top','left'];
8344 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'effect'); // Set Mode
8345 var direction
= o
.options
.direction
|| 'up'; // Default direction
8346 var distance
= o
.options
.distance
|| 20; // Default distance
8347 var times
= o
.options
.times
|| 5; // Default # of times
8348 var speed
= o
.duration
|| 250; // Default speed per bounce
8349 if (/show|hide/.test(mode
)) props
.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
8352 $.effects
.save(el
, props
); el
.show(); // Save & Show
8353 $.effects
.createWrapper(el
); // Create Wrapper
8354 var ref
= (direction
== 'up' || direction
== 'down') ? 'top' : 'left';
8355 var motion
= (direction
== 'up' || direction
== 'left') ? 'pos' : 'neg';
8356 var distance
= o
.options
.distance
|| (ref
== 'top' ? el
.outerHeight({margin
:true}) / 3 : el
.outerWidth({margin
:true}) / 3);
8357 if (mode
== 'show') el
.css('opacity', 0).css(ref
, motion
== 'pos' ? -distance
: distance
); // Shift
8358 if (mode
== 'hide') distance
= distance
/ (times
* 2);
8359 if (mode
!= 'hide') times
--;
8362 if (mode
== 'show') { // Show Bounce
8363 var animation
= {opacity
: 1};
8364 animation
[ref
] = (motion
== 'pos' ? '+=' : '-=') + distance
;
8365 el
.animate(animation
, speed
/ 2, o
.options
.easing
);
8366 distance
= distance
/ 2;
8369 for (var i
= 0; i
< times
; i
++) { // Bounces
8370 var animation1
= {}, animation2
= {};
8371 animation1
[ref
] = (motion
== 'pos' ? '-=' : '+=') + distance
;
8372 animation2
[ref
] = (motion
== 'pos' ? '+=' : '-=') + distance
;
8373 el
.animate(animation1
, speed
/ 2, o
.options
.easing
).animate(animation2
, speed
/ 2, o
.options
.easing
);
8374 distance
= (mode
== 'hide') ? distance
* 2 : distance
/ 2;
8376 if (mode
== 'hide') { // Last Bounce
8377 var animation
= {opacity
: 0};
8378 animation
[ref
] = (motion
== 'pos' ? '-=' : '+=') + distance
;
8379 el
.animate(animation
, speed
/ 2, o
.options
.easing
, function(){
8381 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
8382 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
8385 var animation1
= {}, animation2
= {};
8386 animation1
[ref
] = (motion
== 'pos' ? '-=' : '+=') + distance
;
8387 animation2
[ref
] = (motion
== 'pos' ? '+=' : '-=') + distance
;
8388 el
.animate(animation1
, speed
/ 2, o
.options
.easing
).animate(animation2
, speed
/ 2, o
.options
.easing
, function(){
8389 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
8390 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
8393 el
.queue('fx', function() { el
.dequeue(); });
8401 * jQuery UI Effects Clip 1.7.1
8403 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
8404 * Dual licensed under the MIT (MIT-LICENSE.txt)
8405 * and GPL (GPL-LICENSE.txt) licenses.
8407 * http://docs.jquery.com/UI/Effects/Clip
8414 $.effects
.clip = function(o
) {
8416 return this.queue(function() {
8419 var el
= $(this), props
= ['position','top','left','height','width'];
8422 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'hide'); // Set Mode
8423 var direction
= o
.options
.direction
|| 'vertical'; // Default direction
8426 $.effects
.save(el
, props
); el
.show(); // Save & Show
8427 var wrapper
= $.effects
.createWrapper(el
).css({overflow
:'hidden'}); // Create Wrapper
8428 var animate
= el
[0].tagName
== 'IMG' ? wrapper
: el
;
8430 size
: (direction
== 'vertical') ? 'height' : 'width',
8431 position
: (direction
== 'vertical') ? 'top' : 'left'
8433 var distance
= (direction
== 'vertical') ? animate
.height() : animate
.width();
8434 if(mode
== 'show') { animate
.css(ref
.size
, 0); animate
.css(ref
.position
, distance
/ 2); } // Shift
8438 animation
[ref
.size
] = mode
== 'show' ? distance
: 0;
8439 animation
[ref
.position
] = mode
== 'show' ? 0 : distance
/ 2;
8442 animate
.animate(animation
, { queue
: false, duration
: o
.duration
, easing
: o
.options
.easing
, complete: function() {
8443 if(mode
== 'hide') el
.hide(); // Hide
8444 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
8445 if(o
.callback
) o
.callback
.apply(el
[0], arguments
); // Callback
8455 * jQuery UI Effects Drop 1.7.1
8457 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
8458 * Dual licensed under the MIT (MIT-LICENSE.txt)
8459 * and GPL (GPL-LICENSE.txt) licenses.
8461 * http://docs.jquery.com/UI/Effects/Drop
8468 $.effects
.drop = function(o
) {
8470 return this.queue(function() {
8473 var el
= $(this), props
= ['position','top','left','opacity'];
8476 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'hide'); // Set Mode
8477 var direction
= o
.options
.direction
|| 'left'; // Default Direction
8480 $.effects
.save(el
, props
); el
.show(); // Save & Show
8481 $.effects
.createWrapper(el
); // Create Wrapper
8482 var ref
= (direction
== 'up' || direction
== 'down') ? 'top' : 'left';
8483 var motion
= (direction
== 'up' || direction
== 'left') ? 'pos' : 'neg';
8484 var distance
= o
.options
.distance
|| (ref
== 'top' ? el
.outerHeight({margin
:true}) / 2 : el
.outerWidth({margin
:true}) / 2);
8485 if (mode
== 'show') el
.css('opacity', 0).css(ref
, motion
== 'pos' ? -distance
: distance
); // Shift
8488 var animation
= {opacity
: mode
== 'show' ? 1 : 0};
8489 animation
[ref
] = (mode
== 'show' ? (motion
== 'pos' ? '+=' : '-=') : (motion
== 'pos' ? '-=' : '+=')) + distance
;
8492 el
.animate(animation
, { queue
: false, duration
: o
.duration
, easing
: o
.options
.easing
, complete: function() {
8493 if(mode
== 'hide') el
.hide(); // Hide
8494 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
8495 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
8505 * jQuery UI Effects Explode 1.7.1
8507 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
8508 * Dual licensed under the MIT (MIT-LICENSE.txt)
8509 * and GPL (GPL-LICENSE.txt) licenses.
8511 * http://docs.jquery.com/UI/Effects/Explode
8518 $.effects
.explode = function(o
) {
8520 return this.queue(function() {
8522 var rows
= o
.options
.pieces
? Math
.round(Math
.sqrt(o
.options
.pieces
)) : 3;
8523 var cells
= o
.options
.pieces
? Math
.round(Math
.sqrt(o
.options
.pieces
)) : 3;
8525 o
.options
.mode
= o
.options
.mode
== 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o
.options
.mode
;
8526 var el
= $(this).show().css('visibility', 'hidden');
8527 var offset
= el
.offset();
8529 //Substract the margins - not fixing the problem yet.
8530 offset
.top
-= parseInt(el
.css("marginTop"),10) || 0;
8531 offset
.left
-= parseInt(el
.css("marginLeft"),10) || 0;
8533 var width
= el
.outerWidth(true);
8534 var height
= el
.outerHeight(true);
8536 for(var i
=0;i
<rows
;i
++) { // =
8537 for(var j
=0;j
<cells
;j
++) { // ||
8541 .wrap('<div></div>')
8543 position
: 'absolute',
8544 visibility
: 'visible',
8545 left
: -j
*(width
/cells
),
8546 top
: -i
*(height
/rows
)
8549 .addClass('ui-effects-explode')
8551 position
: 'absolute',
8554 height
: height
/rows
,
8555 left
: offset
.left
+ j
*(width
/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width
/cells
) : 0),
8556 top
: offset
.top
+ i
*(height
/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height
/rows
) : 0),
8557 opacity
: o
.options
.mode
== 'show' ? 0 : 1
8559 left
: offset
.left
+ j
*(width
/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width
/cells
)),
8560 top
: offset
.top
+ i
*(height
/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height
/rows
)),
8561 opacity
: o
.options
.mode
== 'show' ? 1 : 0
8562 }, o
.duration
|| 500);
8566 // Set a timeout, to call the callback approx. when the other animations have finished
8567 setTimeout(function() {
8569 o
.options
.mode
== 'show' ? el
.css({ visibility
: 'visible' }) : el
.css({ visibility
: 'visible' }).hide();
8570 if(o
.callback
) o
.callback
.apply(el
[0]); // Callback
8573 $('div.ui-effects-explode').remove();
8575 }, o
.duration
|| 500);
8584 * jQuery UI Effects Fold 1.7.1
8586 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
8587 * Dual licensed under the MIT (MIT-LICENSE.txt)
8588 * and GPL (GPL-LICENSE.txt) licenses.
8590 * http://docs.jquery.com/UI/Effects/Fold
8597 $.effects
.fold = function(o
) {
8599 return this.queue(function() {
8602 var el
= $(this), props
= ['position','top','left'];
8605 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'hide'); // Set Mode
8606 var size
= o
.options
.size
|| 15; // Default fold size
8607 var horizFirst
= !(!o
.options
.horizFirst
); // Ensure a boolean value
8608 var duration
= o
.duration
? o
.duration
/ 2 : $.fx
.speeds
._default
/ 2;
8611 $.effects
.save(el
, props
); el
.show(); // Save & Show
8612 var wrapper
= $.effects
.createWrapper(el
).css({overflow
:'hidden'}); // Create Wrapper
8613 var widthFirst
= ((mode
== 'show') != horizFirst
);
8614 var ref
= widthFirst
? ['width', 'height'] : ['height', 'width'];
8615 var distance
= widthFirst
? [wrapper
.width(), wrapper
.height()] : [wrapper
.height(), wrapper
.width()];
8616 var percent
= /([0-9]+)%/.exec(size
);
8617 if(percent
) size
= parseInt(percent
[1],10) / 100 * distance
[mode
== 'hide' ? 0 : 1];
8618 if(mode
== 'show') wrapper
.css(horizFirst
? {height
: 0, width
: size
} : {height
: size
, width
: 0}); // Shift
8621 var animation1
= {}, animation2
= {};
8622 animation1
[ref
[0]] = mode
== 'show' ? distance
[0] : size
;
8623 animation2
[ref
[1]] = mode
== 'show' ? distance
[1] : 0;
8626 wrapper
.animate(animation1
, duration
, o
.options
.easing
)
8627 .animate(animation2
, duration
, o
.options
.easing
, function() {
8628 if(mode
== 'hide') el
.hide(); // Hide
8629 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
8630 if(o
.callback
) o
.callback
.apply(el
[0], arguments
); // Callback
8640 * jQuery UI Effects Highlight 1.7.1
8642 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
8643 * Dual licensed under the MIT (MIT-LICENSE.txt)
8644 * and GPL (GPL-LICENSE.txt) licenses.
8646 * http://docs.jquery.com/UI/Effects/Highlight
8653 $.effects
.highlight = function(o
) {
8655 return this.queue(function() {
8658 var el
= $(this), props
= ['backgroundImage','backgroundColor','opacity'];
8661 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'show'); // Set Mode
8662 var color
= o
.options
.color
|| "#ffff99"; // Default highlight color
8663 var oldColor
= el
.css("backgroundColor");
8666 $.effects
.save(el
, props
); el
.show(); // Save & Show
8667 el
.css({backgroundImage
: 'none', backgroundColor
: color
}); // Shift
8670 var animation
= {backgroundColor
: oldColor
};
8671 if (mode
== "hide") animation
['opacity'] = 0;
8674 el
.animate(animation
, { queue
: false, duration
: o
.duration
, easing
: o
.options
.easing
, complete: function() {
8675 if(mode
== "hide") el
.hide();
8676 $.effects
.restore(el
, props
);
8677 if (mode
== "show" && $.browser
.msie
) this.style
.removeAttribute('filter');
8678 if(o
.callback
) o
.callback
.apply(this, arguments
);
8688 * jQuery UI Effects Pulsate 1.7.1
8690 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
8691 * Dual licensed under the MIT (MIT-LICENSE.txt)
8692 * and GPL (GPL-LICENSE.txt) licenses.
8694 * http://docs.jquery.com/UI/Effects/Pulsate
8701 $.effects
.pulsate = function(o
) {
8703 return this.queue(function() {
8709 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'show'); // Set Mode
8710 var times
= o
.options
.times
|| 5; // Default # of times
8711 var duration
= o
.duration
? o
.duration
/ 2 : $.fx
.speeds
._default
/ 2;
8714 if (mode
== 'hide') times
--;
8715 if (el
.is(':hidden')) { // Show fadeIn
8716 el
.css('opacity', 0);
8718 el
.animate({opacity
: 1}, duration
, o
.options
.easing
);
8723 for (var i
= 0; i
< times
; i
++) { // Pulsate
8724 el
.animate({opacity
: 0}, duration
, o
.options
.easing
).animate({opacity
: 1}, duration
, o
.options
.easing
);
8726 if (mode
== 'hide') { // Last Pulse
8727 el
.animate({opacity
: 0}, duration
, o
.options
.easing
, function(){
8729 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
8732 el
.animate({opacity
: 0}, duration
, o
.options
.easing
).animate({opacity
: 1}, duration
, o
.options
.easing
, function(){
8733 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
8736 el
.queue('fx', function() { el
.dequeue(); });
8744 * jQuery UI Effects Scale 1.7.1
8746 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
8747 * Dual licensed under the MIT (MIT-LICENSE.txt)
8748 * and GPL (GPL-LICENSE.txt) licenses.
8750 * http://docs.jquery.com/UI/Effects/Scale
8757 $.effects
.puff = function(o
) {
8759 return this.queue(function() {
8765 var options
= $.extend(true, {}, o
.options
);
8766 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'hide'); // Set Mode
8767 var percent
= parseInt(o
.options
.percent
,10) || 150; // Set default puff percent
8768 options
.fade
= true; // It's not a puff if it doesn't fade! :)
8769 var original
= {height
: el
.height(), width
: el
.width()}; // Save original
8772 var factor
= percent
/ 100;
8773 el
.from = (mode
== 'hide') ? original
: {height
: original
.height
* factor
, width
: original
.width
* factor
};
8776 options
.from = el
.from;
8777 options
.percent
= (mode
== 'hide') ? percent
: 100;
8778 options
.mode
= mode
;
8781 el
.effect('scale', options
, o
.duration
, o
.callback
);
8787 $.effects
.scale = function(o
) {
8789 return this.queue(function() {
8795 var options
= $.extend(true, {}, o
.options
);
8796 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'effect'); // Set Mode
8797 var percent
= parseInt(o
.options
.percent
,10) || (parseInt(o
.options
.percent
,10) == 0 ? 0 : (mode
== 'hide' ? 0 : 100)); // Set default scaling percent
8798 var direction
= o
.options
.direction
|| 'both'; // Set default axis
8799 var origin
= o
.options
.origin
; // The origin of the scaling
8800 if (mode
!= 'effect') { // Set default origin and restore for show/hide
8801 options
.origin
= origin
|| ['middle','center'];
8802 options
.restore
= true;
8804 var original
= {height
: el
.height(), width
: el
.width()}; // Save original
8805 el
.from = o
.options
.from || (mode
== 'show' ? {height
: 0, width
: 0} : original
); // Default from state
8808 var factor
= { // Set scaling factor
8809 y
: direction
!= 'horizontal' ? (percent
/ 100) : 1,
8810 x
: direction
!= 'vertical' ? (percent
/ 100) : 1
8812 el
.to
= {height
: original
.height
* factor
.y
, width
: original
.width
* factor
.x
}; // Set to state
8814 if (o
.options
.fade
) { // Fade option to support puff
8815 if (mode
== 'show') {el
.from.opacity
= 0; el
.to
.opacity
= 1;};
8816 if (mode
== 'hide') {el
.from.opacity
= 1; el
.to
.opacity
= 0;};
8820 options
.from = el
.from; options
.to
= el
.to
; options
.mode
= mode
;
8823 el
.effect('size', options
, o
.duration
, o
.callback
);
8829 $.effects
.size = function(o
) {
8831 return this.queue(function() {
8834 var el
= $(this), props
= ['position','top','left','width','height','overflow','opacity'];
8835 var props1
= ['position','top','left','overflow','opacity']; // Always restore
8836 var props2
= ['width','height','overflow']; // Copy for children
8837 var cProps
= ['fontSize'];
8838 var vProps
= ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
8839 var hProps
= ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
8842 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'effect'); // Set Mode
8843 var restore
= o
.options
.restore
|| false; // Default restore
8844 var scale
= o
.options
.scale
|| 'both'; // Default scale mode
8845 var origin
= o
.options
.origin
; // The origin of the sizing
8846 var original
= {height
: el
.height(), width
: el
.width()}; // Save original
8847 el
.from = o
.options
.from || original
; // Default from state
8848 el
.to
= o
.options
.to
|| original
; // Default to state
8850 if (origin
) { // Calculate baseline shifts
8851 var baseline
= $.effects
.getBaseline(origin
, original
);
8852 el
.from.top
= (original
.height
- el
.from.height
) * baseline
.y
;
8853 el
.from.left
= (original
.width
- el
.from.width
) * baseline
.x
;
8854 el
.to
.top
= (original
.height
- el
.to
.height
) * baseline
.y
;
8855 el
.to
.left
= (original
.width
- el
.to
.width
) * baseline
.x
;
8857 var factor
= { // Set scaling factor
8858 from: {y
: el
.from.height
/ original
.height
, x
: el
.from.width
/ original
.width
},
8859 to
: {y
: el
.to
.height
/ original
.height
, x
: el
.to
.width
/ original
.width
}
8861 if (scale
== 'box' || scale
== 'both') { // Scale the css box
8862 if (factor
.from.y
!= factor
.to
.y
) { // Vertical props scaling
8863 props
= props
.concat(vProps
);
8864 el
.from = $.effects
.setTransition(el
, vProps
, factor
.from.y
, el
.from);
8865 el
.to
= $.effects
.setTransition(el
, vProps
, factor
.to
.y
, el
.to
);
8867 if (factor
.from.x
!= factor
.to
.x
) { // Horizontal props scaling
8868 props
= props
.concat(hProps
);
8869 el
.from = $.effects
.setTransition(el
, hProps
, factor
.from.x
, el
.from);
8870 el
.to
= $.effects
.setTransition(el
, hProps
, factor
.to
.x
, el
.to
);
8873 if (scale
== 'content' || scale
== 'both') { // Scale the content
8874 if (factor
.from.y
!= factor
.to
.y
) { // Vertical props scaling
8875 props
= props
.concat(cProps
);
8876 el
.from = $.effects
.setTransition(el
, cProps
, factor
.from.y
, el
.from);
8877 el
.to
= $.effects
.setTransition(el
, cProps
, factor
.to
.y
, el
.to
);
8880 $.effects
.save(el
, restore
? props
: props1
); el
.show(); // Save & Show
8881 $.effects
.createWrapper(el
); // Create Wrapper
8882 el
.css('overflow','hidden').css(el
.from); // Shift
8885 if (scale
== 'content' || scale
== 'both') { // Scale the children
8886 vProps
= vProps
.concat(['marginTop','marginBottom']).concat(cProps
); // Add margins/font-size
8887 hProps
= hProps
.concat(['marginLeft','marginRight']); // Add margins
8888 props2
= props
.concat(vProps
).concat(hProps
); // Concat
8889 el
.find("*[width]").each(function(){
8891 if (restore
) $.effects
.save(child
, props2
);
8892 var c_original
= {height
: child
.height(), width
: child
.width()}; // Save original
8893 child
.from = {height
: c_original
.height
* factor
.from.y
, width
: c_original
.width
* factor
.from.x
};
8894 child
.to
= {height
: c_original
.height
* factor
.to
.y
, width
: c_original
.width
* factor
.to
.x
};
8895 if (factor
.from.y
!= factor
.to
.y
) { // Vertical props scaling
8896 child
.from = $.effects
.setTransition(child
, vProps
, factor
.from.y
, child
.from);
8897 child
.to
= $.effects
.setTransition(child
, vProps
, factor
.to
.y
, child
.to
);
8899 if (factor
.from.x
!= factor
.to
.x
) { // Horizontal props scaling
8900 child
.from = $.effects
.setTransition(child
, hProps
, factor
.from.x
, child
.from);
8901 child
.to
= $.effects
.setTransition(child
, hProps
, factor
.to
.x
, child
.to
);
8903 child
.css(child
.from); // Shift children
8904 child
.animate(child
.to
, o
.duration
, o
.options
.easing
, function(){
8905 if (restore
) $.effects
.restore(child
, props2
); // Restore children
8906 }); // Animate children
8911 el
.animate(el
.to
, { queue
: false, duration
: o
.duration
, easing
: o
.options
.easing
, complete: function() {
8912 if(mode
== 'hide') el
.hide(); // Hide
8913 $.effects
.restore(el
, restore
? props
: props1
); $.effects
.removeWrapper(el
); // Restore
8914 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
8924 * jQuery UI Effects Shake 1.7.1
8926 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
8927 * Dual licensed under the MIT (MIT-LICENSE.txt)
8928 * and GPL (GPL-LICENSE.txt) licenses.
8930 * http://docs.jquery.com/UI/Effects/Shake
8937 $.effects
.shake = function(o
) {
8939 return this.queue(function() {
8942 var el
= $(this), props
= ['position','top','left'];
8945 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'effect'); // Set Mode
8946 var direction
= o
.options
.direction
|| 'left'; // Default direction
8947 var distance
= o
.options
.distance
|| 20; // Default distance
8948 var times
= o
.options
.times
|| 3; // Default # of times
8949 var speed
= o
.duration
|| o
.options
.duration
|| 140; // Default speed per shake
8952 $.effects
.save(el
, props
); el
.show(); // Save & Show
8953 $.effects
.createWrapper(el
); // Create Wrapper
8954 var ref
= (direction
== 'up' || direction
== 'down') ? 'top' : 'left';
8955 var motion
= (direction
== 'up' || direction
== 'left') ? 'pos' : 'neg';
8958 var animation
= {}, animation1
= {}, animation2
= {};
8959 animation
[ref
] = (motion
== 'pos' ? '-=' : '+=') + distance
;
8960 animation1
[ref
] = (motion
== 'pos' ? '+=' : '-=') + distance
* 2;
8961 animation2
[ref
] = (motion
== 'pos' ? '-=' : '+=') + distance
* 2;
8964 el
.animate(animation
, speed
, o
.options
.easing
);
8965 for (var i
= 1; i
< times
; i
++) { // Shakes
8966 el
.animate(animation1
, speed
, o
.options
.easing
).animate(animation2
, speed
, o
.options
.easing
);
8968 el
.animate(animation1
, speed
, o
.options
.easing
).
8969 animate(animation
, speed
/ 2, o
.options
.easing
, function(){ // Last shake
8970 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
8971 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
8973 el
.queue('fx', function() { el
.dequeue(); });
8981 * jQuery UI Effects Slide 1.7.1
8983 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
8984 * Dual licensed under the MIT (MIT-LICENSE.txt)
8985 * and GPL (GPL-LICENSE.txt) licenses.
8987 * http://docs.jquery.com/UI/Effects/Slide
8994 $.effects
.slide = function(o
) {
8996 return this.queue(function() {
8999 var el
= $(this), props
= ['position','top','left'];
9002 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'show'); // Set Mode
9003 var direction
= o
.options
.direction
|| 'left'; // Default Direction
9006 $.effects
.save(el
, props
); el
.show(); // Save & Show
9007 $.effects
.createWrapper(el
).css({overflow
:'hidden'}); // Create Wrapper
9008 var ref
= (direction
== 'up' || direction
== 'down') ? 'top' : 'left';
9009 var motion
= (direction
== 'up' || direction
== 'left') ? 'pos' : 'neg';
9010 var distance
= o
.options
.distance
|| (ref
== 'top' ? el
.outerHeight({margin
:true}) : el
.outerWidth({margin
:true}));
9011 if (mode
== 'show') el
.css(ref
, motion
== 'pos' ? -distance
: distance
); // Shift
9015 animation
[ref
] = (mode
== 'show' ? (motion
== 'pos' ? '+=' : '-=') : (motion
== 'pos' ? '-=' : '+=')) + distance
;
9018 el
.animate(animation
, { queue
: false, duration
: o
.duration
, easing
: o
.options
.easing
, complete: function() {
9019 if(mode
== 'hide') el
.hide(); // Hide
9020 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
9021 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
9031 * jQuery UI Effects Transfer 1.7.1
9033 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
9034 * Dual licensed under the MIT (MIT-LICENSE.txt)
9035 * and GPL (GPL-LICENSE.txt) licenses.
9037 * http://docs.jquery.com/UI/Effects/Transfer
9044 $.effects
.transfer = function(o
) {
9045 return this.queue(function() {
9047 target
= $(o
.options
.to
),
9048 endPosition
= target
.offset(),
9050 top
: endPosition
.top
,
9051 left
: endPosition
.left
,
9052 height
: target
.innerHeight(),
9053 width
: target
.innerWidth()
9055 startPosition
= elem
.offset(),
9056 transfer
= $('<div class="ui-effects-transfer"></div>')
9057 .appendTo(document
.body
)
9058 .addClass(o
.options
.className
)
9060 top
: startPosition
.top
,
9061 left
: startPosition
.left
,
9062 height
: elem
.innerHeight(),
9063 width
: elem
.innerWidth(),
9064 position
: 'absolute'
9066 .animate(animation
, o
.duration
, o
.options
.easing
, function() {
9068 (o
.callback
&& o
.callback
.apply(elem
[0], arguments
));