4 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
5 * Dual licensed under the MIT (MIT-LICENSE.txt)
6 * and GPL (GPL-LICENSE.txt) licenses.
8 * http://docs.jquery.com/UI
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];
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);
48 if ($.ui.cssCache[name]) { return $.ui.cssCache[name]; }
49 var tmp = $('<div class="ui-gen"></div>').addClass(name).css({position:'absolute', top:'-5000px', left:'-5000px', display:'block'}).appendTo('body');
51 //if (!$.browser.safari)
52 //tmp.appendTo('body');
54 //Opera and Safari set width and height to 0px instead of auto
55 //Safari returns rgba(0,0,0,0) when bgcolor is not set
56 $.ui.cssCache[name] = !!(
57 (!(/auto|default/).test(tmp.css('cursor')) || (/^[1-9]/).test(tmp.css('height')) || (/^[1-9]/).test(tmp.css('width')) ||
58 !(/none/).test(tmp.css('backgroundImage')) || !(/transparent|rgba\(0, 0, 0, 0\)/).test(tmp.css('backgroundColor')))
60 try { $('body').get(0).removeChild(tmp.get(0)); } catch(e){}
61 return $.ui.cssCache[name];
64 hasScroll: function(el, a) {
66 //If overflow is hidden, the element might have extra content, but the user wants to hide it
67 if ($(el).css('overflow') == 'hidden') { return false; }
69 var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop',
72 if (el[scroll] > 0) { return true; }
74 // TODO: determine which cases actually cause this to happen
75 // if the element doesn't have the scroll set, see if it's possible to
78 has = (el[scroll] > 0);
83 isOverAxis: function(x, reference, size) {
84 //Determines when x coordinate is over "b" element axis
85 return (x > reference) && (x < (reference + size));
88 isOver: function(y, x, top, left, height, width) {
89 //Determines when x, y coordinates is over "b" element
90 return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width);
110 NUMPAD_MULTIPLY: 106,
111 NUMPAD_SUBTRACT: 109,
123 // WAI-ARIA normalization
126 removeAttr = $.fn.removeAttr,
127 ariaNS = "http://www.w3.org/2005/07/aaa",
128 ariaState = /^aria-/,
129 ariaRole = /^wairole:/;
131 $.attr = function(elem, name, value) {
132 var set = value !== undefined;
134 return (name == 'role'
136 ? attr.call(this, elem, name, "wairole:" + value)
137 : (attr.apply(this, arguments) || "").replace(ariaRole, ""))
138 : (ariaState.test(name)
140 ? elem.setAttributeNS(ariaNS,
141 name.replace(ariaState, "aaa:"), value)
142 : attr.call(this, elem, name.replace(ariaState, "aaa:")))
143 : attr.apply(this, arguments)));
146 $.fn.removeAttr = function(name) {
147 return (ariaState.test(name)
148 ? this.each(function() {
149 this.removeAttributeNS(ariaNS, name.replace(ariaState, ""));
150 }) : removeAttr.call(this, name));
157 // Safari has a native remove event which actually removes DOM elements,
158 // so we have to use triggerHandler instead of trigger (#3037).
159 $("*", this).add(this).each(function() {
160 $(this).triggerHandler("remove");
162 return _remove.apply(this, arguments );
165 enableSelection: function() {
167 .attr('unselectable', 'off')
168 .css('MozUserSelect', '')
169 .unbind('selectstart.ui');
172 disableSelection: function() {
174 .attr('unselectable', 'on')
175 .css('MozUserSelect', 'none')
176 .bind('selectstart.ui', function() { return false; });
179 scrollParent: function() {
181 if(($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
182 scrollParent = this.parents().filter(function() {
183 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));
186 scrollParent = this.parents().filter(function() {
187 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
191 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
196 //Additional selectors
197 $.extend($.expr[':'], {
198 data: function(elem, i, match) {
199 return !!$.data(elem, match[3]);
202 focusable: function(element) {
203 var nodeName = element.nodeName.toLowerCase(),
204 tabIndex = $.attr(element, 'tabindex');
205 return (/input|select|textarea|button|object/.test(nodeName)
207 : 'a' == nodeName || 'area' == nodeName
208 ? element.href || !isNaN(tabIndex)
210 // the element and all of its ancestors must be visible
211 // the browser may report that the area is hidden
212 && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
215 tabbable: function(element) {
216 var tabIndex = $.attr(element, 'tabindex');
217 return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
222 // $.widget is a factory to create jQuery plugins
223 // taking some boilerplate code out of the plugin code
224 function getter(namespace, plugin, method, args) {
225 function getMethods(type) {
226 var methods = $[namespace][plugin][type] || [];
227 return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods);
230 var methods = getMethods('getter');
231 if (args.length == 1 && typeof args[0] == 'string') {
232 methods = methods.concat(getMethods('getterSetter'));
234 return ($.inArray(method, methods) != -1);
237 $.widget = function(name, prototype) {
238 var namespace = name.split(".")[0];
239 name = name.split(".")[1];
241 // create plugin method
242 $.fn[name] = function(options) {
243 var isMethodCall = (typeof options == 'string'),
244 args = Array.prototype.slice.call(arguments, 1);
246 // prevent calls to internal methods
247 if (isMethodCall && options.substring(0, 1) == '_') {
251 // handle getter methods
252 if (isMethodCall && getter(namespace, name, options, args)) {
253 var instance = $.data(this[0], name);
254 return (instance ? instance[options].apply(instance, args)
258 // handle initialization and non-getter methods
259 return this.each(function() {
260 var instance = $.data(this, name);
263 (!instance && !isMethodCall &&
264 $.data(this, name, new $[namespace][name](this, options))._init());
267 (instance && isMethodCall && $.isFunction(instance[options]) &&
268 instance[options].apply(instance, args));
272 // create widget constructor
273 $[namespace] = $[namespace] || {};
274 $[namespace][name] = function(element, options) {
277 this.namespace = namespace;
278 this.widgetName = name;
279 this.widgetEventPrefix = $[namespace][name].eventPrefix || name;
280 this.widgetBaseClass = namespace + '-' + name;
282 this.options = $.extend({},
284 $[namespace][name].defaults,
285 $.metadata && $.metadata.get(element)[name],
288 this.element = $(element)
289 .bind('setData.' + name, function(event, key, value) {
290 if (event.target == element) {
291 return self._setData(key, value);
294 .bind('getData.' + name, function(event, key) {
295 if (event.target == element) {
296 return self._getData(key);
299 .bind('remove', function() {
300 return self.destroy();
304 // add widget prototype
305 $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);
307 // TODO: merge getter and getterSetter properties from widget prototype
308 // and plugin prototype
309 $[namespace][name].getterSetter = 'option';
312 $.widget.prototype = {
313 _init: function() {},
314 destroy: function() {
315 this.element.removeData(this.widgetName)
316 .removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled')
317 .removeAttr('aria-disabled');
320 option: function(key, value) {
324 if (typeof key == "string") {
325 if (value === undefined) {
326 return this._getData(key);
329 options[key] = value;
332 $.each(options, function(key, value) {
333 self._setData(key, value);
336 _getData: function(key) {
337 return this.options[key];
339 _setData: function(key, value) {
340 this.options[key] = value;
342 if (key == 'disabled') {
344 [value ? 'addClass' : 'removeClass'](
345 this.widgetBaseClass + '-disabled' + ' ' +
346 this.namespace + '-state-disabled')
347 .attr("aria-disabled", value);
352 this._setData('disabled', false);
354 disable: function() {
355 this._setData('disabled', true);
358 _trigger: function(type, event, data) {
359 var callback = this.options[type],
360 eventName = (type == this.widgetEventPrefix
361 ? type : this.widgetEventPrefix + type);
363 event = $.Event(event);
364 event.type = eventName;
366 // copy original event properties over to the new event
367 // this would happen if we could call $.event.fix instead of $.Event
368 // but we don't have a way to force an event to be fixed multiple times
369 if (event.originalEvent) {
370 for (var i = $.event.props.length, prop; i;) {
371 prop = $.event.props[--i];
372 event[prop] = event.originalEvent[prop];
376 this.element.trigger(event, data);
378 return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false
379 || event.isDefaultPrevented());
383 $.widget.defaults = {
388 /** Mouse Interaction Plugin **/
391 _mouseInit: function() {
395 .bind('mousedown.'+this.widgetName, function(event) {
396 return self._mouseDown(event);
398 .bind('click.'+this.widgetName, function(event) {
399 if(self._preventClickEvent) {
400 self._preventClickEvent = false;
405 // Prevent text selection in IE
406 if ($.browser.msie) {
407 this._mouseUnselectable = this.element.attr('unselectable');
408 this.element.attr('unselectable', 'on');
411 this.started = false;
414 // TODO: make sure destroying one instance of mouse doesn't mess with
415 // other instances of mouse
416 _mouseDestroy: function() {
417 this.element.unbind('.'+this.widgetName);
419 // Restore text selection in IE
421 && this.element.attr('unselectable', this._mouseUnselectable));
424 _mouseDown: function(event) {
425 // don't let more than one widget handle mouseStart
426 if (event.originalEvent.mouseHandled) { return; }
428 // we may have missed mouseup (out of window)
429 (this._mouseStarted && this._mouseUp(event));
431 this._mouseDownEvent = event;
434 btnIsLeft = (event.which == 1),
435 elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
436 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
440 this.mouseDelayMet = !this.options.delay;
441 if (!this.mouseDelayMet) {
442 this._mouseDelayTimer = setTimeout(function() {
443 self.mouseDelayMet = true;
444 }, this.options.delay);
447 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
448 this._mouseStarted = (this._mouseStart(event) !== false);
449 if (!this._mouseStarted) {
450 event.preventDefault();
455 // these delegates are required to keep context
456 this._mouseMoveDelegate = function(event) {
457 return self._mouseMove(event);
459 this._mouseUpDelegate = function(event) {
460 return self._mouseUp(event);
463 .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
464 .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
466 // preventDefault() is used to prevent the selection of text here -
467 // however, in Safari, this causes select boxes not to be selectable
468 // anymore, so this fix is needed
469 ($.browser.safari || event.preventDefault());
471 event.originalEvent.mouseHandled = true;
475 _mouseMove: function(event) {
476 // IE mouseup check - mouseup happened when mouse was out of window
477 if ($.browser.msie && !event.button) {
478 return this._mouseUp(event);
481 if (this._mouseStarted) {
482 this._mouseDrag(event);
483 return event.preventDefault();
486 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
488 (this._mouseStart(this._mouseDownEvent, event) !== false);
489 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
492 return !this._mouseStarted;
495 _mouseUp: function(event) {
497 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
498 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
500 if (this._mouseStarted) {
501 this._mouseStarted = false;
502 this._preventClickEvent = true;
503 this._mouseStop(event);
509 _mouseDistanceMet: function(event) {
511 Math.abs(this._mouseDownEvent.pageX - event.pageX),
512 Math.abs(this._mouseDownEvent.pageY - event.pageY)
513 ) >= this.options.distance
517 _mouseDelayMet: function(event) {
518 return this.mouseDelayMet;
521 // These are placeholder methods, to be overriden by extending plugin
522 _mouseStart: function(event) {},
523 _mouseDrag: function(event) {},
524 _mouseStop: function(event) {},
525 _mouseCapture: function(event) { return true; }
528 $.ui.mouse.defaults = {
536 * jQuery UI Draggable 1.6rc6
538 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
539 * Dual licensed under the MIT (MIT-LICENSE.txt)
540 * and GPL (GPL-LICENSE.txt) licenses.
542 * http://docs.jquery.com/UI/Draggables
549 $.widget("ui.draggable", $.extend({}, $.ui.mouse, {
553 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
554 this.element[0].style.position = 'relative';
556 (this.options.cssNamespace && this.element.addClass(this.options.cssNamespace+"-draggable"));
557 (this.options.disabled && this.element.addClass(this.options.cssNamespace+'-draggable-disabled'));
563 destroy: function() {
564 if(!this.element.data('draggable')) return;
565 this.element.removeData("draggable").unbind(".draggable").removeClass(this.options.cssNamespace+'-draggable '+this.options.cssNamespace+'-draggable-dragging '+this.options.cssNamespace+'-draggable-disabled');
566 this._mouseDestroy();
569 _mouseCapture: function(event) {
571 var o = this.options;
573 if (this.helper || o.disabled || $(event.target).is('.'+this.options.cssNamespace+'-resizable-handle'))
576 //Quit if we're not on a valid handle
577 this.handle = this._getHandle(event);
585 _mouseStart: function(event) {
587 var o = this.options;
589 //Create and append the visible helper
590 this.helper = this._createHelper(event);
592 //Cache the helper size
593 this._cacheHelperProportions();
595 //If ddmanager is used for droppables, set the global draggable
597 $.ui.ddmanager.current = this;
600 * - Position generation -
601 * This block generates everything position related - it's the core of draggables.
604 //Cache the margins of the original element
605 this._cacheMargins();
607 //Store the helper's css position
608 this.cssPosition = this.helper.css("position");
609 this.scrollParent = this.helper.scrollParent();
611 //The element's absolute position on the page minus margins
612 this.offset = this.element.offset();
614 top: this.offset.top - this.margins.top,
615 left: this.offset.left - this.margins.left
618 $.extend(this.offset, {
619 click: { //Where the click happened, relative to the element
620 left: event.pageX - this.offset.left,
621 top: event.pageY - this.offset.top
623 parent: this._getParentOffset(),
624 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
627 //Generate the original position
628 this.originalPosition = this._generatePosition(event);
629 this.originalPageX = event.pageX;
630 this.originalPageY = event.pageY;
632 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
634 this._adjustOffsetFromHelper(o.cursorAt);
636 //Set a containment if given in the options
638 this._setContainment();
640 //Call plugins and callbacks
641 this._trigger("start", event);
643 //Recache the helper size
644 this._cacheHelperProportions();
646 //Prepare the droppable offsets
647 if ($.ui.ddmanager && !o.dropBehaviour)
648 $.ui.ddmanager.prepareOffsets(this, event);
650 this.helper.addClass(o.cssNamespace+"-draggable-dragging");
651 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
655 _mouseDrag: function(event, noPropagation) {
657 //Compute the helpers position
658 this.position = this._generatePosition(event);
659 this.positionAbs = this._convertPositionTo("absolute");
661 //Call plugins and callbacks and use the resulting position if something is returned
662 if (!noPropagation) {
663 var ui = this._uiHash();
664 this._trigger('drag', event, ui);
665 this.position = ui.position;
668 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
669 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
670 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
675 _mouseStop: function(event) {
677 //If we are using droppables, inform the manager about the drop
679 if ($.ui.ddmanager && !this.options.dropBehaviour)
680 dropped = $.ui.ddmanager.drop(this, event);
682 //if a drop comes from outside (a sortable)
684 dropped = this.dropped;
685 this.dropped = false;
688 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))) {
690 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
691 self._trigger("stop", event);
695 this._trigger("stop", event);
702 _getHandle: function(event) {
704 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
705 $(this.options.handle, this.element)
709 if(this == event.target) handle = true;
716 _createHelper: function(event) {
718 var o = this.options;
719 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
721 if(!helper.parents('body').length)
722 helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
724 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
725 helper.css("position", "absolute");
731 _adjustOffsetFromHelper: function(obj) {
732 if(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left;
733 if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
734 if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top;
735 if(obj.bottom != undefined) this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
738 _getParentOffset: function() {
740 //Get the offsetParent and cache its position
741 this.offsetParent = this.helper.offsetParent();
742 var po = this.offsetParent.offset();
744 // This is a special case where we need to modify a offset calculated on start, since the following happened:
745 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
746 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
747 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
748 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
749 po.left += this.scrollParent.scrollLeft();
750 po.top += this.scrollParent.scrollTop();
753 if((this.offsetParent[0] == document.body && $.browser.mozilla) //Ugly FF3 fix
754 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
755 po = { top: 0, left: 0 };
758 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
759 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
764 _getRelativeOffset: function() {
766 if(this.cssPosition == "relative") {
767 var p = this.element.position();
769 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
770 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
773 return { top: 0, left: 0 };
778 _cacheMargins: function() {
780 left: (parseInt(this.element.css("marginLeft"),10) || 0),
781 top: (parseInt(this.element.css("marginTop"),10) || 0)
785 _cacheHelperProportions: function() {
786 this.helperProportions = {
787 width: this.helper.outerWidth(),
788 height: this.helper.outerHeight()
792 _setContainment: function() {
794 var o = this.options;
795 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
796 if(o.containment == 'document' || o.containment == 'window') this.containment = [
797 0 - this.offset.relative.left - this.offset.parent.left,
798 0 - this.offset.relative.top - this.offset.parent.top,
799 $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
800 ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
803 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
804 var ce = $(o.containment)[0]; if(!ce) return;
805 var co = $(o.containment).offset();
806 var over = ($(ce).css("overflow") != 'hidden');
809 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
810 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
811 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,
812 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
814 } else if(o.containment.constructor == Array) {
815 this.containment = o.containment;
820 _convertPositionTo: function(d, pos) {
822 if(!pos) pos = this.position;
823 var mod = d == "absolute" ? 1 : -1;
824 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);
828 pos.top // The absolute mouse position
829 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
830 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
831 - ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod
834 pos.left // The absolute mouse position
835 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
836 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
837 - ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod
843 _generatePosition: function(event) {
845 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);
847 // This is another very weird special case that only happens for relative elements:
848 // 1. If the css position is relative
849 // 2. and the scroll parent is the document or similar to the offset parent
850 // we have to refresh the relative offset during the scroll so there are no jumps
851 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
852 this.offset.relative = this._getRelativeOffset();
855 var pageX = event.pageX;
856 var pageY = event.pageY;
859 * - Position constraining -
860 * Constrain the position to a mix of grid, containment.
863 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
865 if(this.containment) {
866 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
867 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
868 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
869 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
873 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
874 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;
876 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
877 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;
884 pageY // The absolute mouse position
885 - this.offset.click.top // Click offset (relative to the element)
886 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
887 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
888 + ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )
891 pageX // The absolute mouse position
892 - this.offset.click.left // Click offset (relative to the element)
893 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
894 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
895 + ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )
902 this.helper.removeClass(this.options.cssNamespace+"-draggable-dragging");
903 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
904 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
906 this.cancelHelperRemoval = false;
909 // From now on bulk stuff - mainly helpers
911 _trigger: function(type, event, ui) {
912 ui = ui || this._uiHash();
913 $.ui.plugin.call(this, type, [event, ui]);
914 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
915 return $.widget.prototype._trigger.call(this, type, event, ui);
920 _uiHash: function(event) {
923 position: this.position,
924 absolutePosition: this.positionAbs, //deprecated
925 offset: this.positionAbs
931 $.extend($.ui.draggable, {
937 cancel: ":input,option",
938 connectToSortable: false,
950 refreshPositions: false,
955 scrollSensitivity: 20,
965 $.ui.plugin.add("draggable", "connectToSortable", {
966 start: function(event, ui) {
968 var inst = $(this).data("draggable"), o = inst.options;
970 $(o.connectToSortable).each(function() {
971 // 'this' points to a string, and should therefore resolved as query, but instead, if the string is assigned to a variable, it loops through the strings properties,
972 // so we have to append '' to make it anonymous again
973 $(typeof this == 'string' ? this+'': this).each(function() {
974 if($.data(this, 'sortable')) {
975 var sortable = $.data(this, 'sortable');
976 inst.sortables.push({
978 shouldRevert: sortable.options.revert
980 sortable._refreshItems(); //Do a one-time refresh at start to refresh the containerCache
981 sortable._trigger("activate", event, inst);
987 stop: function(event, ui) {
989 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
990 var inst = $(this).data("draggable");
992 $.each(inst.sortables, function() {
993 if(this.instance.isOver) {
995 this.instance.isOver = 0;
997 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
998 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1000 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
1001 if(this.shouldRevert) this.instance.options.revert = true;
1003 //Trigger the stop of the sortable
1004 this.instance._mouseStop(event);
1006 this.instance.options.helper = this.instance.options._helper;
1008 //If the helper has been the original item, restore properties in the sortable
1009 if(inst.options.helper == 'original')
1010 this.instance.currentItem.css({ top: 'auto', left: 'auto' });
1013 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1014 this.instance._trigger("deactivate", event, inst);
1020 drag: function(event, ui) {
1022 var inst = $(this).data("draggable"), self = this;
1024 var checkPos = function(o) {
1025 var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
1026 var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
1027 var itemHeight = o.height, itemWidth = o.width;
1028 var itemTop = o.top, itemLeft = o.left;
1030 return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
1033 $.each(inst.sortables, function(i) {
1035 if(checkPos.call(inst, this.instance.containerCache)) {
1037 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1038 if(!this.instance.isOver) {
1039 this.instance.isOver = 1;
1040 //Now we fake the start of dragging for the sortable instance,
1041 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1042 //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)
1043 this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
1044 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1045 this.instance.options.helper = function() { return ui.helper[0]; };
1047 event.target = this.instance.currentItem[0];
1048 this.instance._mouseCapture(event, true);
1049 this.instance._mouseStart(event, true, true);
1051 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1052 this.instance.offset.click.top = inst.offset.click.top;
1053 this.instance.offset.click.left = inst.offset.click.left;
1054 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1055 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1057 inst._trigger("toSortable", event);
1058 inst.dropped = this.instance.element; //draggable revert needs that
1059 this.instance.fromOutside = inst; //Little hack so receive/update callbacks work
1063 //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
1064 if(this.instance.currentItem) this.instance._mouseDrag(event);
1068 //If it doesn't intersect with the sortable, and it intersected before,
1069 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1070 if(this.instance.isOver) {
1071 this.instance.isOver = 0;
1072 this.instance.cancelHelperRemoval = true;
1073 this.instance.options.revert = false; //No revert here
1074 this.instance._mouseStop(event, true);
1075 this.instance.options.helper = this.instance.options._helper;
1077 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1078 this.instance.currentItem.remove();
1079 if(this.instance.placeholder) this.instance.placeholder.remove();
1081 inst._trigger("fromSortable", event);
1082 inst.dropped = false; //draggable revert needs that
1092 $.ui.plugin.add("draggable", "cursor", {
1093 start: function(event, ui) {
1094 var t = $('body'), o = $(this).data('draggable').options;
1095 if (t.css("cursor")) o._cursor = t.css("cursor");
1096 t.css("cursor", o.cursor);
1098 stop: function(event, ui) {
1099 var o = $(this).data('draggable').options;
1100 if (o._cursor) $('body').css("cursor", o._cursor);
1104 $.ui.plugin.add("draggable", "iframeFix", {
1105 start: function(event, ui) {
1106 var o = $(this).data('draggable').options;
1107 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1108 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
1110 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
1111 position: "absolute", opacity: "0.001", zIndex: 1000
1113 .css($(this).offset())
1117 stop: function(event, ui) {
1118 $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
1122 $.ui.plugin.add("draggable", "opacity", {
1123 start: function(event, ui) {
1124 var t = $(ui.helper), o = $(this).data('draggable').options;
1125 if(t.css("opacity")) o._opacity = t.css("opacity");
1126 t.css('opacity', o.opacity);
1128 stop: function(event, ui) {
1129 var o = $(this).data('draggable').options;
1130 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
1134 $.ui.plugin.add("draggable", "scroll", {
1135 start: function(event, ui) {
1136 var i = $(this).data("draggable");
1137 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
1139 drag: function(event, ui) {
1141 var i = $(this).data("draggable"), o = i.options, scrolled = false;
1143 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
1145 if(!o.axis || o.axis != 'x') {
1146 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
1147 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1148 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
1149 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1152 if(!o.axis || o.axis != 'y') {
1153 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
1154 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1155 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
1156 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1161 if(!o.axis || o.axis != 'x') {
1162 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
1163 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1164 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
1165 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1168 if(!o.axis || o.axis != 'y') {
1169 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
1170 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1171 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
1172 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1177 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
1178 $.ui.ddmanager.prepareOffsets(i, event);
1183 $.ui.plugin.add("draggable", "snap", {
1184 start: function(event, ui) {
1186 var i = $(this).data("draggable"), o = i.options;
1187 i.snapElements = [];
1189 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
1190 var $t = $(this); var $o = $t.offset();
1191 if(this != i.element[0]) i.snapElements.push({
1193 width: $t.outerWidth(), height: $t.outerHeight(),
1194 top: $o.top, left: $o.left
1199 drag: function(event, ui) {
1201 var inst = $(this).data("draggable"), o = inst.options;
1202 var d = o.snapTolerance;
1204 var x1 = ui.absolutePosition.left, x2 = x1 + inst.helperProportions.width,
1205 y1 = ui.absolutePosition.top, y2 = y1 + inst.helperProportions.height;
1207 for (var i = inst.snapElements.length - 1; i >= 0; i--){
1209 var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
1210 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
1212 //Yes, I know, this is insane ;)
1213 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))) {
1214 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 })));
1215 inst.snapElements[i].snapping = false;
1219 if(o.snapMode != 'inner') {
1220 var ts = Math.abs(t - y2) <= d;
1221 var bs = Math.abs(b - y1) <= d;
1222 var ls = Math.abs(l - x2) <= d;
1223 var rs = Math.abs(r - x1) <= d;
1224 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1225 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1226 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1227 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1230 var first = (ts || bs || ls || rs);
1232 if(o.snapMode != 'outer') {
1233 var ts = Math.abs(t - y1) <= d;
1234 var bs = Math.abs(b - y2) <= d;
1235 var ls = Math.abs(l - x1) <= d;
1236 var rs = Math.abs(r - x2) <= d;
1237 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1238 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1239 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1240 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1243 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
1244 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1245 inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1252 $.ui.plugin.add("draggable", "stack", {
1253 start: function(event, ui) {
1255 var o = $(this).data("draggable").options;
1257 var group = $.makeArray($(o.stack.group)).sort(function(a,b) {
1258 return (parseInt($(a).css("zIndex"),10) || o.stack.min) - (parseInt($(b).css("zIndex"),10) || o.stack.min);
1261 $(group).each(function(i) {
1262 this.style.zIndex = o.stack.min + i;
1265 this[0].style.zIndex = o.stack.min + group.length;
1270 $.ui.plugin.add("draggable", "zIndex", {
1271 start: function(event, ui) {
1272 var t = $(ui.helper), o = $(this).data("draggable").options;
1273 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
1274 t.css('zIndex', o.zIndex);
1276 stop: function(event, ui) {
1277 var o = $(this).data("draggable").options;
1278 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
1284 * jQuery UI Droppable 1.6rc6
1286 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
1287 * Dual licensed under the MIT (MIT-LICENSE.txt)
1288 * and GPL (GPL-LICENSE.txt) licenses.
1290 * http://docs.jquery.com/UI/Droppables
1298 $.widget("ui.droppable", {
1302 var o = this.options, accept = o.accept;
1303 this.isover = 0; this.isout = 1;
1305 this.options.accept = this.options.accept && $.isFunction(this.options.accept) ? this.options.accept : function(d) {
1306 return d.is(accept);
1309 //Store the droppable's proportions
1310 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
1312 // Add the reference and positions to the manager
1313 $.ui.ddmanager.droppables[this.options.scope] = $.ui.ddmanager.droppables[this.options.scope] || [];
1314 $.ui.ddmanager.droppables[this.options.scope].push(this);
1316 (this.options.cssNamespace && this.element.addClass(this.options.cssNamespace+"-droppable"));
1320 destroy: function() {
1321 var drop = $.ui.ddmanager.droppables[this.options.scope];
1322 for ( var i = 0; i < drop.length; i++ )
1323 if ( drop[i] == this )
1327 .removeClass(this.options.cssNamespace+"-droppable "+this.options.cssNamespace+"-droppable-disabled")
1328 .removeData("droppable")
1329 .unbind(".droppable");
1332 _setData: function(key, value) {
1334 if(key == 'accept') {
1335 this.options.accept = value && $.isFunction(value) ? value : function(d) {
1336 return d.is(accept);
1339 $.widget.prototype._setData.apply(this, arguments);
1344 _activate: function(event) {
1345 var draggable = $.ui.ddmanager.current;
1346 if(this.options.activeClass) this.element.addClass(this.options.activeClass);
1347 (draggable && this._trigger('activate', event, this.ui(draggable)));
1350 _deactivate: function(event) {
1351 var draggable = $.ui.ddmanager.current;
1352 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1353 (draggable && this._trigger('deactivate', event, this.ui(draggable)));
1356 _over: function(event) {
1358 var draggable = $.ui.ddmanager.current;
1359 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1361 if (this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1362 if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
1363 this._trigger('over', event, this.ui(draggable));
1368 _out: function(event) {
1370 var draggable = $.ui.ddmanager.current;
1371 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1373 if (this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1374 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1375 this._trigger('out', event, this.ui(draggable));
1380 _drop: function(event,custom) {
1382 var draggable = custom || $.ui.ddmanager.current;
1383 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
1385 var childrenIntersection = false;
1386 this.element.find(":data(droppable)").not("."+draggable.options.cssNamespace+"-draggable-dragging").each(function() {
1387 var inst = $.data(this, 'droppable');
1388 if(inst.options.greedy && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)) {
1389 childrenIntersection = true; return false;
1392 if(childrenIntersection) return false;
1394 if(this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1395 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1396 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1397 this._trigger('drop', event, this.ui(draggable));
1398 return this.element;
1407 draggable: (c.currentItem || c.element),
1409 position: c.position,
1410 absolutePosition: c.positionAbs, //deprecated
1411 offset: c.positionAbs
1417 $.extend($.ui.droppable, {
1419 eventPrefix: 'drop',
1427 tolerance: 'intersect'
1431 $.ui.intersect = function(draggable, droppable, toleranceMode) {
1433 if (!droppable.offset) return false;
1435 var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
1436 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
1437 var l = droppable.offset.left, r = l + droppable.proportions.width,
1438 t = droppable.offset.top, b = t + droppable.proportions.height;
1440 switch (toleranceMode) {
1442 return (l < x1 && x2 < r
1443 && t < y1 && y2 < b);
1446 return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
1447 && x2 - (draggable.helperProportions.width / 2) < r // Left Half
1448 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
1449 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
1452 var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
1453 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
1454 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
1459 (y1 >= t && y1 <= b) || // Top edge touching
1460 (y2 >= t && y2 <= b) || // Bottom edge touching
1461 (y1 < t && y2 > b) // Surrounded vertically
1463 (x1 >= l && x1 <= r) || // Left edge touching
1464 (x2 >= l && x2 <= r) || // Right edge touching
1465 (x1 < l && x2 > r) // Surrounded horizontally
1476 This manager tracks offsets of draggables and droppables
1480 droppables: { 'default': [] },
1481 prepareOffsets: function(t, event) {
1483 var m = $.ui.ddmanager.droppables[t.options.scope];
1484 var type = event ? event.type : null; // workaround for #2317
1485 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
1487 droppablesLoop: for (var i = 0; i < m.length; i++) {
1489 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
1490 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
1491 m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue
1493 m[i].offset = m[i].element.offset();
1494 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
1496 if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
1501 drop: function(draggable, event) {
1503 var dropped = false;
1504 $.each($.ui.ddmanager.droppables[draggable.options.scope], function() {
1506 if(!this.options) return;
1507 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
1508 dropped = this._drop.call(this, event);
1510 if (!this.options.disabled && this.visible && this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1511 this.isout = 1; this.isover = 0;
1512 this._deactivate.call(this, event);
1519 drag: function(draggable, event) {
1521 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
1522 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
1524 //Run through all droppables and check their positions based on specific tolerance options
1526 $.each($.ui.ddmanager.droppables[draggable.options.scope], function() {
1528 if(this.options.disabled || this.greedyChild || !this.visible) return;
1529 var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
1531 var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
1535 if (this.options.greedy) {
1536 var parent = this.element.parents(':data(droppable):eq(0)');
1537 if (parent.length) {
1538 parentInstance = $.data(parent[0], 'droppable');
1539 parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
1543 // we just moved into a greedy child
1544 if (parentInstance && c == 'isover') {
1545 parentInstance['isover'] = 0;
1546 parentInstance['isout'] = 1;
1547 parentInstance._out.call(parentInstance, event);
1550 this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
1551 this[c == "isover" ? "_over" : "_out"].call(this, event);
1553 // we just moved out of a greedy child
1554 if (parentInstance && c == 'isout') {
1555 parentInstance['isout'] = 0;
1556 parentInstance['isover'] = 1;
1557 parentInstance._over.call(parentInstance, event);
1566 * jQuery UI Resizable 1.6rc6
1568 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
1569 * Dual licensed under the MIT (MIT-LICENSE.txt)
1570 * and GPL (GPL-LICENSE.txt) licenses.
1572 * http://docs.jquery.com/UI/Resizables
1579 $.widget("ui.resizable", $.extend({}, $.ui.mouse, {
1583 var self = this, o = this.options;
1584 this.element.addClass("ui-resizable");
1587 _aspectRatio: !!(o.aspectRatio),
1588 aspectRatio: o.aspectRatio,
1589 originalElement: this.element,
1590 proportionallyResize: o.proportionallyResize ? [o.proportionallyResize] : [],
1591 _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
1594 //Wrap the element if it cannot hold child nodes
1595 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
1597 //Opera fix for relative positioning
1598 if (/relative/.test(this.element.css('position')) && $.browser.opera)
1599 this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
1601 //Create a wrapper element and set the wrapper to the new current internal element
1603 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
1604 position: this.element.css('position'),
1605 width: this.element.outerWidth(),
1606 height: this.element.outerHeight(),
1607 top: this.element.css('top'),
1608 left: this.element.css('left')
1612 //Overwrite the original this.element
1613 this.element = this.element.parent();
1614 this.elementIsWrapper = true;
1616 //Move margins to the wrapper
1617 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
1618 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
1620 //Prevent Safari textarea resize
1621 if ($.browser.safari && o.preventDefault) this.originalElement.css('resize', 'none');
1623 //Push the actual element to our proportionallyResize internal array
1624 this.proportionallyResize.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
1626 // avoid IE jump (hard set the margin)
1627 this.originalElement.css({ margin: this.originalElement.css('margin') });
1629 // fix handlers offset
1630 this._proportionallyResize();
1634 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' });
1635 if(this.handles.constructor == String) {
1637 if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
1638 var n = this.handles.split(","); this.handles = {};
1640 for(var i = 0; i < n.length; i++) {
1642 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
1643 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
1645 // increase zIndex of sw, se, ne, nw axis
1646 //TODO : this modifies original option
1647 if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
1649 //TODO : What's going on here?
1650 if ('se' == handle) {
1651 axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
1654 //Insert into internal handles object and append to element
1655 this.handles[handle] = '.ui-resizable-'+handle;
1656 this.element.append(axis);
1661 this._renderAxis = function(target) {
1663 target = target || this.element;
1665 for(var i in this.handles) {
1667 if(this.handles[i].constructor == String)
1668 this.handles[i] = $(this.handles[i], this.element).show();
1671 this.handles[i].css({ opacity: 0 });
1673 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
1674 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
1676 var axis = $(this.handles[i], this.element), padWrapper = 0;
1678 //Checking the correct pad and border
1679 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
1681 //The padding type i have to apply...
1682 var padPos = [ 'padding',
1683 /ne|nw|n/.test(i) ? 'Top' :
1684 /se|sw|s/.test(i) ? 'Bottom' :
1685 /^e$/.test(i) ? 'Right' : 'Left' ].join("");
1688 target.css(padPos, padWrapper);
1690 this._proportionallyResize();
1694 //TODO: What's that good for? There's not anything to be executed left
1695 if(!$(this.handles[i]).length)
1701 //TODO: make renderAxis a prototype function
1702 this._renderAxis(this.element);
1704 this._handles = $('.ui-resizable-handle', this.element);
1706 if (o.disableSelection)
1707 this._handles.disableSelection();
1709 //Matching axis name
1710 this._handles.mouseover(function() {
1711 if (!self.resizing) {
1713 var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
1714 //Axis, default = se
1715 self.axis = axis && axis[1] ? axis[1] : 'se';
1719 //If we want to auto hide the elements
1721 this._handles.hide();
1723 .addClass("ui-resizable-autohide")
1725 $(this).removeClass("ui-resizable-autohide");
1726 self._handles.show();
1729 if (!self.resizing) {
1730 $(this).addClass("ui-resizable-autohide");
1731 self._handles.hide();
1736 //Initialize the mouse interaction
1741 destroy: function() {
1743 this._mouseDestroy();
1745 var _destroy = function(exp) {
1746 $(exp).removeClass("ui-resizable ui-resizable-disabled")
1747 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
1750 //TODO: Unwrap at same DOM position
1751 if (this.elementIsWrapper) {
1752 _destroy(this.element);
1753 this.wrapper.parent().append(
1754 this.originalElement.css({
1755 position: this.wrapper.css('position'),
1756 width: this.wrapper.outerWidth(),
1757 height: this.wrapper.outerHeight(),
1758 top: this.wrapper.css('top'),
1759 left: this.wrapper.css('left')
1764 _destroy(this.originalElement);
1768 _mouseCapture: function(event) {
1771 for(var i in this.handles) {
1772 if($(this.handles[i])[0] == event.target) handle = true;
1775 return this.options.disabled || !!handle;
1779 _mouseStart: function(event) {
1781 var o = this.options, iniPos = this.element.position(), el = this.element;
1783 this.resizing = true;
1784 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
1786 // bugfix for http://dev.jquery.com/ticket/1749
1787 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
1788 el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
1791 //Opera fixing relative position
1792 if ($.browser.opera && (/relative/).test(el.css('position')))
1793 el.css({ position: 'relative', top: 'auto', left: 'auto' });
1795 this._renderProxy();
1797 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
1799 if (o.containment) {
1800 curleft += $(o.containment).scrollLeft() || 0;
1801 curtop += $(o.containment).scrollTop() || 0;
1804 //Store needed variables
1805 this.offset = this.helper.offset();
1806 this.position = { left: curleft, top: curtop };
1807 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
1808 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
1809 this.originalPosition = { left: curleft, top: curtop };
1810 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
1811 this.originalMousePosition = { left: event.pageX, top: event.pageY };
1814 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
1816 if (o.preserveCursor) {
1817 var cursor = $('.ui-resizable-' + this.axis).css('cursor');
1818 $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
1821 this._propagate("start", event);
1825 _mouseDrag: function(event) {
1827 //Increase performance, avoid regex
1828 var el = this.helper, o = this.options, props = {},
1829 self = this, smp = this.originalMousePosition, a = this.axis;
1831 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
1832 var trigger = this._change[a];
1833 if (!trigger) return false;
1835 // Calculate the attrs that will be change
1836 var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
1838 if (this._aspectRatio || event.shiftKey)
1839 data = this._updateRatio(data, event);
1841 data = this._respectSize(data, event);
1843 // plugins callbacks need to be called first
1844 this._propagate("resize", event);
1847 top: this.position.top + "px", left: this.position.left + "px",
1848 width: this.size.width + "px", height: this.size.height + "px"
1851 if (!this._helper && this.proportionallyResize.length)
1852 this._proportionallyResize();
1854 this._updateCache(data);
1856 // calling the user callback at the end
1857 this._trigger('resize', event, this.ui());
1862 _mouseStop: function(event) {
1864 this.resizing = false;
1865 var o = this.options, self = this;
1868 var pr = this.proportionallyResize, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
1869 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
1870 soffsetw = ista ? 0 : self.sizeDiff.width;
1872 var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
1873 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
1874 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
1877 this.element.css($.extend(s, { top: top, left: left }));
1879 if (this._helper && !o.animate) this._proportionallyResize();
1882 if (o.preserveCursor)
1883 $('body').css('cursor', 'auto');
1885 this._propagate("stop", event);
1887 if (this._helper) this.helper.remove();
1892 _updateCache: function(data) {
1893 var o = this.options;
1894 this.offset = this.helper.offset();
1895 if (data.left) this.position.left = data.left;
1896 if (data.top) this.position.top = data.top;
1897 if (data.height) this.size.height = data.height;
1898 if (data.width) this.size.width = data.width;
1901 _updateRatio: function(data, event) {
1903 var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
1905 if (data.height) data.width = (csize.height * this.aspectRatio);
1906 else if (data.width) data.height = (csize.width / this.aspectRatio);
1909 data.left = cpos.left + (csize.width - data.width);
1913 data.top = cpos.top + (csize.height - data.height);
1914 data.left = cpos.left + (csize.width - data.width);
1920 _respectSize: function(data, event) {
1922 var isNumber = function(value) {
1923 return !isNaN(parseInt(value, 10))
1926 var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
1927 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
1928 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
1930 if (isminw) data.width = o.minWidth;
1931 if (isminh) data.height = o.minHeight;
1932 if (ismaxw) data.width = o.maxWidth;
1933 if (ismaxh) data.height = o.maxHeight;
1935 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
1936 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
1938 if (isminw && cw) data.left = dw - o.minWidth;
1939 if (ismaxw && cw) data.left = dw - o.maxWidth;
1940 if (isminh && ch) data.top = dh - o.minHeight;
1941 if (ismaxh && ch) data.top = dh - o.maxHeight;
1943 // fixing jump error on top/left - bug #2330
1944 var isNotwh = !data.width && !data.height;
1945 if (isNotwh && !data.left && data.top) data.top = null;
1946 else if (isNotwh && !data.top && data.left) data.left = null;
1951 _proportionallyResize: function() {
1953 var o = this.options;
1954 if (!this.proportionallyResize.length) return;
1955 var element = this.helper || this.element;
1957 for (var i=0; i < this.proportionallyResize.length; i++) {
1959 var prel = this.proportionallyResize[i];
1961 if (!this.borderDif) {
1962 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
1963 p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
1965 this.borderDif = $.map(b, function(v, i) {
1966 var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
1967 return border + padding;
1971 if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
1975 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
1976 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
1983 _renderProxy: function() {
1985 var el = this.element, o = this.options;
1986 this.elementOffset = el.offset();
1990 this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
1992 // fix ie6 offset TODO: This seems broken
1993 var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
1994 pxyoffset = ( ie6 ? 2 : -1 );
1996 this.helper.addClass(this._helper).css({
1997 width: this.element.outerWidth() + pxyoffset,
1998 height: this.element.outerHeight() + pxyoffset,
1999 position: 'absolute',
2000 left: this.elementOffset.left - ie6offset +'px',
2001 top: this.elementOffset.top - ie6offset +'px',
2002 zIndex: ++o.zIndex //TODO: Don't modify option
2005 this.helper.appendTo("body");
2007 if (o.disableSelection)
2008 this.helper.disableSelection();
2011 this.helper = this.element;
2017 e: function(event, dx, dy) {
2018 return { width: this.originalSize.width + dx };
2020 w: function(event, dx, dy) {
2021 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2022 return { left: sp.left + dx, width: cs.width - dx };
2024 n: function(event, dx, dy) {
2025 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2026 return { top: sp.top + dy, height: cs.height - dy };
2028 s: function(event, dx, dy) {
2029 return { height: this.originalSize.height + dy };
2031 se: function(event, dx, dy) {
2032 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2034 sw: function(event, dx, dy) {
2035 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2037 ne: function(event, dx, dy) {
2038 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2040 nw: function(event, dx, dy) {
2041 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2045 _propagate: function(n, event) {
2046 $.ui.plugin.call(this, n, [event, this.ui()]);
2047 (n != "resize" && this._trigger(n, event, this.ui()));
2054 originalElement: this.originalElement,
2055 element: this.element,
2056 helper: this.helper,
2057 position: this.position,
2059 originalSize: this.originalSize,
2060 originalPosition: this.originalPosition
2066 $.extend($.ui.resizable, {
2068 eventPrefix: "resize",
2072 animateDuration: "slow",
2073 animateEasing: "swing",
2076 cancel: ":input,option",
2079 disableSelection: true,
2089 preserveCursor: true,
2090 preventDefault: true,
2091 proportionallyResize: false,
2098 * Resizable Extensions
2101 $.ui.plugin.add("resizable", "alsoResize", {
2103 start: function(event, ui) {
2105 var self = $(this).data("resizable"), o = self.options;
2107 _store = function(exp) {
2108 $(exp).each(function() {
2109 $(this).data("resizable-alsoresize", {
2110 width: parseInt($(this).width(), 10), height: parseInt($(this).height(), 10),
2111 left: parseInt($(this).css('left'), 10), top: parseInt($(this).css('top'), 10)
2116 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
2117 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
2118 else { $.each(o.alsoResize, function(exp, c) { _store(exp); }); }
2120 _store(o.alsoResize);
2124 resize: function(event, ui){
2125 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
2128 height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
2129 top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
2132 _alsoResize = function(exp, c) {
2133 $(exp).each(function() {
2134 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, css = c && c.length ? c : ['width', 'height', 'top', 'left'];
2136 $.each(css || ['width', 'height', 'top', 'left'], function(i, prop) {
2137 var sum = (start[prop]||0) + (delta[prop]||0);
2138 if (sum && sum >= 0)
2139 style[prop] = sum || null;
2142 //Opera fixing relative position
2143 if (/relative/.test(el.css('position')) && $.browser.opera) {
2144 self._revertToRelativePosition = true;
2145 el.css({ position: 'absolute', top: 'auto', left: 'auto' });
2152 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2153 $.each(o.alsoResize, function(exp, c) { _alsoResize(exp, c); });
2155 _alsoResize(o.alsoResize);
2159 stop: function(event, ui){
2160 var self = $(this).data("resizable");
2162 //Opera fixing relative position
2163 if (self._revertToRelativePosition && $.browser.opera) {
2164 self._revertToRelativePosition = false;
2165 el.css({ position: 'relative' });
2168 $(this).removeData("resizable-alsoresize-start");
2172 $.ui.plugin.add("resizable", "animate", {
2174 stop: function(event, ui) {
2175 var self = $(this).data("resizable"), o = self.options;
2177 var pr = o.proportionallyResize, ista = pr && (/textarea/i).test(pr.get(0).nodeName),
2178 soffseth = ista && $.ui.hasScroll(pr.get(0), 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2179 soffsetw = ista ? 0 : self.sizeDiff.width;
2181 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
2182 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2183 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2185 self.element.animate(
2186 $.extend(style, top && left ? { top: top, left: left } : {}), {
2187 duration: o.animateDuration,
2188 easing: o.animateEasing,
2192 width: parseInt(self.element.css('width'), 10),
2193 height: parseInt(self.element.css('height'), 10),
2194 top: parseInt(self.element.css('top'), 10),
2195 left: parseInt(self.element.css('left'), 10)
2198 if (pr) pr.css({ width: data.width, height: data.height });
2200 // propagating resize, and updating values for each animation step
2201 self._updateCache(data);
2202 self._propagate("resize", event);
2211 $.ui.plugin.add("resizable", "containment", {
2213 start: function(event, ui) {
2214 var self = $(this).data("resizable"), o = self.options, el = self.element;
2215 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
2218 self.containerElement = $(ce);
2220 if (/document/.test(oc) || oc == document) {
2221 self.containerOffset = { left: 0, top: 0 };
2222 self.containerPosition = { left: 0, top: 0 };
2225 element: $(document), left: 0, top: 0,
2226 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
2230 // i'm a node, so compute top, left, right, bottom
2232 var element = $(ce), p = [];
2233 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
2235 self.containerOffset = element.offset();
2236 self.containerPosition = element.position();
2237 self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
2239 var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width,
2240 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
2243 element: ce, left: co.left, top: co.top, width: width, height: height
2248 resize: function(event, ui) {
2249 var self = $(this).data("resizable"), o = self.options,
2250 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
2251 pRatio = o._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
2253 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
2255 if (cp.left < (self._helper ? co.left : 0)) {
2256 self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
2257 if (pRatio) self.size.height = self.size.width / o.aspectRatio;
2258 self.position.left = o.helper ? co.left : 0;
2261 if (cp.top < (self._helper ? co.top : 0)) {
2262 self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
2263 if (pRatio) self.size.width = self.size.height * o.aspectRatio;
2264 self.position.top = self._helper ? co.top : 0;
2267 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
2268 hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
2270 if (woset + self.size.width >= self.parentData.width) {
2271 self.size.width = self.parentData.width - woset;
2272 if (pRatio) self.size.height = self.size.width / o.aspectRatio;
2275 if (hoset + self.size.height >= self.parentData.height) {
2276 self.size.height = self.parentData.height - hoset;
2277 if (pRatio) self.size.width = self.size.height * o.aspectRatio;
2281 stop: function(event, ui){
2282 var self = $(this).data("resizable"), o = self.options, cp = self.position,
2283 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
2285 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
2287 if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
2288 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2290 if (self._helper && !o.animate && (/static/).test(ce.css('position')))
2291 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2296 $.ui.plugin.add("resizable", "ghost", {
2298 start: function(event, ui) {
2300 var self = $(this).data("resizable"), o = self.options, pr = o.proportionallyResize, cs = self.size;
2302 self.ghost = self.originalElement.clone();
2304 .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
2305 .addClass('ui-resizable-ghost')
2306 .addClass(typeof o.ghost == 'string' ? o.ghost : '');
2308 self.ghost.appendTo(self.helper);
2312 resize: function(event, ui){
2313 var self = $(this).data("resizable"), o = self.options;
2314 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
2317 stop: function(event, ui){
2318 var self = $(this).data("resizable"), o = self.options;
2319 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
2324 $.ui.plugin.add("resizable", "grid", {
2326 resize: function(event, ui) {
2327 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;
2328 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
2329 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);
2331 if (/^(se|s|e)$/.test(a)) {
2332 self.size.width = os.width + ox;
2333 self.size.height = os.height + oy;
2335 else if (/^(ne)$/.test(a)) {
2336 self.size.width = os.width + ox;
2337 self.size.height = os.height + oy;
2338 self.position.top = op.top - oy;
2340 else if (/^(sw)$/.test(a)) {
2341 self.size.width = os.width + ox;
2342 self.size.height = os.height + oy;
2343 self.position.left = op.left - ox;
2346 self.size.width = os.width + ox;
2347 self.size.height = os.height + oy;
2348 self.position.top = op.top - oy;
2349 self.position.left = op.left - ox;
2355 var num = function(v) {
2356 return parseInt(v, 10) || 0;
2361 * jQuery UI Selectable 1.6rc6
2363 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
2364 * Dual licensed under the MIT (MIT-LICENSE.txt)
2365 * and GPL (GPL-LICENSE.txt) licenses.
2367 * http://docs.jquery.com/UI/Selectables
2374 $.widget("ui.selectable", $.extend({}, $.ui.mouse, {
2379 this.element.addClass("ui-selectable");
2381 this.dragged = false;
2383 // cache selectee children based on filter
2385 this.refresh = function() {
2386 selectees = $(self.options.filter, self.element[0]);
2387 selectees.each(function() {
2388 var $this = $(this);
2389 var pos = $this.offset();
2390 $.data(this, "selectable-item", {
2395 right: pos.left + $this.outerWidth(),
2396 bottom: pos.top + $this.outerHeight(),
2397 startselected: false,
2398 selected: $this.hasClass('ui-selected'),
2399 selecting: $this.hasClass('ui-selecting'),
2400 unselecting: $this.hasClass('ui-unselecting')
2406 this.selectees = selectees.addClass("ui-selectee");
2410 this.helper = $(document.createElement('div'))
2411 .css({border:'1px dotted black'})
2412 .addClass("ui-selectable-helper");
2415 destroy: function() {
2417 .removeClass("ui-selectable ui-selectable-disabled")
2418 .removeData("selectable")
2419 .unbind(".selectable");
2420 this._mouseDestroy();
2423 _mouseStart: function(event) {
2426 this.opos = [event.pageX, event.pageY];
2428 if (this.options.disabled)
2431 var options = this.options;
2433 this.selectees = $(options.filter, this.element[0]);
2435 this._trigger("start", event);
2437 $('body').append(this.helper);
2438 // position helper (lasso)
2441 "position": "absolute",
2442 "left": event.clientX,
2443 "top": event.clientY,
2448 if (options.autoRefresh) {
2452 this.selectees.filter('.ui-selected').each(function() {
2453 var selectee = $.data(this, "selectable-item");
2454 selectee.startselected = true;
2455 if (!event.metaKey) {
2456 selectee.$element.removeClass('ui-selected');
2457 selectee.selected = false;
2458 selectee.$element.addClass('ui-unselecting');
2459 selectee.unselecting = true;
2460 // selectable UNSELECTING callback
2461 self._trigger("unselecting", event, {
2462 unselecting: selectee.element
2467 $(event.target).parents().andSelf().each(function() {
2468 var selectee = $.data(this, "selectable-item");
2470 selectee.$element.removeClass("ui-unselecting").addClass('ui-selecting');
2471 selectee.unselecting = false;
2472 selectee.selecting = true;
2473 selectee.selected = true;
2474 // selectable SELECTING callback
2475 self._trigger("selecting", event, {
2476 selecting: selectee.element
2484 _mouseDrag: function(event) {
2486 this.dragged = true;
2488 if (this.options.disabled)
2491 var options = this.options;
2493 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
2494 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
2495 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
2496 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
2498 this.selectees.each(function() {
2499 var selectee = $.data(this, "selectable-item");
2500 //prevent helper from being selected if appendTo: selectable
2501 if (!selectee || selectee.element == self.element[0])
2504 if (options.tolerance == 'touch') {
2505 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
2506 } else if (options.tolerance == 'fit') {
2507 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
2512 if (selectee.selected) {
2513 selectee.$element.removeClass('ui-selected');
2514 selectee.selected = false;
2516 if (selectee.unselecting) {
2517 selectee.$element.removeClass('ui-unselecting');
2518 selectee.unselecting = false;
2520 if (!selectee.selecting) {
2521 selectee.$element.addClass('ui-selecting');
2522 selectee.selecting = true;
2523 // selectable SELECTING callback
2524 self._trigger("selecting", event, {
2525 selecting: selectee.element
2530 if (selectee.selecting) {
2531 if (event.metaKey && selectee.startselected) {
2532 selectee.$element.removeClass('ui-selecting');
2533 selectee.selecting = false;
2534 selectee.$element.addClass('ui-selected');
2535 selectee.selected = true;
2537 selectee.$element.removeClass('ui-selecting');
2538 selectee.selecting = false;
2539 if (selectee.startselected) {
2540 selectee.$element.addClass('ui-unselecting');
2541 selectee.unselecting = true;
2543 // selectable UNSELECTING callback
2544 self._trigger("unselecting", event, {
2545 unselecting: selectee.element
2549 if (selectee.selected) {
2550 if (!event.metaKey && !selectee.startselected) {
2551 selectee.$element.removeClass('ui-selected');
2552 selectee.selected = false;
2554 selectee.$element.addClass('ui-unselecting');
2555 selectee.unselecting = true;
2556 // selectable UNSELECTING callback
2557 self._trigger("unselecting", event, {
2558 unselecting: selectee.element
2568 _mouseStop: function(event) {
2571 this.dragged = false;
2573 var options = this.options;
2575 $('.ui-unselecting', this.element[0]).each(function() {
2576 var selectee = $.data(this, "selectable-item");
2577 selectee.$element.removeClass('ui-unselecting');
2578 selectee.unselecting = false;
2579 selectee.startselected = false;
2580 self._trigger("unselected", event, {
2581 unselected: selectee.element
2584 $('.ui-selecting', this.element[0]).each(function() {
2585 var selectee = $.data(this, "selectable-item");
2586 selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
2587 selectee.selecting = false;
2588 selectee.selected = true;
2589 selectee.startselected = true;
2590 self._trigger("selected", event, {
2591 selected: selectee.element
2594 this._trigger("stop", event);
2596 this.helper.remove();
2603 $.extend($.ui.selectable, {
2608 cancel: ":input,option",
2618 * jQuery UI Sortable 1.6rc6
2620 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
2621 * Dual licensed under the MIT (MIT-LICENSE.txt)
2622 * and GPL (GPL-LICENSE.txt) licenses.
2624 * http://docs.jquery.com/UI/Sortables
2631 $.widget("ui.sortable", $.extend({}, $.ui.mouse, {
2634 var o = this.options;
2635 this.containerCache = {};
2636 (this.options.cssNamespace && this.element.addClass(this.options.cssNamespace+"-sortable"));
2641 //Let's determine if the items are floating
2642 this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
2644 //Let's determine the parent's offset
2645 this.offset = this.element.offset();
2647 //Initialize mouse events for interaction
2652 destroy: function() {
2654 .removeClass(this.options.cssNamespace+"-sortable "+this.options.cssNamespace+"-sortable-disabled")
2655 .removeData("sortable")
2656 .unbind(".sortable");
2657 this._mouseDestroy();
2659 for ( var i = this.items.length - 1; i >= 0; i-- )
2660 this.items[i].item.removeData("sortable-item");
2663 _mouseCapture: function(event, overrideHandle) {
2665 if (this.reverting) {
2669 if(this.options.disabled || this.options.type == 'static') return false;
2671 //We have to refresh the items data once first
2672 this._refreshItems(event);
2674 //Find out if the clicked node (or one of its parents) is a actual item in this.items
2675 var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
2676 if($.data(this, 'sortable-item') == self) {
2677 currentItem = $(this);
2681 if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
2683 if(!currentItem) return false;
2684 if(this.options.handle && !overrideHandle) {
2685 var validHandle = false;
2687 $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
2688 if(!validHandle) return false;
2691 this.currentItem = currentItem;
2692 this._removeCurrentsFromItems();
2697 _mouseStart: function(event, overrideHandle, noActivation) {
2699 var o = this.options, self = this;
2700 this.currentContainer = this;
2702 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
2703 this.refreshPositions();
2705 //Create and append the visible helper
2706 this.helper = this._createHelper(event);
2708 //Cache the helper size
2709 this._cacheHelperProportions();
2712 * - Position generation -
2713 * This block generates everything position related - it's the core of draggables.
2716 //Cache the margins of the original element
2717 this._cacheMargins();
2719 //Get the next scrolling parent
2720 this.scrollParent = this.helper.scrollParent();
2722 //The element's absolute position on the page minus margins
2723 this.offset = this.currentItem.offset();
2725 top: this.offset.top - this.margins.top,
2726 left: this.offset.left - this.margins.left
2729 // Only after we got the offset, we can change the helper's position to absolute
2730 // TODO: Still need to figure out a way to make relative sorting possible
2731 this.helper.css("position", "absolute");
2732 this.cssPosition = this.helper.css("position");
2734 $.extend(this.offset, {
2735 click: { //Where the click happened, relative to the element
2736 left: event.pageX - this.offset.left,
2737 top: event.pageY - this.offset.top
2739 parent: this._getParentOffset(),
2740 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
2743 //Generate the original position
2744 this.originalPosition = this._generatePosition(event);
2745 this.originalPageX = event.pageX;
2746 this.originalPageY = event.pageY;
2748 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
2750 this._adjustOffsetFromHelper(o.cursorAt);
2752 //Cache the former DOM position
2753 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
2755 //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
2756 if(this.helper[0] != this.currentItem[0]) {
2757 this.currentItem.hide();
2760 //Create the placeholder
2761 this._createPlaceholder();
2763 //Set a containment if given in the options
2765 this._setContainment();
2767 if(o.cursor) { // cursor option
2768 if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
2769 $('body').css("cursor", o.cursor);
2772 if(o.opacity) { // opacity option
2773 if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
2774 this.helper.css("opacity", o.opacity);
2777 if(o.zIndex) { // zIndex option
2778 if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
2779 this.helper.css("zIndex", o.zIndex);
2783 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
2784 this.overflowOffset = this.scrollParent.offset();
2787 this._trigger("start", event, this._uiHash());
2789 //Recache the helper size
2790 if(!this._preserveHelperProportions)
2791 this._cacheHelperProportions();
2794 //Post 'activate' events to possible containers
2796 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
2799 //Prepare possible droppables
2801 $.ui.ddmanager.current = this;
2803 if ($.ui.ddmanager && !o.dropBehaviour)
2804 $.ui.ddmanager.prepareOffsets(this, event);
2806 this.dragging = true;
2808 this.helper.addClass(o.cssNamespace+'-sortable-helper');
2809 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
2814 _mouseDrag: function(event) {
2816 //Compute the helpers position
2817 this.position = this._generatePosition(event);
2818 this.positionAbs = this._convertPositionTo("absolute");
2820 if (!this.lastPositionAbs) {
2821 this.lastPositionAbs = this.positionAbs;
2825 if(this.options.scroll) {
2826 var o = this.options, scrolled = false;
2827 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
2829 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
2830 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
2831 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
2832 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
2834 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
2835 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
2836 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
2837 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
2841 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
2842 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
2843 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
2844 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
2846 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
2847 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
2848 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
2849 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
2853 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
2854 $.ui.ddmanager.prepareOffsets(this, event);
2857 //Regenerate the absolute position used for position checks
2858 this.positionAbs = this._convertPositionTo("absolute");
2860 //Set the helper position
2861 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
2862 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
2865 for (var i = this.items.length - 1; i >= 0; i--) {
2867 //Cache variables and intersection, continue if no intersection
2868 var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
2869 if (!intersection) continue;
2871 if(itemElement != this.currentItem[0] //cannot intersect with itself
2872 && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
2873 && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
2874 && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
2877 this.direction = intersection == 1 ? "down" : "up";
2879 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
2880 this.options.sortIndicator.call(this, event, item);
2885 this._trigger("change", event, this._uiHash());
2890 //Post events to containers
2891 this._contactContainers(event);
2893 //Interconnect with droppables
2894 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
2897 this._trigger('sort', event, this._uiHash());
2899 this.lastPositionAbs = this.positionAbs;
2904 _mouseStop: function(event, noPropagation) {
2908 //If we are using droppables, inform the manager about the drop
2909 if ($.ui.ddmanager && !this.options.dropBehaviour)
2910 $.ui.ddmanager.drop(this, event);
2912 if(this.options.revert) {
2914 var cur = self.placeholder.offset();
2916 self.reverting = true;
2918 $(this.helper).animate({
2919 left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
2920 top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
2921 }, parseInt(this.options.revert, 10) || 500, function() {
2925 this._clear(event, noPropagation);
2932 cancel: function() {
2940 if(this.options.helper == "original")
2941 this.currentItem.css(this._storedCSS).removeClass(this.options.cssNamespace+"-sortable-helper");
2943 this.currentItem.show();
2945 //Post deactivating events to containers
2946 for (var i = this.containers.length - 1; i >= 0; i--){
2947 this.containers[i]._trigger("deactivate", null, self._uiHash(this));
2948 if(this.containers[i].containerCache.over) {
2949 this.containers[i]._trigger("out", null, self._uiHash(this));
2950 this.containers[i].containerCache.over = 0;
2956 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
2957 if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
2958 if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
2967 if(this.domPosition.prev) {
2968 $(this.domPosition.prev).after(this.currentItem);
2970 $(this.domPosition.parent).prepend(this.currentItem);
2977 serialize: function(o) {
2979 var items = this._getItemsAsjQuery(o && o.connected);
2980 var str = []; o = o || {};
2982 $(items).each(function() {
2983 var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
2984 if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
2987 return str.join('&');
2991 toArray: function(o) {
2993 var items = this._getItemsAsjQuery(o && o.connected);
2994 var ret = []; o = o || {};
2996 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
3001 /* Be careful with the following core functions */
3002 _intersectsWith: function(item) {
3004 var x1 = this.positionAbs.left,
3005 x2 = x1 + this.helperProportions.width,
3006 y1 = this.positionAbs.top,
3007 y2 = y1 + this.helperProportions.height;
3012 b = t + item.height;
3014 var dyClick = this.offset.click.top,
3015 dxClick = this.offset.click.left;
3017 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
3019 if( this.options.tolerance == "pointer"
3020 || this.options.forcePointerForContainers
3021 || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
3023 return isOverElement;
3026 return (l < x1 + (this.helperProportions.width / 2) // Right Half
3027 && x2 - (this.helperProportions.width / 2) < r // Left Half
3028 && t < y1 + (this.helperProportions.height / 2) // Bottom Half
3029 && y2 - (this.helperProportions.height / 2) < b ); // Top Half
3034 _intersectsWithPointer: function(item) {
3036 var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
3037 isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
3038 isOverElement = isOverElementHeight && isOverElementWidth,
3039 verticalDirection = this._getDragVerticalDirection(),
3040 horizontalDirection = this._getDragHorizontalDirection();
3045 return this.floating ?
3046 ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
3047 : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
3051 _intersectsWithSides: function(item) {
3053 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
3054 isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
3055 verticalDirection = this._getDragVerticalDirection(),
3056 horizontalDirection = this._getDragHorizontalDirection();
3058 if (this.floating && horizontalDirection) {
3059 return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
3061 return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
3066 _getDragVerticalDirection: function() {
3067 var delta = this.positionAbs.top - this.lastPositionAbs.top;
3068 return delta != 0 && (delta > 0 ? "down" : "up");
3071 _getDragHorizontalDirection: function() {
3072 var delta = this.positionAbs.left - this.lastPositionAbs.left;
3073 return delta != 0 && (delta > 0 ? "right" : "left");
3076 refresh: function(event) {
3077 this._refreshItems(event);
3078 this.refreshPositions();
3081 _getItemsAsjQuery: function(connected) {
3087 if(this.options.connectWith && connected) {
3088 var connectWith = this.options.connectWith.constructor == String ? [this.options.connectWith] : this.options.connectWith;
3089 for (var i = connectWith.length - 1; i >= 0; i--){
3090 var cur = $(connectWith[i]);
3091 for (var j = cur.length - 1; j >= 0; j--){
3092 var inst = $.data(cur[j], 'sortable');
3093 if(inst && inst != this && !inst.options.disabled) {
3094 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not("."+inst.options.cssNamespace+"-sortable-helper"), inst]);
3100 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("."+this.options.cssNamespace+"-sortable-helper"), this]);
3102 for (var i = queries.length - 1; i >= 0; i--){
3103 queries[i][0].each(function() {
3112 _removeCurrentsFromItems: function() {
3114 var list = this.currentItem.find(":data(sortable-item)");
3116 for (var i=0; i < this.items.length; i++) {
3118 for (var j=0; j < list.length; j++) {
3119 if(list[j] == this.items[i].item[0])
3120 this.items.splice(i,1);
3127 _refreshItems: function(event) {
3130 this.containers = [this];
3131 var items = this.items;
3133 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
3135 if(this.options.connectWith) {
3136 for (var i = this.options.connectWith.length - 1; i >= 0; i--){
3137 var cur = $(this.options.connectWith[i]);
3138 for (var j = cur.length - 1; j >= 0; j--){
3139 var inst = $.data(cur[j], 'sortable');
3140 if(inst && inst != this && !inst.options.disabled) {
3141 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
3142 this.containers.push(inst);
3148 for (var i = queries.length - 1; i >= 0; i--) {
3149 var targetData = queries[i][1];
3150 var _queries = queries[i][0];
3152 for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
3153 var item = $(_queries[j]);
3155 item.data('sortable-item', targetData); // Data for target checking (mouse manager)
3159 instance: targetData,
3160 width: 0, height: 0,
3168 refreshPositions: function(fast) {
3170 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
3171 if(this.offsetParent && this.helper) {
3172 this.offset.parent = this._getParentOffset();
3175 for (var i = this.items.length - 1; i >= 0; i--){
3176 var item = this.items[i];
3178 //We ignore calculating positions of all connected containers when we're not over them
3179 if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
3182 var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
3185 if (this.options.accurateIntersection) {
3186 item.width = t.outerWidth();
3187 item.height = t.outerHeight();
3190 item.width = t[0].offsetWidth;
3191 item.height = t[0].offsetHeight;
3200 if(this.options.custom && this.options.custom.refreshContainers) {
3201 this.options.custom.refreshContainers.call(this);
3203 for (var i = this.containers.length - 1; i >= 0; i--){
3204 var p = this.containers[i].element.offset();
3205 this.containers[i].containerCache.left = p.left;
3206 this.containers[i].containerCache.top = p.top;
3207 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
3208 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
3214 _createPlaceholder: function(that) {
3216 var self = that || this, o = self.options;
3218 if(!o.placeholder || o.placeholder.constructor == String) {
3219 var className = o.placeholder;
3221 element: function() {
3223 var el = $(document.createElement(self.currentItem[0].nodeName))
3224 .addClass(className || self.currentItem[0].className+" "+self.options.cssNamespace+"-sortable-placeholder")
3225 .removeClass(self.options.cssNamespace+'-sortable-helper')[0];
3228 el.style.visibility = "hidden";
3232 update: function(container, p) {
3234 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
3235 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
3236 if(className && !o.forcePlaceholderSize) return;
3238 //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
3239 if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
3240 if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
3245 //Create the placeholder
3246 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
3248 //Append it after the actual current item
3249 self.currentItem.after(self.placeholder);
3251 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
3252 o.placeholder.update(self, self.placeholder);
3256 _contactContainers: function(event) {
3257 for (var i = this.containers.length - 1; i >= 0; i--){
3259 if(this._intersectsWith(this.containers[i].containerCache)) {
3260 if(!this.containers[i].containerCache.over) {
3262 if(this.currentContainer != this.containers[i]) {
3264 //When entering a new container, we will find the item with the least distance and append our item near it
3265 var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[i].floating ? 'left' : 'top'];
3266 for (var j = this.items.length - 1; j >= 0; j--) {
3267 if(!$.ui.contains(this.containers[i].element[0], this.items[j].item[0])) continue;
3268 var cur = this.items[j][this.containers[i].floating ? 'left' : 'top'];
3269 if(Math.abs(cur - base) < dist) {
3270 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
3274 if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
3277 this.currentContainer = this.containers[i];
3278 itemWithLeastDistance ? this.options.sortIndicator.call(this, event, itemWithLeastDistance, null, true) : this.options.sortIndicator.call(this, event, null, this.containers[i].element, true);
3279 this._trigger("change", event, this._uiHash());
3280 this.containers[i]._trigger("change", event, this._uiHash(this));
3282 //Update the placeholder
3283 this.options.placeholder.update(this.currentContainer, this.placeholder);
3287 this.containers[i]._trigger("over", event, this._uiHash(this));
3288 this.containers[i].containerCache.over = 1;
3291 if(this.containers[i].containerCache.over) {
3292 this.containers[i]._trigger("out", event, this._uiHash(this));
3293 this.containers[i].containerCache.over = 0;
3300 _createHelper: function(event) {
3302 var o = this.options;
3303 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
3305 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
3306 $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
3308 if(helper[0] == this.currentItem[0])
3309 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") };
3311 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
3312 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
3318 _adjustOffsetFromHelper: function(obj) {
3319 if(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left;
3320 if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
3321 if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top;
3322 if(obj.bottom != undefined) this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
3325 _getParentOffset: function() {
3328 //Get the offsetParent and cache its position
3329 this.offsetParent = this.helper.offsetParent();
3330 var po = this.offsetParent.offset();
3332 // This is a special case where we need to modify a offset calculated on start, since the following happened:
3333 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
3334 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
3335 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
3336 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
3337 po.left += this.scrollParent.scrollLeft();
3338 po.top += this.scrollParent.scrollTop();
3341 if((this.offsetParent[0] == document.body && $.browser.mozilla) //Ugly FF3 fix
3342 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
3343 po = { top: 0, left: 0 };
3346 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
3347 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
3352 _getRelativeOffset: function() {
3354 if(this.cssPosition == "relative") {
3355 var p = this.currentItem.position();
3357 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
3358 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
3361 return { top: 0, left: 0 };
3366 _cacheMargins: function() {
3368 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
3369 top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
3373 _cacheHelperProportions: function() {
3374 this.helperProportions = {
3375 width: this.helper.outerWidth(),
3376 height: this.helper.outerHeight()
3380 _setContainment: function() {
3382 var o = this.options;
3383 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
3384 if(o.containment == 'document' || o.containment == 'window') this.containment = [
3385 0 - this.offset.relative.left - this.offset.parent.left,
3386 0 - this.offset.relative.top - this.offset.parent.top,
3387 $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
3388 ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
3391 if(!(/^(document|window|parent)$/).test(o.containment)) {
3392 var ce = $(o.containment)[0];
3393 var co = $(o.containment).offset();
3394 var over = ($(ce).css("overflow") != 'hidden');
3396 this.containment = [
3397 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
3398 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
3399 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,
3400 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
3406 _convertPositionTo: function(d, pos) {
3408 if(!pos) pos = this.position;
3409 var mod = d == "absolute" ? 1 : -1;
3410 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);
3414 pos.top // The absolute mouse position
3415 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
3416 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
3417 - ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod
3420 pos.left // The absolute mouse position
3421 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
3422 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
3423 - ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod
3429 _generatePosition: function(event) {
3431 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);
3433 // This is another very weird special case that only happens for relative elements:
3434 // 1. If the css position is relative
3435 // 2. and the scroll parent is the document or similar to the offset parent
3436 // we have to refresh the relative offset during the scroll so there are no jumps
3437 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
3438 this.offset.relative = this._getRelativeOffset();
3441 var pageX = event.pageX;
3442 var pageY = event.pageY;
3445 * - Position constraining -
3446 * Constrain the position to a mix of grid, containment.
3449 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
3451 if(this.containment) {
3452 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
3453 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
3454 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
3455 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
3459 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
3460 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;
3462 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
3463 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;
3470 pageY // The absolute mouse position
3471 - this.offset.click.top // Click offset (relative to the element)
3472 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
3473 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
3474 + ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )
3477 pageX // The absolute mouse position
3478 - this.offset.click.left // Click offset (relative to the element)
3479 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
3480 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
3481 + ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )
3487 _rearrange: function(event, i, a, hardRefresh) {
3489 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));
3491 //Various things done here to improve the performance:
3492 // 1. we create a setTimeout, that calls refreshPositions
3493 // 2. on the instance, we have a counter variable, that get's higher after every append
3494 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
3495 // 4. this lets only the last addition to the timeout stack through
3496 this.counter = this.counter ? ++this.counter : 1;
3497 var self = this, counter = this.counter;
3499 window.setTimeout(function() {
3500 if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
3505 _clear: function(event, noPropagation) {
3507 this.reverting = false;
3508 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
3509 // everything else normalized again
3510 var delayedTriggers = [], self = this;
3512 //We first have to update the dom position of the actual currentItem
3513 if(!this._noFinalSort) this.placeholder.before(this.currentItem);
3514 this._noFinalSort = null;
3516 if(this.helper[0] == this.currentItem[0]) {
3517 for(var i in this._storedCSS) {
3518 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
3520 this.currentItem.css(this._storedCSS).removeClass(this.options.cssNamespace+"-sortable-helper");
3522 this.currentItem.show();
3525 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
3526 if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not("."+this.options.cssNamespace+"-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
3527 if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
3528 if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
3529 for (var i = this.containers.length - 1; i >= 0; i--){
3530 if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
3531 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
3532 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
3537 //Post events to containers
3538 for (var i = this.containers.length - 1; i >= 0; i--){
3539 if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
3540 if(this.containers[i].containerCache.over) {
3541 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
3542 this.containers[i].containerCache.over = 0;
3546 //Do what was originally in plugins
3547 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
3548 if(this._storedOpacity) this.helper.css("opacity", this._storedCursor); //Reset cursor
3549 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
3551 this.dragging = false;
3552 if(this.cancelHelperRemoval) {
3553 if(!noPropagation) {
3554 this._trigger("beforeStop", event, this._uiHash());
3555 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
3556 this._trigger("stop", event, this._uiHash());
3561 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
3563 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3564 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3566 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
3568 if(!noPropagation) {
3569 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
3570 this._trigger("stop", event, this._uiHash());
3573 this.fromOutside = false;
3578 _trigger: function() {
3579 if ($.widget.prototype._trigger.apply(this, arguments) === false) {
3584 _uiHash: function(inst) {
3585 var self = inst || this;
3587 helper: self.helper,
3588 placeholder: self.placeholder || $([]),
3589 position: self.position,
3590 absolutePosition: self.positionAbs, //deprecated
3591 offset: self.positionAbs,
3592 item: self.currentItem,
3593 sender: inst ? inst.element : null
3599 $.extend($.ui.sortable, {
3600 getter: "serialize toArray",
3603 accurateIntersection: true,
3605 cancel: ":input,option",
3611 forcePlaceholderSize: false,
3612 forceHelperSize: false,
3619 scrollSensitivity: 20,
3621 sortIndicator: $.ui.sortable.prototype._rearrange,
3622 tolerance: "intersect",
3629 * jQuery UI Accordion 1.6rc6
3631 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
3632 * Dual licensed under the MIT (MIT-LICENSE.txt)
3633 * and GPL (GPL-LICENSE.txt) licenses.
3635 * http://docs.jquery.com/UI/Accordion
3642 $.widget("ui.accordion", {
3646 var o = this.options, self = this;
3649 if ( o.navigation ) {
3650 var current = this.element.find("a").filter(o.navigationFilter);
3651 if ( current.length ) {
3652 if ( current.filter(o.header).length ) {
3653 this.active = current;
3655 this.active = current.parent().parent().prev();
3656 current.addClass("ui-accordion-content-active");
3661 this.element.addClass("ui-accordion ui-widget ui-helper-reset");
3663 this.headers = this.element.find(o.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all")
3664 .bind("mouseenter.accordion", function(){ $(this).addClass('ui-state-hover'); })
3665 .bind("mouseleave.accordion", function(){ $(this).removeClass('ui-state-hover'); });
3669 .addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");
3671 this.active = this._findActive(this.active || o.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");
3672 this.active.next().addClass('ui-accordion-content-active');
3674 //Append icon elements
3675 $("<span/>").addClass("ui-icon " + o.icons.header).prependTo(this.headers);
3676 this.active.find(".ui-icon").toggleClass(o.icons.header).toggleClass(o.icons.headerSelected);
3678 // IE7-/Win - Extra vertical space in lists fixed
3679 if ($.browser.msie) {
3680 this.element.find('a').css('zoom', '1');
3686 this.element.attr('role','tablist');
3690 .bind('keydown', function(event) { return self._keydown(event); })
3692 .attr('role','tabpanel');
3695 .not(this.active || "")
3696 .attr('aria-expanded','false')
3697 .attr("tabIndex", "-1")
3701 // make sure at least one header is in the tab order
3702 if (!this.active.length) {
3703 this.headers.eq(0).attr('tabIndex','0');
3706 .attr('aria-expanded','true')
3707 .attr('tabIndex', '0');
3710 // only need links in taborder for Safari
3711 if (!$.browser.safari)
3712 this.headers.find('a').attr('tabIndex','-1');
3715 this.element.bind((o.event) + ".accordion", function(event) { return self._clickHandler.call(self, event); });
3720 destroy: function() {
3723 .removeClass("ui-accordion ui-widget ui-helper-reset")
3725 .unbind('.accordion')
3726 .removeData('accordion');
3729 .unbind(".accordion")
3730 .removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top")
3731 .removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex");
3733 this.headers.find("a").removeAttr("tabindex");
3734 this.headers.children(".ui-icon").remove();
3735 this.headers.next().removeClass("ui-accordion-content ui-accordion-content-active");
3739 _keydown: function(event) {
3741 var o = this.options, keyCode = $.ui.keyCode;
3743 if (o.disabled || event.altKey || event.ctrlKey)
3746 var length = this.headers.length;
3747 var currentIndex = this.headers.index(event.target);
3748 var toFocus = false;
3750 switch(event.keyCode) {
3753 toFocus = this.headers[(currentIndex + 1) % length];
3757 toFocus = this.headers[(currentIndex - 1 + length) % length];
3761 return this._clickHandler({ target: event.target });
3765 $(event.target).attr('tabIndex','-1');
3766 $(toFocus).attr('tabIndex','0');
3775 resize: function() {
3777 var o = this.options, maxHeight;
3781 if($.browser.msie) { var defOverflow = this.element.parent().css('overflow'); this.element.parent().css('overflow', 'hidden'); }
3782 maxHeight = this.element.parent().height();
3783 if($.browser.msie) { this.element.parent().css('overflow', defOverflow); }
3785 this.headers.each(function() {
3786 maxHeight -= $(this).outerHeight();
3790 this.headers.next().each(function() {
3791 maxPadding = Math.max(maxPadding, $(this).innerHeight() - $(this).height());
3792 }).height(maxHeight - maxPadding)
3793 .css('overflow', 'auto');
3795 } else if ( o.autoHeight ) {
3797 this.headers.next().each(function() {
3798 maxHeight = Math.max(maxHeight, $(this).outerHeight());
3799 }).height(maxHeight);
3804 activate: function(index) {
3805 // call clickHandler with custom event
3806 this._clickHandler({ target: this._findActive(index)[0] });
3809 _findActive: function(selector) {
3811 ? typeof selector == "number"
3812 ? this.headers.filter(":eq(" + selector + ")")
3813 : this.headers.not(this.headers.not(selector))
3814 : selector === false
3816 : this.headers.filter(":eq(0)");
3819 _clickHandler: function(event) {
3821 var o = this.options;
3822 if (o.disabled) return false;
3824 // called only when using activate(false) to close all parts programmatically
3825 if (!event.target && !o.alwaysOpen) {
3826 this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
3827 .find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);
3828 this.active.next().addClass('ui-accordion-content-active');
3829 var toHide = this.active.next(),
3833 oldHeader: o.active,
3837 toShow = (this.active = $([]));
3838 this._toggle(toShow, toHide, data);
3842 // get the click target
3843 var clicked = $(event.target);
3845 // due to the event delegation model, we have to check if one
3846 // of the parent elements is our actual header, and find that
3847 // otherwise stick with the initial target
3848 clicked = $( clicked.parents(o.header)[0] || clicked );
3849 var clickedIsActive = clicked[0] == this.active[0];
3851 // if animations are still active, or the active header is the target, ignore click
3852 if (this.running || (o.alwaysOpen && clickedIsActive)) {
3855 if (!clicked.is(o.header)) {
3860 this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
3861 .find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);
3862 this.active.next().addClass('ui-accordion-content-active');
3863 if (!clickedIsActive) {
3864 clicked.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top")
3865 .find(".ui-icon").removeClass(o.icons.header).addClass(o.icons.headerSelected);
3866 clicked.next().addClass('ui-accordion-content-active');
3869 // find elements to show and hide
3870 var toShow = clicked.next(),
3871 toHide = this.active.next(),
3874 newHeader: clickedIsActive && !o.alwaysOpen ? $([]) : clicked,
3875 oldHeader: this.active,
3876 newContent: clickedIsActive && !o.alwaysOpen ? $([]) : toShow.find('> *'),
3877 oldContent: toHide.find('> *')
3879 down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
3881 this.active = clickedIsActive ? $([]) : clicked;
3882 this._toggle(toShow, toHide, data, clickedIsActive, down);
3888 _toggle: function(toShow, toHide, data, clickedIsActive, down) {
3890 var o = this.options, self = this;
3892 this.toShow = toShow;
3893 this.toHide = toHide;
3896 var complete = function() { if(!self) return; return self._completed.apply(self, arguments); };
3898 // trigger changestart event
3899 this._trigger("changestart", null, this.data);
3901 // count elements to animate
3902 this.running = toHide.size() === 0 ? toShow.size() : toHide.size();
3906 var animOptions = {};
3908 if ( !o.alwaysOpen && clickedIsActive ) {
3914 autoHeight: o.autoHeight || o.fillSpace
3922 autoHeight: o.autoHeight || o.fillSpace
3927 o.proxied = o.animated;
3930 if (!o.proxiedDuration) {
3931 o.proxiedDuration = o.duration;
3934 o.animated = $.isFunction(o.proxied) ?
3935 o.proxied(animOptions) : o.proxied;
3937 o.duration = $.isFunction(o.proxiedDuration) ?
3938 o.proxiedDuration(animOptions) : o.proxiedDuration;
3940 var animations = $.ui.accordion.animations,
3941 duration = o.duration,
3942 easing = o.animated;
3944 if (!animations[easing]) {
3945 animations[easing] = function(options) {
3946 this.slide(options, {
3948 duration: duration || 700
3953 animations[easing](animOptions);
3957 if (!o.alwaysOpen && clickedIsActive) {
3968 toHide.prev().attr('aria-expanded','false').attr("tabIndex", "-1");
3969 toShow.prev().attr('aria-expanded','true').attr("tabIndex", "0").focus();
3973 _completed: function(cancel) {
3975 var o = this.options;
3977 this.running = cancel ? 0 : --this.running;
3978 if (this.running) return;
3981 this.toShow.add(this.toHide).css({
3987 this._trigger('change', null, this.data);
3993 $.extend($.ui.accordion, {
4005 header: "ui-icon-triangle-1-e",
4006 headerSelected: "ui-icon-triangle-1-s"
4009 navigationFilter: function() {
4010 return this.href.toLowerCase() == location.href.toLowerCase();
4014 slide: function(options, additions) {
4015 options = $.extend({
4018 }, options, additions);
4019 if ( !options.toHide.size() ) {
4020 options.toShow.animate({height: "show"}, options);
4023 var hideHeight = options.toHide.height(),
4024 showHeight = options.toShow.height(),
4025 difference = showHeight / hideHeight,
4026 overflow = options.toShow.css('overflow'),
4029 fxAttrs = [ "height", "paddingTop", "paddingBottom" ];
4030 $.each(fxAttrs, function(i, prop) {
4031 hideProps[prop] = 'hide';
4032 showProps[prop] = parseFloat(options.toShow.css(prop));
4034 options.toShow.css({ height: 0, overflow: 'hidden' }).show();
4035 options.toHide.filter(":hidden").each(options.complete).end().filter(":visible").animate(hideProps,{
4036 step: function(now, settings) {
4037 // if the alwaysOpen option is set to false, we may not have
4038 // a content pane to show
4039 if (!options.toShow[0]) { return; }
4041 var percentDone = settings.start != settings.end
4042 ? (settings.now - settings.start) / (settings.end - settings.start)
4044 current = percentDone * showProps[settings.prop];
4045 if ($.browser.msie || $.browser.opera) {
4046 current = Math.ceil(current);
4048 options.toShow[0].style[settings.prop] = current + 'px';
4050 duration: options.duration,
4051 easing: options.easing,
4052 complete: function() {
4053 if ( !options.autoHeight ) {
4054 options.toShow.css("height", "auto");
4056 options.toShow.css({overflow: overflow});
4061 bounceslide: function(options) {
4062 this.slide(options, {
4063 easing: options.down ? "easeOutBounce" : "swing",
4064 duration: options.down ? 1000 : 200
4067 easeslide: function(options) {
4068 this.slide(options, {
4069 easing: "easeinout",
4078 * jQuery UI Dialog 1.6rc6
4080 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
4081 * Dual licensed under the MIT (MIT-LICENSE.txt)
4082 * and GPL (GPL-LICENSE.txt) licenses.
4084 * http://docs.jquery.com/UI/Dialog
4093 var setDataSwitch = {
4094 dragStart: "start.draggable",
4095 drag: "drag.draggable",
4096 dragStop: "stop.draggable",
4097 maxHeight: "maxHeight.resizable",
4098 minHeight: "minHeight.resizable",
4099 maxWidth: "maxWidth.resizable",
4100 minWidth: "minWidth.resizable",
4101 resizeStart: "start.resizable",
4102 resize: "drag.resizable",
4103 resizeStop: "stop.resizable"
4106 $.widget("ui.dialog", {
4109 this.originalTitle = this.element.attr('title');
4112 options = this.options,
4114 title = options.title || this.originalTitle || ' ',
4115 titleId = $.ui.dialog.getTitleId(this.element),
4117 uiDialog = (this.uiDialog = $('<div/>'))
4118 .appendTo(document.body)
4123 'ui-widget-content ' +
4128 position: 'absolute',
4130 zIndex: options.zIndex
4132 // setting tabIndex makes the div focusable
4133 // setting outline to 0 prevents a border on focus in Mozilla
4134 .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
4135 (options.closeOnEscape && event.keyCode
4136 && event.keyCode == $.ui.keyCode.ESCAPE && self.close(event));
4140 'aria-labelledby': titleId
4142 .mousedown(function(event) {
4143 self.moveToTop(event);
4146 uiDialogContent = this.element
4148 .removeAttr('title')
4150 'ui-dialog-content ' +
4151 'ui-widget-content')
4152 .appendTo(uiDialog),
4154 uiDialogTitlebar = (this.uiDialogTitlebar = $('<div></div>'))
4156 'ui-dialog-titlebar ' +
4157 'ui-widget-header ' +
4159 'ui-helper-clearfix'
4161 .prependTo(uiDialog),
4163 uiDialogTitlebarClose = $('<a href="#"/>')
4165 'ui-dialog-titlebar-close ' +
4168 .attr('role', 'button')
4171 uiDialogTitlebarClose.addClass('ui-state-hover');
4174 uiDialogTitlebarClose.removeClass('ui-state-hover');
4178 uiDialogTitlebarClose.addClass('ui-state-focus');
4181 uiDialogTitlebarClose.removeClass('ui-state-focus');
4183 .mousedown(function(ev) {
4184 ev.stopPropagation();
4186 .click(function(event) {
4190 .appendTo(uiDialogTitlebar),
4192 uiDialogTitlebarCloseText = (this.uiDialogTitlebarCloseText = $('<span/>'))
4195 'ui-icon-closethick'
4197 .text(options.closeText)
4198 .appendTo(uiDialogTitlebarClose),
4200 uiDialogTitle = $('<span/>')
4201 .addClass('ui-dialog-title')
4202 .attr('id', titleId)
4204 .prependTo(uiDialogTitlebar);
4206 uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
4208 (options.draggable && $.fn.draggable && this._makeDraggable());
4209 (options.resizable && $.fn.resizable && this._makeResizable());
4211 this._createButtons(options.buttons);
4212 this._isOpen = false;
4214 (options.bgiframe && $.fn.bgiframe && uiDialog.bgiframe());
4215 (options.autoOpen && this.open());
4219 destroy: function() {
4220 (this.overlay && this.overlay.destroy());
4221 (this.shadow && this._destroyShadow());
4222 this.uiDialog.hide();
4225 .removeData('dialog')
4226 .removeClass('ui-dialog-content ui-widget-content')
4227 .hide().appendTo('body');
4228 this.uiDialog.remove();
4230 (this.originalTitle && this.element.attr('title', this.originalTitle));
4233 close: function(event) {
4234 if (false === this._trigger('beforeclose', event)) {
4238 (this.overlay && this.overlay.destroy());
4239 (this.shadow && this._destroyShadow());
4241 .hide(this.options.hide)
4242 .unbind('keypress.ui-dialog');
4244 this._trigger('close', event);
4245 $.ui.dialog.overlay.resize();
4247 this._isOpen = false;
4250 isOpen: function() {
4251 return this._isOpen;
4254 // the force parameter allows us to move modal dialogs to their correct
4256 moveToTop: function(force, event) {
4258 if ((this.options.modal && !force)
4259 || (!this.options.stack && !this.options.modal)) {
4260 return this._trigger('focus', event);
4263 var maxZ = this.options.zIndex, options = this.options;
4264 $('.ui-dialog:visible').each(function() {
4265 maxZ = Math.max(maxZ, parseInt($(this).css('z-index'), 10) || options.zIndex);
4267 (this.overlay && this.overlay.$el.css('z-index', ++maxZ));
4268 (this.shadow && this.shadow.css('z-index', ++maxZ));
4270 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
4271 // http://ui.jquery.com/bugs/ticket/3193
4272 var saveScroll = { scrollTop: this.element.attr('scrollTop'), scrollLeft: this.element.attr('scrollLeft') };
4273 this.uiDialog.css('z-index', ++maxZ);
4274 this.element.attr(saveScroll);
4275 this._trigger('focus', event);
4278 open: function(event) {
4279 if (this._isOpen) { return; }
4281 var options = this.options,
4282 uiDialog = this.uiDialog;
4284 this.overlay = options.modal ? new $.ui.dialog.overlay(this) : null;
4285 (uiDialog.next().length && uiDialog.appendTo('body'));
4287 this._position(options.position);
4288 uiDialog.show(options.show);
4289 this.moveToTop(true, event);
4291 // prevent tabbing out of modal dialogs
4292 (options.modal && uiDialog.bind('keypress.ui-dialog', function(event) {
4293 if (event.keyCode != $.ui.keyCode.TAB) {
4297 var tabbables = $(':tabbable', this),
4298 first = tabbables.filter(':first')[0],
4299 last = tabbables.filter(':last')[0];
4301 if (event.target == last && !event.shiftKey) {
4302 setTimeout(function() {
4305 } else if (event.target == first && event.shiftKey) {
4306 setTimeout(function() {
4312 // set focus to the first tabbable element in:
4317 .add(uiDialog.find('.ui-dialog-content :tabbable:first'))
4318 .add(uiDialog.find('.ui-dialog-buttonpane :tabbable:first'))
4319 .add(uiDialog.find('.ui-dialog-titlebar :tabbable:first'))
4324 this._createShadow();
4326 this._trigger('open', event);
4327 this._isOpen = true;
4330 _createButtons: function(buttons) {
4333 uiDialogButtonPane = $('<div></div>')
4335 'ui-dialog-buttonpane ' +
4336 'ui-widget-content ' +
4337 'ui-helper-clearfix'
4340 // if we already have a button pane, remove it
4341 this.uiDialog.find('.ui-dialog-buttonpane').remove();
4343 (typeof buttons == 'object' && buttons !== null &&
4344 $.each(buttons, function() { return !(hasButtons = true); }));
4346 $.each(buttons, function(name, fn) {
4347 $('<button type="button"></button>')
4349 'ui-state-default ' +
4353 .click(function() { fn.apply(self.element[0], arguments); })
4356 $(this).addClass('ui-state-hover');
4359 $(this).removeClass('ui-state-hover');
4363 $(this).addClass('ui-state-focus');
4366 $(this).removeClass('ui-state-focus');
4368 .appendTo(uiDialogButtonPane);
4370 uiDialogButtonPane.appendTo(this.uiDialog);
4374 _makeDraggable: function() {
4376 options = this.options;
4378 this.uiDialog.draggable({
4379 cancel: '.ui-dialog-content',
4380 helper: options.dragHelper,
4381 handle: '.ui-dialog-titlebar',
4382 containment: 'document',
4384 (options.dragStart && options.dragStart.apply(self.element[0], arguments));
4385 if($.browser.msie && $.browser.version < 7 && self.shadow) self.shadow.hide();
4388 (options.drag && options.drag.apply(self.element[0], arguments));
4389 self._refreshShadow(1);
4392 (options.dragStop && options.dragStop.apply(self.element[0], arguments));
4393 $.ui.dialog.overlay.resize();
4394 if($.browser.msie && $.browser.version < 7 && self.shadow) self.shadow.show();
4395 self._refreshShadow();
4400 _makeResizable: function(handles) {
4401 handles = (handles === undefined ? this.options.resizable : handles);
4403 options = this.options,
4404 resizeHandles = typeof handles == 'string'
4406 : 'n,e,s,w,se,sw,ne,nw';
4408 this.uiDialog.resizable({
4409 cancel: '.ui-dialog-content',
4410 alsoResize: this.element,
4411 helper: options.resizeHelper,
4412 maxWidth: options.maxWidth,
4413 maxHeight: options.maxHeight,
4414 minWidth: options.minWidth,
4415 minHeight: options.minHeight,
4417 (options.resizeStart && options.resizeStart.apply(self.element[0], arguments));
4418 if($.browser.msie && $.browser.version < 7 && self.shadow) self.shadow.hide();
4420 resize: function() {
4421 (options.resize && options.resize.apply(self.element[0], arguments));
4422 self._refreshShadow(1);
4424 handles: resizeHandles,
4426 (options.resizeStop && options.resizeStop.apply(self.element[0], arguments));
4427 $.ui.dialog.overlay.resize();
4428 if($.browser.msie && $.browser.version < 7 && self.shadow) self.shadow.show();
4429 self._refreshShadow();
4432 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
4435 _position: function(pos) {
4436 var wnd = $(window), doc = $(document),
4437 pTop = doc.scrollTop(), pLeft = doc.scrollLeft(),
4440 if ($.inArray(pos, ['center','top','right','bottom','left']) >= 0) {
4442 pos == 'right' || pos == 'left' ? pos : 'center',
4443 pos == 'top' || pos == 'bottom' ? pos : 'middle'
4446 if (pos.constructor != Array) {
4447 pos = ['center', 'middle'];
4449 if (pos[0].constructor == Number) {
4457 pLeft += wnd.width() - this.uiDialog.outerWidth();
4461 pLeft += (wnd.width() - this.uiDialog.outerWidth()) / 2;
4464 if (pos[1].constructor == Number) {
4472 pTop += wnd.height() - this.uiDialog.outerHeight();
4476 pTop += (wnd.height() - this.uiDialog.outerHeight()) / 2;
4480 // prevent the dialog from being too high (make sure the titlebar
4482 pTop = Math.max(pTop, minTop);
4483 this.uiDialog.css({top: pTop, left: pLeft});
4486 _setData: function(key, value){
4487 (setDataSwitch[key] && this.uiDialog.data(setDataSwitch[key], value));
4490 this._createButtons(value);
4493 this.uiDialogTitlebarCloseText.text(value);
4497 ? this._makeDraggable()
4498 : this.uiDialog.draggable('destroy'));
4501 this.uiDialog.height(value);
4504 this._position(value);
4507 var uiDialog = this.uiDialog,
4508 isResizable = this.uiDialog.is(':data(resizable)');
4510 // currently resizable, becoming non-resizable
4511 (isResizable && !value && uiDialog.resizable('destroy'));
4513 // currently resizable, changing handles
4514 (isResizable && typeof value == 'string' &&
4515 uiDialog.resizable('option', 'handles', value));
4517 // currently non-resizable, becoming resizable
4518 (isResizable || this._makeResizable(value));
4522 $(".ui-dialog-title", this.uiDialogTitlebar).html(value || ' ');
4525 this.uiDialog.width(value);
4529 $.widget.prototype._setData.apply(this, arguments);
4533 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
4534 * divs will both have width and height set, so we need to reset them
4536 var options = this.options;
4538 // reset content sizing
4545 // reset wrapper sizing
4546 // determine the height of all the non-content elements
4547 var nonContentHeight = this.uiDialog.css({
4549 width: options.width
4555 minHeight: Math.max(options.minHeight - nonContentHeight, 0),
4556 height: options.height == 'auto'
4558 : options.height - nonContentHeight
4562 _createShadow: function() {
4563 this.shadow = $('<div class="ui-widget-shadow"></div>').css('position', 'absolute').appendTo(document.body);
4564 this._refreshShadow();
4568 _refreshShadow: function(dragging) {
4569 // IE6 is simply to slow to handle the reflow in a good way, so
4570 // resizing only happens on stop, and the shadow is hidden during drag/resize
4571 if(dragging && $.browser.msie && $.browser.version < 7) return;
4573 var offset = this.uiDialog.offset();
4577 width: this.uiDialog.outerWidth(),
4578 height: this.uiDialog.outerHeight()
4582 _destroyShadow: function() {
4583 this.shadow.remove();
4589 $.extend($.ui.dialog, {
4595 closeOnEscape: true,
4615 getTitleId: function($el) {
4616 return 'ui-dialog-title-' + ($el.attr('id') || ++this.uuid);
4619 overlay: function(dialog) {
4620 this.$el = $.ui.dialog.overlay.create(dialog);
4624 $.extend($.ui.dialog.overlay, {
4626 events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
4627 function(event) { return event + '.dialog-overlay'; }).join(' '),
4628 create: function(dialog) {
4629 if (this.instances.length === 0) {
4630 // prevent use of anchors and inputs
4631 // we use a setTimeout in case the overlay is created from an
4632 // event that we're going to be cancelling (see #2804)
4633 setTimeout(function() {
4634 $('a, :input').bind($.ui.dialog.overlay.events, function() {
4635 // allow use of the element if inside a dialog and
4636 // - there are no modal dialogs
4637 // - there are modal dialogs, but we are in front of the topmost modal
4639 var $dialog = $(this).parents('.ui-dialog');
4640 if ($dialog.length) {
4641 var $overlays = $('.ui-dialog-overlay');
4642 if ($overlays.length) {
4643 var maxZ = parseInt($overlays.css('z-index'), 10);
4644 $overlays.each(function() {
4645 maxZ = Math.max(maxZ, parseInt($(this).css('z-index'), 10));
4647 allow = parseInt($dialog.css('z-index'), 10) > maxZ;
4656 // allow closing by pressing the escape key
4657 $(document).bind('keydown.dialog-overlay', function(event) {
4658 (dialog.options.closeOnEscape && event.keyCode
4659 && event.keyCode == $.ui.keyCode.ESCAPE && dialog.close(event));
4662 // handle window resize
4663 $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
4666 var $el = $('<div></div>').appendTo(document.body)
4667 .addClass('ui-widget-overlay').css({
4668 width: this.width(),
4669 height: this.height()
4672 (dialog.options.bgiframe && $.fn.bgiframe && $el.bgiframe());
4674 this.instances.push($el);
4678 destroy: function($el) {
4679 this.instances.splice($.inArray(this.instances, $el), 1);
4681 if (this.instances.length === 0) {
4682 $('a, :input').add([document, window]).unbind('.dialog-overlay');
4688 height: function() {
4690 if ($.browser.msie && $.browser.version < 7) {
4691 var scrollHeight = Math.max(
4692 document.documentElement.scrollHeight,
4693 document.body.scrollHeight
4695 var offsetHeight = Math.max(
4696 document.documentElement.offsetHeight,
4697 document.body.offsetHeight
4700 if (scrollHeight < offsetHeight) {
4701 return $(window).height() + 'px';
4703 return scrollHeight + 'px';
4705 // handle "good" browsers
4707 return $(document).height() + 'px';
4713 if ($.browser.msie && $.browser.version < 7) {
4714 var scrollWidth = Math.max(
4715 document.documentElement.scrollWidth,
4716 document.body.scrollWidth
4718 var offsetWidth = Math.max(
4719 document.documentElement.offsetWidth,
4720 document.body.offsetWidth
4723 if (scrollWidth < offsetWidth) {
4724 return $(window).width() + 'px';
4726 return scrollWidth + 'px';
4728 // handle "good" browsers
4730 return $(document).width() + 'px';
4734 resize: function() {
4735 /* If the dialog is draggable and the user drags it past the
4736 * right edge of the window, the document becomes wider so we
4737 * need to stretch the overlay. If the user then drags the
4738 * dialog back to the left, the document will become narrower,
4739 * so we need to shrink the overlay to the appropriate size.
4740 * This is handled by shrinking the overlay before setting it
4741 * to the full document size.
4743 var $overlays = $([]);
4744 $.each($.ui.dialog.overlay.instances, function() {
4745 $overlays = $overlays.add(this);
4752 width: $.ui.dialog.overlay.width(),
4753 height: $.ui.dialog.overlay.height()
4758 $.extend($.ui.dialog.overlay.prototype, {
4759 destroy: function() {
4760 $.ui.dialog.overlay.destroy(this.$el);
4766 * jQuery UI Slider 1.6rc6
4768 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
4769 * Dual licensed under the MIT (MIT-LICENSE.txt)
4770 * and GPL (GPL-LICENSE.txt) licenses.
4772 * http://docs.jquery.com/UI/Slider
4780 $.widget("ui.slider", $.extend({}, $.ui.mouse, {
4784 var self = this, o = this.options;
4785 this._keySliding = false;
4786 this._handleIndex = null;
4787 this._detectOrientation();
4791 .addClass("ui-slider"
4792 + " ui-slider-" + this.orientation
4794 + " ui-widget-content"
4795 + " ui-corner-all");
4801 if (o.range === true) {
4802 this.range = $('<div></div>');
4803 if (!o.values) o.values = [this._valueMin(), this._valueMin()];
4804 if (o.values.length && o.values.length != 2) {
4805 o.values = [o.values[0], o.values[0]];
4808 this.range = $('<div></div>');
4812 .appendTo(this.element)
4813 .addClass("ui-slider-range"
4814 + " ui-widget-header");
4816 (o.range == "min") && (this.orientation == "horizontal") && this.range.css({ left : 0 });
4817 (o.range == "max") && (this.orientation == "horizontal") && this.range.css({ right : 0 });
4818 (o.range == "min") && (this.orientation == "vertical") && this.range.css({ bottom : 0 });
4819 (o.range == "max") && (this.orientation == "vertical") && this.range.css({ top : 0 });
4823 if ($(".ui-slider-handle", this.element).length == 0)
4824 $('<a href="#"></a>')
4825 .appendTo(this.element)
4826 .addClass("ui-slider-handle");
4828 if (o.values && o.values.length) {
4829 while ($(".ui-slider-handle", this.element).length < o.values.length)
4830 $('<a href="#"></a>')
4831 .appendTo(this.element)
4832 .addClass("ui-slider-handle");
4835 this.handles = $(".ui-slider-handle", this.element)
4836 .addClass("ui-state-default"
4837 + " ui-corner-all");
4839 this.handle = this.handles.eq(0);
4841 this.handles.add(this.range).filter("a")
4842 .click(function(event) { event.preventDefault(); })
4843 .hover(function() { $(this).addClass('ui-state-hover'); }, function() { $(this).removeClass('ui-state-hover'); })
4844 .focus(function() { self.handles.removeClass('ui-state-focus'); $(this).addClass('ui-state-focus'); })
4845 .blur(function() { $(this).removeClass('ui-state-focus'); });
4847 this.handles.each(function(i) {
4848 $(this).data("index.ui-slider-handle", i);
4851 this.handles.keydown(function(event) {
4853 var index = $(this).data("index.ui-slider-handle");
4855 if (self.options.disabled)
4858 switch (event.keyCode) {
4859 case $.ui.keyCode.HOME:
4860 case $.ui.keyCode.END:
4861 case $.ui.keyCode.UP:
4862 case $.ui.keyCode.RIGHT:
4863 case $.ui.keyCode.DOWN:
4864 case $.ui.keyCode.LEFT:
4865 if (!self._keySliding) {
4866 self._keySliding = true;
4867 $(this).addClass("ui-state-active");
4873 var curVal, newVal, step = self._step();
4874 if (self.options.values && self.options.values.length) {
4875 curVal = newVal = self.values(index);
4877 curVal = newVal = self.value();
4880 switch (event.keyCode) {
4881 case $.ui.keyCode.HOME:
4882 newVal = self._valueMin();
4884 case $.ui.keyCode.END:
4885 newVal = self._valueMax();
4887 case $.ui.keyCode.UP:
4888 case $.ui.keyCode.RIGHT:
4889 if(curVal == self._valueMax()) return;
4890 newVal = curVal + step;
4892 case $.ui.keyCode.DOWN:
4893 case $.ui.keyCode.LEFT:
4894 if(curVal == self._valueMin()) return;
4895 newVal = curVal - step;
4899 self._slide(event, index, newVal);
4901 }).keyup(function(event) {
4903 if (self._keySliding) {
4905 self._change(event);
4906 self._keySliding = false;
4907 $(this).removeClass("ui-state-active");
4912 this._refreshValue();
4916 destroy: function() {
4918 this.handles.remove();
4921 .removeClass("ui-slider"
4922 + " ui-slider-horizontal"
4923 + " ui-slider-vertical"
4924 + " ui-slider-disabled"
4926 + " ui-widget-content"
4928 .removeData("slider")
4931 this._mouseDestroy();
4935 _mouseCapture: function(event) {
4937 var o = this.options;
4944 this.elementSize = {
4945 width: this.element.outerWidth(),
4946 height: this.element.outerHeight()
4948 this.elementOffset = this.element.offset();
4950 var position = { x: event.pageX, y: event.pageY };
4951 var normValue = this._normValueFromMouse(position);
4953 var distance = this._valueMax() + 1, closestHandle;
4954 var self = this, index;
4955 this.handles.each(function(i) {
4956 var thisDistance = Math.abs(normValue - self.values(i));
4957 if (distance > thisDistance) {
4958 distance = thisDistance;
4959 closestHandle = $(this);
4964 // workaround for bug #3736 (if both handles of a range are at 0, the first is always used as the one with least distance,
4965 // and moving it is obviously prevented by preventing negative ranges)
4966 if(o.range && (this.values(0) + this.values(1)) == 0) {
4967 closestHandle = $(this.handles[++index]);
4970 self._handleIndex = index;
4973 .addClass("ui-state-active")
4976 var offset = closestHandle.offset();
4977 var mouseOverHandle = !$(event.target).parents().andSelf().is('.ui-slider-handle');
4978 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
4979 left: event.pageX - offset.left + (parseInt(closestHandle.css('marginLeft'),10) || 0),
4980 top: event.pageY - offset.top + (parseInt(closestHandle.css('marginTop'),10) || 0)
4983 normValue = this._normValueFromMouse(position);
4984 this._slide(event, index, normValue);
4989 _mouseStart: function(event) {
4993 _mouseDrag: function(event) {
4995 var position = { x: event.pageX, y: event.pageY };
4996 var normValue = this._normValueFromMouse(position);
4998 this._slide(event, this._handleIndex, normValue);
5004 _mouseStop: function(event) {
5006 this.handles.removeClass("ui-state-active");
5008 this._change(event);
5009 this._handleIndex = null;
5010 this._clickOffset = null;
5016 _detectOrientation: function() {
5017 this.orientation = this.options.orientation == 'auto' ? (this.element[0].offsetWidth/this.element[0].offsetHeight > 1 ? 'horizontal' : 'vertical') : this.options.orientation;
5020 _normValueFromMouse: function(position) {
5022 var pixelTotal, pixelMouse;
5023 if ('horizontal' == this.orientation) {
5024 pixelTotal = this.elementSize.width;
5025 pixelMouse = position.x - this.elementOffset.left - (this._clickOffset ? this._clickOffset.left : 0);
5027 pixelTotal = this.elementSize.height;
5028 pixelMouse = position.y - this.elementOffset.top - (this._clickOffset ? this._clickOffset.top : 0);
5031 var percentMouse = (pixelMouse / pixelTotal);
5032 if (percentMouse > 1) percentMouse = 1;
5033 if (percentMouse < 0) percentMouse = 0;
5034 if ('vertical' == this.orientation)
5035 percentMouse = 1 - percentMouse;
5037 var valueTotal = this._valueMax() - this._valueMin(),
5038 valueMouse = percentMouse * valueTotal,
5039 valueMouseModStep = valueMouse % this.options.step,
5040 normValue = this._valueMin() + valueMouse - valueMouseModStep;
5042 if (valueMouseModStep > (this.options.step / 2))
5043 normValue += this.options.step;
5049 _start: function(event) {
5050 this._trigger("start", event, {
5055 _slide: function(event, index, newVal) {
5057 var handle = this.handles[index];
5059 if (this.options.values && this.options.values.length) {
5061 var otherVal = this.values(index ? 0 : 1);
5063 if ((index == 0 && newVal >= otherVal) || (index == 1 && newVal <= otherVal))
5066 if (newVal != this.values(index)) {
5067 var newValues = this.values();
5068 newValues[index] = newVal;
5069 // A slide can be canceled by returning false from the slide callback
5070 var allowed = this._trigger("slide", event, {
5075 var otherVal = this.values(index ? 0 : 1);
5076 if (allowed !== false) {
5077 this.values(index, newVal, !( event.type == 'mousedown' && this.options.animate ));
5083 if (newVal != this.value()) {
5084 // A slide can be canceled by returning false from the slide callback
5085 var allowed = this._trigger("slide", event, {
5089 if (allowed !== false) {
5090 this._setData('value', newVal, ( event.type == 'mousedown' && this.options.animate ));
5099 _stop: function(event) {
5100 this._trigger("stop", event, {
5105 _change: function(event) {
5106 this._trigger("change", event, {
5111 value: function(newValue) {
5113 if (arguments.length) {
5114 this._setData("value", newValue);
5118 return this._value();
5122 values: function(index, newValue, noAnimation) {
5124 if(!this.options.animate) noAnimation = true;
5126 if (arguments.length > 1) {
5127 this.options.values[index] = newValue;
5128 this._refreshValue(!noAnimation);
5132 if (arguments.length) {
5133 if (this.options.values && this.options.values.length) {
5134 return this._values(index);
5136 return this.value();
5139 return this._values();
5144 _setData: function(key, value) {
5146 $.widget.prototype._setData.apply(this, arguments);
5151 this._detectOrientation();
5154 .removeClass("ui-slider-horizontal ui-slider-vertical")
5155 .addClass("ui-slider-" + this.orientation);
5156 this._refreshValue();
5159 this._refreshValue();
5166 var step = this.options.step;
5170 _value: function() {
5172 var val = this.options.value;
5173 if (val < this._valueMin()) val = this._valueMin();
5174 if (val > this._valueMax()) val = this._valueMax();
5180 _values: function(index) {
5182 if (arguments.length) {
5183 var val = this.options.values[index];
5184 if (val < this._valueMin()) val = this._valueMin();
5185 if (val > this._valueMax()) val = this._valueMax();
5189 return this.options.values;
5194 _valueMin: function() {
5195 var valueMin = this.options.min;
5199 _valueMax: function() {
5200 var valueMax = this.options.max;
5204 _refreshValue: function(animate) {
5206 var oRange = this.options.range, o = this.options, self = this;
5208 if (this.options.values && this.options.values.length) {
5210 this.handles.each(function(i, j) {
5211 var valPercent = (self.values(i) - self._valueMin()) / (self._valueMax() - self._valueMin()) * 100;
5212 var _set = {}; _set[self.orientation == 'horizontal' ? 'left' : 'bottom'] = valPercent + '%';
5213 $(this).stop(1,1)[animate ? 'animate' : 'css'](_set, o.animate);
5214 if (self.options.range === true) {
5215 if (self.orientation == 'horizontal') {
5216 (i == 0) && self.range.stop(1,1)[animate ? 'animate' : 'css']({ left: valPercent + '%' }, o.animate);
5217 (i == 1) && self.range[animate ? 'animate' : 'css']({ width: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate });
5219 (i == 0) && self.range.stop(1,1)[animate ? 'animate' : 'css']({ bottom: (valPercent) + '%' }, o.animate);
5220 (i == 1) && self.range[animate ? 'animate' : 'css']({ height: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate });
5223 lastValPercent = valPercent;
5226 var valPercent = (this.value() - this._valueMin()) / (this._valueMax() - this._valueMin()) * 100;
5227 var _set = {}; _set[self.orientation == 'horizontal' ? 'left' : 'bottom'] = valPercent + '%';
5228 this.handle.stop(1,1)[animate ? 'animate' : 'css'](_set, o.animate);
5230 (oRange == "min") && (this.orientation == "horizontal") && this.range.stop(1,1)[animate ? 'animate' : 'css']({ left: 0, width: valPercent + '%' }, o.animate);
5231 (oRange == "max") && (this.orientation == "horizontal") && this.range[animate ? 'animate' : 'css']({ left: valPercent + '%', width: (100 - valPercent) + '%' }, { queue: false, duration: o.animate });
5232 (oRange == "min") && (this.orientation == "vertical") && this.range.stop(1,1)[animate ? 'animate' : 'css']({ top: (100 - valPercent) + '%', height: valPercent + '%' }, o.animate);
5233 (oRange == "max") && (this.orientation == "vertical") && this.range[animate ? 'animate' : 'css']({ bottom: valPercent + '%', height: (100 - valPercent) + '%' }, { queue: false, duration: o.animate });
5240 $.extend($.ui.slider, {
5241 getter: "value values",
5243 eventPrefix: "slide",
5250 orientation: 'auto',
5260 * jQuery UI Tabs 1.6rc6
5262 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
5263 * Dual licensed under the MIT (MIT-LICENSE.txt)
5264 * and GPL (GPL-LICENSE.txt) licenses.
5266 * http://docs.jquery.com/UI/Tabs
5273 $.widget("ui.tabs", {
5280 _setData: function(key, value) {
5281 if ((/^selected/).test(key))
5284 this.options[key] = value;
5289 _tabId: function(a) {
5290 return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '')
5291 || this.options.idPrefix + $.data(a);
5294 _sanitizeSelector: function(hash) {
5295 return hash.replace(/:/g, '\\:'); // we need this because an id may contain a ":"
5298 _cookie: function() {
5299 var cookie = this.cookie || (this.cookie = this.options.cookie.name || 'ui-tabs-' + $.data(this.list[0]));
5300 return $.cookie.apply(null, [cookie].concat($.makeArray(arguments)));
5303 _ui: function(tab, panel) {
5307 index: this.$tabs.index(tab)
5311 _tabify: function(init) {
5313 this.list = this.element.is('div') ? this.element.children('ul:first, ol:first').eq(0) : this.element;
5314 this.$lis = $('li:has(a[href])', this.list);
5315 this.$tabs = this.$lis.map(function() { return $('a', this)[0]; });
5316 this.$panels = $([]);
5318 var self = this, o = this.options;
5320 var fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
5321 this.$tabs.each(function(i, a) {
5322 var href = $(a).attr('href');
5325 if (fragmentId.test(href))
5326 self.$panels = self.$panels.add(self._sanitizeSelector(href));
5329 else if (href != '#') { // prevent loading the page itself if href is just "#"
5330 $.data(a, 'href.tabs', href); // required for restore on destroy
5332 // TODO until #3808 is fixed strip fragment identifier from url
5333 // (IE fails to load from such url)
5334 $.data(a, 'load.tabs', href.replace(/#.*$/, '')); // mutable data
5336 var id = self._tabId(a);
5338 var $panel = $('#' + id);
5339 if (!$panel.length) {
5340 $panel = $(o.panelTemplate).attr('id', id).addClass('ui-tabs-panel ui-widget-content ui-corner-bottom')
5341 .insertAfter(self.$panels[i - 1] || self.list);
5342 $panel.data('destroy.tabs', true);
5344 self.$panels = self.$panels.add($panel);
5349 o.disabled.push(i + 1);
5352 // initialization from scratch
5355 // attach necessary classes for styling
5356 if (this.element.is('div')) {
5357 this.element.addClass('ui-tabs ui-widget ui-widget-content ui-corner-all');
5359 this.list.addClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
5360 this.$lis.addClass('ui-state-default ui-corner-top');
5361 this.$panels.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom');
5364 // use "selected" option or try to retrieve:
5365 // 1. from fragment identifier in url
5367 // 3. from selected class attribute on <li>
5368 if (o.selected === undefined) {
5369 if (location.hash) {
5370 this.$tabs.each(function(i, a) {
5371 if (a.hash == location.hash) {
5373 return false; // break
5378 o.selected = parseInt(self._cookie(), 10);
5380 else if (this.$lis.filter('.ui-tabs-selected').length)
5381 o.selected = this.$lis.index(this.$lis.filter('.ui-tabs-selected'));
5387 else if (o.selected === null)
5391 o.selected = ((o.selected >= 0 && this.$tabs[o.selected]) || o.selected < 0) ? o.selected : 0; // default to first tab
5393 // Take disabling tabs via class attribute from HTML
5394 // into account and update option properly.
5395 // A selected tab cannot become disabled.
5396 o.disabled = $.unique(o.disabled.concat(
5397 $.map(this.$lis.filter('.ui-state-disabled'),
5398 function(n, i) { return self.$lis.index(n); } )
5400 if ($.inArray(o.selected, o.disabled) != -1)
5401 o.disabled.splice($.inArray(o.selected, o.disabled), 1);
5403 // highlight selected tab
5404 this.$panels.addClass('ui-tabs-hide');
5405 this.$lis.removeClass('ui-tabs-selected ui-state-active');
5406 if (o.selected >= 0 && this.$tabs.length) { // check for length avoids error when initializing empty list
5407 this.$panels.eq(o.selected).removeClass('ui-tabs-hide');
5408 var classes = ['ui-tabs-selected ui-state-active'];
5409 if (o.deselectable) classes.push('ui-tabs-deselectable');
5410 this.$lis.eq(o.selected).addClass(classes.join(' '));
5412 // seems to be expected behavior that the show callback is fired
5413 var onShow = function() {
5414 self._trigger('show', null,
5415 self._ui(self.$tabs[o.selected], self.$panels[o.selected]));
5418 // load if remote tab
5419 if ($.data(this.$tabs[o.selected], 'load.tabs'))
5420 this.load(o.selected, onShow);
5421 // just trigger show event
5426 if (o.event != 'mouseover') {
5427 var handleState = function(state, el) {
5428 if (el.is(':not(.ui-state-disabled)')) el.toggleClass('ui-state-' + state);
5430 this.$lis.bind('mouseover.tabs mouseout.tabs', function() {
5431 handleState('hover', $(this));
5433 // TODO focus/blur don't seem to work with namespace
5434 this.$tabs.bind('focus.tabs blur.tabs', function() {
5435 handleState('focus', $(this).parents('li:first'));
5439 // clean up to avoid memory leaks in certain versions of IE 6
5440 $(window).bind('unload', function() {
5441 self.$lis.add(self.$tabs).unbind('.tabs');
5442 self.$lis = self.$tabs = self.$panels = null;
5446 // update selected after add/remove
5448 o.selected = this.$lis.index(this.$lis.filter('.ui-tabs-selected'));
5450 // set or update cookie after init and add/remove respectively
5451 if (o.cookie) this._cookie(o.selected, o.cookie);
5454 for (var i = 0, li; li = this.$lis[i]; i++)
5455 $(li)[$.inArray(i, o.disabled) != -1 && !$(li).hasClass('ui-tabs-selected') ? 'addClass' : 'removeClass']('ui-state-disabled');
5457 // reset cache if switching from cached to not cached
5458 if (o.cache === false) this.$tabs.removeData('cache.tabs');
5460 // set up animations
5463 if ($.isArray(o.fx)) {
5467 else hideFx = showFx = o.fx;
5470 // Reset certain styles left over from animation
5471 // and prevent IE's ClearType bug...
5472 function resetStyle($el, fx) {
5473 $el.css({ display: '' });
5474 if ($.browser.msie && fx.opacity) $el[0].style.removeAttribute('filter');
5478 var showTab = showFx ?
5479 function(clicked, $show) {
5480 $show.hide().removeClass('ui-tabs-hide') // avoid flicker that way
5481 .animate(showFx, 500, function() {
5482 resetStyle($show, showFx);
5483 self._trigger('show', null, self._ui(clicked, $show[0]));
5486 function(clicked, $show) {
5487 $show.removeClass('ui-tabs-hide');
5488 self._trigger('show', null, self._ui(clicked, $show[0]));
5491 // Hide a tab, $show is optional...
5492 var hideTab = hideFx ?
5493 function(clicked, $hide, $show) {
5494 $hide.animate(hideFx, hideFx.duration || 'normal', function() {
5495 $hide.addClass('ui-tabs-hide');
5496 resetStyle($hide, hideFx);
5497 if ($show) showTab(clicked, $show);
5500 function(clicked, $hide, $show) {
5501 $hide.addClass('ui-tabs-hide');
5502 if ($show) showTab(clicked, $show);
5506 function switchTab(clicked, $li, $hide, $show) {
5507 var classes = ['ui-tabs-selected ui-state-active'];
5508 if (o.deselectable) classes.push('ui-tabs-deselectable');
5509 $li.removeClass('ui-state-default').addClass(classes.join(' '))
5510 .siblings().removeClass(classes.join(' ')).addClass('ui-state-default');
5511 hideTab(clicked, $hide, $show);
5514 // attach tab event handler, unbind to avoid duplicates from former tabifying...
5515 this.$tabs.unbind('.tabs').bind(o.event + '.tabs', function() {
5517 var $li = $(this).parents('li:eq(0)'),
5518 $hide = self.$panels.filter(':visible'),
5519 $show = $(self._sanitizeSelector(this.hash));
5521 // If tab is already selected and not deselectable or tab disabled or
5522 // or is already loading or click callback returns false stop here.
5523 // Check if click handler returns false last so that it is not executed
5524 // for a disabled or loading tab!
5525 if (($li.hasClass('ui-state-active') && !o.deselectable)
5526 || $li.hasClass('ui-state-disabled')
5527 || $(this).hasClass('ui-tabs-loading')
5528 || self._trigger('select', null, self._ui(this, $show[0])) === false
5534 o.selected = self.$tabs.index(this);
5536 // if tab may be closed TODO avoid redundant code in this block
5537 if (o.deselectable) {
5538 if ($li.hasClass('ui-state-active')) {
5540 if (o.cookie) self._cookie(o.selected, o.cookie);
5541 $li.removeClass('ui-tabs-selected ui-state-active ui-tabs-deselectable')
5542 .addClass('ui-state-default');
5543 self.$panels.stop();
5544 hideTab(this, $hide);
5547 } else if (!$hide.length) {
5548 if (o.cookie) self._cookie(o.selected, o.cookie);
5549 self.$panels.stop();
5551 self.load(self.$tabs.index(this), function() {
5552 $li.addClass('ui-tabs-selected ui-state-active ui-tabs-deselectable')
5553 .removeClass('ui-state-default');
5561 if (o.cookie) self._cookie(o.selected, o.cookie);
5563 // stop possibly running animations
5564 self.$panels.stop();
5569 self.load(self.$tabs.index(this), $hide.length ?
5571 switchTab(a, $li, $hide, $show);
5574 $li.addClass('ui-tabs-selected ui-state-active').removeClass('ui-state-default');
5579 throw 'jQuery UI Tabs: Mismatching fragment identifier.';
5581 // Prevent IE from keeping other link focussed when using the back button
5582 // and remove dotted border from clicked link. This is controlled via CSS
5583 // in modern browsers; blur() removes focus from address bar in Firefox
5584 // which can become a usability and annoying problem with tabs('rotate').
5585 if ($.browser.msie) this.blur();
5591 // disable click if event is configured to something else
5592 if (o.event != 'click') this.$tabs.bind('click.tabs', function(){return false;});
5596 destroy: function() {
5597 var o = this.options;
5600 .removeClass('ui-tabs ui-widget ui-widget-content ui-corner-all');
5602 this.list.unbind('.tabs')
5603 .removeClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all')
5604 .removeData('tabs');
5606 this.$tabs.each(function() {
5607 var href = $.data(this, 'href.tabs');
5610 var $this = $(this).unbind('.tabs');
5611 $.each(['href', 'load', 'cache'], function(i, prefix) {
5612 $this.removeData(prefix + '.tabs');
5616 this.$lis.unbind('.tabs').add(this.$panels).each(function() {
5617 if ($.data(this, 'destroy.tabs'))
5620 $(this).removeClass(
5621 'ui-state-default ' +
5623 'ui-tabs-selected ' +
5624 'ui-state-active ' +
5625 'ui-tabs-deselectable ' +
5626 'ui-state-disabled ' +
5628 'ui-widget-content ' +
5629 'ui-corner-bottom ' +
5634 this._cookie(null, o.cookie);
5637 add: function(url, label, index) {
5638 if (index == undefined)
5639 index = this.$tabs.length; // append by default
5641 var self = this, o = this.options;
5642 var $li = $(o.tabTemplate.replace(/#\{href\}/g, url).replace(/#\{label\}/g, label));
5643 $li.addClass('ui-state-default ui-corner-top').data('destroy.tabs', true);
5645 var id = url.indexOf('#') == 0 ? url.replace('#', '') : this._tabId( $('a:first-child', $li)[0] );
5647 // try to find an existing element before creating a new one
5648 var $panel = $('#' + id);
5649 if (!$panel.length) {
5650 $panel = $(o.panelTemplate).attr('id', id).data('destroy.tabs', true);
5652 $panel.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide');
5653 if (index >= this.$lis.length) {
5654 $li.appendTo(this.list);
5655 $panel.appendTo(this.list[0].parentNode);
5658 $li.insertBefore(this.$lis[index]);
5659 $panel.insertBefore(this.$panels[index]);
5662 o.disabled = $.map(o.disabled,
5663 function(n, i) { return n >= index ? ++n : n });
5667 if (this.$tabs.length == 1) { // after tabify
5668 $li.addClass('ui-tabs-selected ui-state-active');
5669 $panel.removeClass('ui-tabs-hide');
5670 var href = $.data(this.$tabs[0], 'load.tabs');
5671 if (href) this.load(0, function() {
5672 self._trigger('show', null,
5673 self._ui(self.$tabs[0], self.$panels[0]));
5678 this._trigger('add', null, this._ui(this.$tabs[index], this.$panels[index]));
5681 remove: function(index) {
5682 var o = this.options, $li = this.$lis.eq(index).remove(),
5683 $panel = this.$panels.eq(index).remove();
5685 // If selected tab was removed focus tab to the right or
5686 // in case the last tab was removed the tab to the left.
5687 if ($li.hasClass('ui-tabs-selected') && this.$tabs.length > 1)
5688 this.select(index + (index + 1 < this.$tabs.length ? 1 : -1));
5690 o.disabled = $.map($.grep(o.disabled, function(n, i) { return n != index; }),
5691 function(n, i) { return n >= index ? --n : n });
5696 this._trigger('remove', null, this._ui($li.find('a')[0], $panel[0]));
5699 enable: function(index) {
5700 var o = this.options;
5701 if ($.inArray(index, o.disabled) == -1)
5704 this.$lis.eq(index).removeClass('ui-state-disabled');
5705 o.disabled = $.grep(o.disabled, function(n, i) { return n != index; });
5708 this._trigger('enable', null, this._ui(this.$tabs[index], this.$panels[index]));
5711 disable: function(index) {
5712 var self = this, o = this.options;
5713 if (index != o.selected) { // cannot disable already selected tab
5714 this.$lis.eq(index).addClass('ui-state-disabled');
5716 o.disabled.push(index);
5720 this._trigger('disable', null, this._ui(this.$tabs[index], this.$panels[index]));
5724 select: function(index) {
5725 if (typeof index == 'string')
5726 index = this.$tabs.index(this.$tabs.filter('[href$=' + index + ']'));
5727 this.$tabs.eq(index).trigger(this.options.event + '.tabs');
5730 load: function(index, callback) { // callback is for internal usage only
5732 var self = this, o = this.options, $a = this.$tabs.eq(index), a = $a[0],
5733 bypassCache = callback == undefined || callback === false, url = $a.data('load.tabs');
5734 // TODO bypassCache == false should work
5736 callback = callback || function() {};
5738 // no remote or from cache - just finish with callback
5739 // TODO in any case: insert cancel running load here..!
5741 if (!url || !bypassCache && $.data(a, 'cache.tabs')) {
5746 // load remote from here on
5748 var inner = function(parent) {
5749 var $parent = $(parent), $inner = $parent.find('*:last');
5750 return $inner.length && $inner.is(':not(img)') && $inner || $parent;
5752 var cleanup = function() {
5753 self.$tabs.filter('.ui-tabs-loading').removeClass('ui-tabs-loading')
5756 inner(this).parent().html(inner(this).data('label.tabs'));
5762 var label = inner(a).html();
5763 inner(a).wrapInner('<em></em>')
5764 .find('em').data('label.tabs', label).html(o.spinner);
5767 var ajaxOptions = $.extend({}, o.ajaxOptions, {
5769 success: function(r, s) {
5770 $(self._sanitizeSelector(a.hash)).html(r);
5774 $.data(a, 'cache.tabs', true); // if loaded once do not load them again
5777 self._trigger('load', null, self._ui(self.$tabs[index], self.$panels[index]));
5779 o.ajaxOptions.success(r, s);
5783 // This callback is required because the switch has to take
5784 // place after loading has completed. Call last in order to
5785 // fire load before show callback...
5790 // terminate pending requests from other tabs and restore tab label
5794 $a.addClass('ui-tabs-loading');
5795 self.xhr = $.ajax(ajaxOptions);
5798 url: function(index, url) {
5799 this.$tabs.eq(index).removeData('cache.tabs').data('load.tabs', url);
5802 length: function() {
5803 return this.$tabs.length;
5808 $.extend($.ui.tabs, {
5814 cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
5815 deselectable: false,
5818 fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
5819 idPrefix: 'ui-tabs-',
5820 panelTemplate: '<div></div>',
5821 spinner: 'Loading…',
5822 tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>'
5833 $.extend($.ui.tabs.prototype, {
5835 rotate: function(ms, continuing) {
5837 var self = this, t = this.options.selected;
5840 clearTimeout(self.rotation);
5841 self.rotation = setTimeout(function() {
5842 t = ++t < self.$tabs.length ? t : 0;
5849 this.element.bind('tabsshow', rotate); // will not be attached twice
5850 this.$tabs.bind(this.options.event + '.tabs', !continuing ?
5852 if (e.clientX) { // in case of a true click
5853 clearTimeout(self.rotation);
5854 self.element.unbind('tabsshow', rotate);
5858 t = self.options.selected;
5866 clearTimeout(self.rotation);
5867 this.element.unbind('tabsshow', rotate);
5868 this.$tabs.unbind(this.options.event + '.tabs', stop);
5875 * jQuery UI Datepicker 1.6rc6
5877 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
5878 * Dual licensed under the MIT (MIT-LICENSE.txt)
5879 * and GPL (GPL-LICENSE.txt) licenses.
5881 * http://docs.jquery.com/UI/Datepicker
5887 (function($) { // hide the namespace
5889 $.extend($.ui, { datepicker: { version: "1.6rc6" } });
5891 var PROP_NAME = 'datepicker';
5893 /* Date picker manager.
5894 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
5895 Settings for (groups of) date pickers are maintained in an instance object,
5896 allowing multiple different settings on the same page. */
5898 function Datepicker() {
5899 this.debug = false; // Change this to true to start debugging
5900 this._curInst = null; // The current instance in use
5901 this._keyEvent = false; // If the last event was a key event
5902 this._disabledInputs = []; // List of date picker inputs that have been disabled
5903 this._datepickerShowing = false; // True if the popup picker is showing , false if not
5904 this._inDialog = false; // True if showing within a "dialog", false if not
5905 this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
5906 this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
5907 this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
5908 this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
5909 this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
5910 this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
5911 this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
5912 this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
5913 this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
5914 this.regional = []; // Available regional settings, indexed by language code
5915 this.regional[''] = { // Default regional settings
5916 closeText: 'Done', // Display text for close link
5917 prevText: 'Prev', // Display text for previous month link
5918 nextText: 'Next', // Display text for next month link
5919 currentText: 'Today', // Display text for current month link
5920 monthNames: ['January','February','March','April','May','June',
5921 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
5922 monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
5923 dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
5924 dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
5925 dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
5926 dateFormat: 'mm/dd/yy', // See format options on parseDate
5927 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
5928 isRTL: false // True if right-to-left language, false if left-to-right
5930 this._defaults = { // Global defaults for all the date picker instances
5931 showOn: 'focus', // 'focus' for popup on focus,
5932 // 'button' for trigger button, or 'both' for either
5933 showAnim: 'show', // Name of jQuery animation for popup
5934 showOptions: {}, // Options for enhanced animations
5935 defaultDate: null, // Used when field is blank: actual date,
5936 // +/-number for offset from today, null for today
5937 appendText: '', // Display text following the input box, e.g. showing the format
5938 buttonText: '...', // Text for trigger button
5939 buttonImage: '', // URL for trigger button image
5940 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
5941 hideIfNoPrevNext: false, // True to hide next/previous month links
5942 // if not applicable, false to just disable them
5943 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
5944 gotoCurrent: false, // True if today link goes back to current selection instead
5945 changeMonth: false, // True if month can be selected directly, false if only prev/next
5946 changeYear: false, // True if year can be selected directly, false if only prev/next
5947 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
5948 yearRange: '-10:+10', // Range of years to display in drop-down,
5949 // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn)
5950 showOtherMonths: false, // True to show dates in other months, false to leave blank
5951 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
5952 // takes a Date and returns the number of the week for it
5953 shortYearCutoff: '+10', // Short year values < this are in the current century,
5954 // > this are in the previous century,
5955 // string value starting with '+' for current year + value
5956 minDate: null, // The earliest selectable date, or null for no limit
5957 maxDate: null, // The latest selectable date, or null for no limit
5958 duration: 'normal', // Duration of display/closure
5959 beforeShowDay: null, // Function that takes a date and returns an array with
5960 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
5961 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
5962 beforeShow: null, // Function that takes an input field and
5963 // returns a set of custom settings for the date picker
5964 onSelect: null, // Define a callback function when a date is selected
5965 onChangeMonthYear: null, // Define a callback function when the month or year is changed
5966 onClose: null, // Define a callback function when the datepicker is closed
5967 numberOfMonths: 1, // Number of months to show at a time
5968 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
5969 stepMonths: 1, // Number of months to step back/forward
5970 stepBigMonths: 12, // Number of months to step back/forward for the big links
5971 altField: '', // Selector for an alternate field to store selected dates into
5972 altFormat: '', // The date format to use for the alternate field
5973 constrainInput: true, // The input is constrained by the current date format
5974 showButtonPanel: false // True to show button panel, false to not show it
5976 $.extend(this._defaults, this.regional['']);
5977 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>');
5980 $.extend(Datepicker.prototype, {
5981 /* Class name added to elements to indicate already configured with a date picker. */
5982 markerClassName: 'hasDatepicker',
5984 /* Debug logging (if enabled). */
5987 console.log.apply('', arguments);
5990 /* Override the default settings for all instances of the date picker.
5991 @param settings object - the new settings to use as defaults (anonymous object)
5992 @return the manager object */
5993 setDefaults: function(settings) {
5994 extendRemove(this._defaults, settings || {});
5998 /* Attach the date picker to a jQuery selection.
5999 @param target element - the target input field or division or span
6000 @param settings object - the new settings to use for this date picker instance (anonymous) */
6001 _attachDatepicker: function(target, settings) {
6002 // check for settings on the control itself - in namespace 'date:'
6003 var inlineSettings = null;
6004 for (var attrName in this._defaults) {
6005 var attrValue = target.getAttribute('date:' + attrName);
6007 inlineSettings = inlineSettings || {};
6009 inlineSettings[attrName] = eval(attrValue);
6011 inlineSettings[attrName] = attrValue;
6015 var nodeName = target.nodeName.toLowerCase();
6016 var inline = (nodeName == 'div' || nodeName == 'span');
6018 target.id = 'dp' + (++this.uuid);
6019 var inst = this._newInst($(target), inline);
6020 inst.settings = $.extend({}, settings || {}, inlineSettings || {});
6021 if (nodeName == 'input') {
6022 this._connectDatepicker(target, inst);
6023 } else if (inline) {
6024 this._inlineDatepicker(target, inst);
6028 /* Create a new instance object. */
6029 _newInst: function(target, inline) {
6030 var id = target[0].id.replace(/([:\[\]\.])/g, '\\\\$1'); // escape jQuery meta chars
6031 return {id: id, input: target, // associated target
6032 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
6033 drawMonth: 0, drawYear: 0, // month being drawn
6034 inline: inline, // is datepicker inline or not
6035 dpDiv: (!inline ? this.dpDiv : // presentation div
6036 $('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
6039 /* Attach the date picker to an input field. */
6040 _connectDatepicker: function(target, inst) {
6041 var input = $(target);
6042 if (input.hasClass(this.markerClassName))
6044 var appendText = this._get(inst, 'appendText');
6045 var isRTL = this._get(inst, 'isRTL');
6047 input[isRTL ? 'before' : 'after']('<span class="' + this._appendClass + '">' + appendText + '</span>');
6048 var showOn = this._get(inst, 'showOn');
6049 if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
6050 input.focus(this._showDatepicker);
6051 if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
6052 var buttonText = this._get(inst, 'buttonText');
6053 var buttonImage = this._get(inst, 'buttonImage');
6054 var trigger = $(this._get(inst, 'buttonImageOnly') ?
6055 $('<img/>').addClass(this._triggerClass).
6056 attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
6057 $('<button type="button"></button>').addClass(this._triggerClass).
6058 html(buttonImage == '' ? buttonText : $('<img/>').attr(
6059 { src:buttonImage, alt:buttonText, title:buttonText })));
6060 input[isRTL ? 'before' : 'after'](trigger);
6061 trigger.click(function() {
6062 if ($.datepicker._datepickerShowing && $.datepicker._lastInput == target)
6063 $.datepicker._hideDatepicker();
6065 $.datepicker._showDatepicker(target);
6069 input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).
6070 bind("setData.datepicker", function(event, key, value) {
6071 inst.settings[key] = value;
6072 }).bind("getData.datepicker", function(event, key) {
6073 return this._get(inst, key);
6075 $.data(target, PROP_NAME, inst);
6078 /* Attach an inline date picker to a div. */
6079 _inlineDatepicker: function(target, inst) {
6080 var divSpan = $(target);
6081 if (divSpan.hasClass(this.markerClassName))
6083 divSpan.addClass(this.markerClassName).append(inst.dpDiv).
6084 bind("setData.datepicker", function(event, key, value){
6085 inst.settings[key] = value;
6086 }).bind("getData.datepicker", function(event, key){
6087 return this._get(inst, key);
6089 $.data(target, PROP_NAME, inst);
6090 this._setDate(inst, this._getDefaultDate(inst));
6091 this._updateDatepicker(inst);
6092 this._updateAlternate(inst);
6095 /* Pop-up the date picker in a "dialog" box.
6096 @param input element - ignored
6097 @param dateText string - the initial date to display (in the current format)
6098 @param onSelect function - the function(dateText) to call when a date is selected
6099 @param settings object - update the dialog date picker instance's settings (anonymous object)
6100 @param pos int[2] - coordinates for the dialog's position within the screen or
6101 event - with x/y coordinates or
6102 leave empty for default (screen centre)
6103 @return the manager object */
6104 _dialogDatepicker: function(input, dateText, onSelect, settings, pos) {
6105 var inst = this._dialogInst; // internal instance
6107 var id = 'dp' + (++this.uuid);
6108 this._dialogInput = $('<input type="text" id="' + id +
6109 '" size="1" style="position: absolute; top: -100px;"/>');
6110 this._dialogInput.keydown(this._doKeyDown);
6111 $('body').append(this._dialogInput);
6112 inst = this._dialogInst = this._newInst(this._dialogInput, false);
6114 $.data(this._dialogInput[0], PROP_NAME, inst);
6116 extendRemove(inst.settings, settings || {});
6117 this._dialogInput.val(dateText);
6119 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
6121 var browserWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
6122 var browserHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
6123 var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
6124 var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
6125 this._pos = // should use actual width/height below
6126 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
6129 // move input on screen for focus, but hidden behind dialog
6130 this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px');
6131 inst.settings.onSelect = onSelect;
6132 this._inDialog = true;
6133 this.dpDiv.addClass(this._dialogClass);
6134 this._showDatepicker(this._dialogInput[0]);
6136 $.blockUI(this.dpDiv);
6137 $.data(this._dialogInput[0], PROP_NAME, inst);
6141 /* Detach a datepicker from its control.
6142 @param target element - the target input field or division or span */
6143 _destroyDatepicker: function(target) {
6144 var $target = $(target);
6145 if (!$target.hasClass(this.markerClassName)) {
6148 var nodeName = target.nodeName.toLowerCase();
6149 $.removeData(target, PROP_NAME);
6150 if (nodeName == 'input') {
6151 $target.siblings('.' + this._appendClass).remove().end().
6152 siblings('.' + this._triggerClass).remove().end().
6153 removeClass(this.markerClassName).
6154 unbind('focus', this._showDatepicker).
6155 unbind('keydown', this._doKeyDown).
6156 unbind('keypress', this._doKeyPress);
6157 } else if (nodeName == 'div' || nodeName == 'span')
6158 $target.removeClass(this.markerClassName).empty();
6161 /* Enable the date picker to a jQuery selection.
6162 @param target element - the target input field or division or span */
6163 _enableDatepicker: function(target) {
6164 var $target = $(target);
6165 if (!$target.hasClass(this.markerClassName)) {
6168 var nodeName = target.nodeName.toLowerCase();
6169 if (nodeName == 'input') {
6170 target.disabled = false;
6171 $target.siblings('button.' + this._triggerClass).
6172 each(function() { this.disabled = false; }).end().
6173 siblings('img.' + this._triggerClass).
6174 css({opacity: '1.0', cursor: ''});
6176 else if (nodeName == 'div' || nodeName == 'span') {
6177 var inline = $target.children('.' + this._inlineClass);
6178 inline.children().removeClass('ui-state-disabled');
6180 this._disabledInputs = $.map(this._disabledInputs,
6181 function(value) { return (value == target ? null : value); }); // delete entry
6184 /* Disable the date picker to a jQuery selection.
6185 @param target element - the target input field or division or span */
6186 _disableDatepicker: function(target) {
6187 var $target = $(target);
6188 if (!$target.hasClass(this.markerClassName)) {
6191 var nodeName = target.nodeName.toLowerCase();
6192 if (nodeName == 'input') {
6193 target.disabled = true;
6194 $target.siblings('button.' + this._triggerClass).
6195 each(function() { this.disabled = true; }).end().
6196 siblings('img.' + this._triggerClass).
6197 css({opacity: '0.5', cursor: 'default'});
6199 else if (nodeName == 'div' || nodeName == 'span') {
6200 var inline = $target.children('.' + this._inlineClass);
6201 inline.children().addClass('ui-state-disabled');
6203 this._disabledInputs = $.map(this._disabledInputs,
6204 function(value) { return (value == target ? null : value); }); // delete entry
6205 this._disabledInputs[this._disabledInputs.length] = target;
6208 /* Is the first field in a jQuery collection disabled as a datepicker?
6209 @param target element - the target input field or division or span
6210 @return boolean - true if disabled, false if enabled */
6211 _isDisabledDatepicker: function(target) {
6215 for (var i = 0; i < this._disabledInputs.length; i++) {
6216 if (this._disabledInputs[i] == target)
6222 /* Retrieve the instance data for the target control.
6223 @param target element - the target input field or division or span
6224 @return object - the associated instance data
6225 @throws error if a jQuery problem getting data */
6226 _getInst: function(target) {
6228 return $.data(target, PROP_NAME);
6231 throw 'Missing instance data for this datepicker';
6235 /* Update the settings for a date picker attached to an input field or division.
6236 @param target element - the target input field or division or span
6237 @param name object - the new settings to update or
6238 string - the name of the setting to change or
6239 @param value any - the new value for the setting (omit if above is an object) */
6240 _optionDatepicker: function(target, name, value) {
6241 var settings = name || {};
6242 if (typeof name == 'string') {
6244 settings[name] = value;
6246 var inst = this._getInst(target);
6248 if (this._curInst == inst) {
6249 this._hideDatepicker(null);
6251 extendRemove(inst.settings, settings);
6252 var date = new Date();
6253 extendRemove(inst, {rangeStart: null, // start of range
6254 endDay: null, endMonth: null, endYear: null, // end of range
6255 selectedDay: date.getDate(), selectedMonth: date.getMonth(),
6256 selectedYear: date.getFullYear(), // starting point
6257 currentDay: date.getDate(), currentMonth: date.getMonth(),
6258 currentYear: date.getFullYear(), // current selection
6259 drawMonth: date.getMonth(), drawYear: date.getFullYear()}); // month being drawn
6260 this._updateDatepicker(inst);
6264 // change method deprecated
6265 _changeDatepicker: function(target, name, value) {
6266 this._optionDatepicker(target, name, value);
6269 /* Redraw the date picker attached to an input field or division.
6270 @param target element - the target input field or division or span */
6271 _refreshDatepicker: function(target) {
6272 var inst = this._getInst(target);
6274 this._updateDatepicker(inst);
6278 /* Set the dates for a jQuery selection.
6279 @param target element - the target input field or division or span
6280 @param date Date - the new date
6281 @param endDate Date - the new end date for a range (optional) */
6282 _setDateDatepicker: function(target, date, endDate) {
6283 var inst = this._getInst(target);
6285 this._setDate(inst, date, endDate);
6286 this._updateDatepicker(inst);
6287 this._updateAlternate(inst);
6291 /* Get the date(s) for the first entry in a jQuery selection.
6292 @param target element - the target input field or division or span
6293 @return Date - the current date or
6294 Date[2] - the current dates for a range */
6295 _getDateDatepicker: function(target) {
6296 var inst = this._getInst(target);
6297 if (inst && !inst.inline)
6298 this._setDateFromField(inst);
6299 return (inst ? this._getDate(inst) : null);
6302 /* Handle keystrokes. */
6303 _doKeyDown: function(event) {
6304 var inst = $.datepicker._getInst(event.target);
6306 var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
6307 inst._keyEvent = true;
6308 if ($.datepicker._datepickerShowing)
6309 switch (event.keyCode) {
6310 case 9: $.datepicker._hideDatepicker(null, '');
6311 break; // hide on tab out
6312 case 13: var sel = $('td.' + $.datepicker._dayOverClass +
6313 ', td.' + $.datepicker._currentClass, inst.dpDiv);
6315 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
6317 $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
6318 return false; // don't submit the form
6319 break; // select the value on enter
6320 case 27: $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
6321 break; // hide on escape
6322 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
6323 -$.datepicker._get(inst, 'stepBigMonths') :
6324 -$.datepicker._get(inst, 'stepMonths')), 'M');
6325 break; // previous month/year on page up/+ ctrl
6326 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
6327 +$.datepicker._get(inst, 'stepBigMonths') :
6328 +$.datepicker._get(inst, 'stepMonths')), 'M');
6329 break; // next month/year on page down/+ ctrl
6330 case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
6331 handled = event.ctrlKey || event.metaKey;
6332 break; // clear on ctrl or command +end
6333 case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
6334 handled = event.ctrlKey || event.metaKey;
6335 break; // current on ctrl or command +home
6336 case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
6337 handled = event.ctrlKey || event.metaKey;
6338 // -1 day on ctrl or command +left
6339 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
6340 -$.datepicker._get(inst, 'stepBigMonths') :
6341 -$.datepicker._get(inst, 'stepMonths')), 'M');
6342 // next month/year on alt +left on Mac
6344 case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
6345 handled = event.ctrlKey || event.metaKey;
6346 break; // -1 week on ctrl or command +up
6347 case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
6348 handled = event.ctrlKey || event.metaKey;
6349 // +1 day on ctrl or command +right
6350 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
6351 +$.datepicker._get(inst, 'stepBigMonths') :
6352 +$.datepicker._get(inst, 'stepMonths')), 'M');
6353 // next month/year on alt +right
6355 case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
6356 handled = event.ctrlKey || event.metaKey;
6357 break; // +1 week on ctrl or command +down
6358 default: handled = false;
6360 else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
6361 $.datepicker._showDatepicker(this);
6366 event.preventDefault();
6367 event.stopPropagation();
6371 /* Filter entered characters - based on date format. */
6372 _doKeyPress: function(event) {
6373 var inst = $.datepicker._getInst(event.target);
6374 if ($.datepicker._get(inst, 'constrainInput')) {
6375 var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
6376 var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
6377 return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
6381 /* Pop-up the date picker for a given input field.
6382 @param input element - the input field attached to the date picker or
6383 event - if triggered by focus */
6384 _showDatepicker: function(input) {
6385 input = input.target || input;
6386 if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
6387 input = $('input', input.parentNode)[0];
6388 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
6390 var inst = $.datepicker._getInst(input);
6391 var beforeShow = $.datepicker._get(inst, 'beforeShow');
6392 extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
6393 $.datepicker._hideDatepicker(null, '');
6394 $.datepicker._lastInput = input;
6395 $.datepicker._setDateFromField(inst);
6396 if ($.datepicker._inDialog) // hide cursor
6398 if (!$.datepicker._pos) { // position below input
6399 $.datepicker._pos = $.datepicker._findPos(input);
6400 $.datepicker._pos[1] += input.offsetHeight; // add the height
6402 var isFixed = false;
6403 $(input).parents().each(function() {
6404 isFixed |= $(this).css('position') == 'fixed';
6407 if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
6408 $.datepicker._pos[0] -= document.documentElement.scrollLeft;
6409 $.datepicker._pos[1] -= document.documentElement.scrollTop;
6411 var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
6412 $.datepicker._pos = null;
6413 inst.rangeStart = null;
6414 // determine sizing offscreen
6415 inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
6416 $.datepicker._updateDatepicker(inst);
6417 // fix width for dynamic number of date pickers
6418 // and adjust position before showing
6419 offset = $.datepicker._checkOffset(inst, offset, isFixed);
6420 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
6421 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
6422 left: offset.left + 'px', top: offset.top + 'px'});
6424 var showAnim = $.datepicker._get(inst, 'showAnim') || 'show';
6425 var duration = $.datepicker._get(inst, 'duration');
6426 var postProcess = function() {
6427 $.datepicker._datepickerShowing = true;
6428 if ($.browser.msie && parseInt($.browser.version,10) < 7) // fix IE < 7 select problems
6429 $('iframe.ui-datepicker-cover').css({width: inst.dpDiv.width() + 4,
6430 height: inst.dpDiv.height() + 4});
6432 if ($.effects && $.effects[showAnim])
6433 inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
6435 inst.dpDiv[showAnim](duration, postProcess);
6438 if (inst.input[0].type != 'hidden')
6439 inst.input[0].focus();
6440 $.datepicker._curInst = inst;
6444 /* Generate the date picker content. */
6445 _updateDatepicker: function(inst) {
6446 var dims = {width: inst.dpDiv.width() + 4,
6447 height: inst.dpDiv.height() + 4};
6449 inst.dpDiv.empty().append(this._generateHTML(inst))
6450 .find('iframe.ui-datepicker-cover').
6451 css({width: dims.width, height: dims.height})
6453 .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
6454 .bind('mouseout', function(){
6455 $(this).removeClass('ui-state-hover');
6456 if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
6457 if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
6459 .bind('mouseover', function(){
6460 if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
6461 $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
6462 $(this).addClass('ui-state-hover');
6463 if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
6464 if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
6468 .find('.' + this._dayOverClass + ' a')
6469 .trigger('mouseover')
6471 var numMonths = this._getNumberOfMonths(inst);
6472 var cols = numMonths[1];
6475 inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
6477 inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
6479 inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
6480 'Class']('ui-datepicker-multi');
6481 inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
6482 'Class']('ui-datepicker-rtl');
6483 if (inst.input && inst.input[0].type != 'hidden' && inst == $.datepicker._curInst)
6484 $(inst.input[0]).focus();
6487 /* Check positioning to remain on screen. */
6488 _checkOffset: function(inst, offset, isFixed) {
6489 var dpWidth = inst.dpDiv.outerWidth();
6490 var dpHeight = inst.dpDiv.outerHeight();
6491 var inputWidth = inst.input ? inst.input.outerWidth() : 0;
6492 var inputHeight = inst.input ? inst.input.outerHeight() : 0;
6493 var viewWidth = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) + $(document).scrollLeft();
6494 var viewHeight = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) + $(document).scrollTop();
6496 offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
6497 offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
6498 offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
6500 // now check if datepicker is showing outside window viewport - move to a better place if so.
6501 offset.left -= (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? Math.abs(offset.left + dpWidth - viewWidth) : 0;
6502 offset.top -= (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? Math.abs(offset.top + dpHeight + inputHeight*2 - viewHeight) : 0;
6507 /* Find an object's position on the screen. */
6508 _findPos: function(obj) {
6509 while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
6510 obj = obj.nextSibling;
6512 var position = $(obj).offset();
6513 return [position.left, position.top];
6516 /* Hide the date picker from view.
6517 @param input element - the input field attached to the date picker
6518 @param duration string - the duration over which to close the date picker */
6519 _hideDatepicker: function(input, duration) {
6520 var inst = this._curInst;
6521 if (!inst || (input && inst != $.data(input, PROP_NAME)))
6524 this._selectDate('#' + inst.id, this._formatDate(inst,
6525 inst.currentDay, inst.currentMonth, inst.currentYear));
6526 inst.stayOpen = false;
6527 if (this._datepickerShowing) {
6528 duration = (duration != null ? duration : this._get(inst, 'duration'));
6529 var showAnim = this._get(inst, 'showAnim');
6530 var postProcess = function() {
6531 $.datepicker._tidyDialog(inst);
6533 if (duration != '' && $.effects && $.effects[showAnim])
6534 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'),
6535 duration, postProcess);
6537 inst.dpDiv[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' :
6538 (showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess);
6540 this._tidyDialog(inst);
6541 var onClose = this._get(inst, 'onClose');
6543 onClose.apply((inst.input ? inst.input[0] : null),
6544 [(inst.input ? inst.input.val() : ''), inst]); // trigger custom callback
6545 this._datepickerShowing = false;
6546 this._lastInput = null;
6547 if (this._inDialog) {
6548 this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
6551 $('body').append(this.dpDiv);
6554 this._inDialog = false;
6556 this._curInst = null;
6559 /* Tidy up after a dialog display. */
6560 _tidyDialog: function(inst) {
6561 inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
6564 /* Close date picker if clicked elsewhere. */
6565 _checkExternalClick: function(event) {
6566 if (!$.datepicker._curInst)
6568 var $target = $(event.target);
6569 if (($target.parents('#' + $.datepicker._mainDivId).length == 0) &&
6570 !$target.hasClass($.datepicker.markerClassName) &&
6571 !$target.hasClass($.datepicker._triggerClass) &&
6572 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
6573 $.datepicker._hideDatepicker(null, '');
6576 /* Adjust one of the date sub-fields. */
6577 _adjustDate: function(id, offset, period) {
6579 var inst = this._getInst(target[0]);
6580 if (this._isDisabledDatepicker(target[0])) {
6583 this._adjustInstDate(inst, offset +
6584 (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
6586 this._updateDatepicker(inst);
6589 /* Action for current link. */
6590 _gotoToday: function(id) {
6592 var inst = this._getInst(target[0]);
6593 if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
6594 inst.selectedDay = inst.currentDay;
6595 inst.drawMonth = inst.selectedMonth = inst.currentMonth;
6596 inst.drawYear = inst.selectedYear = inst.currentYear;
6599 var date = new Date();
6600 inst.selectedDay = date.getDate();
6601 inst.drawMonth = inst.selectedMonth = date.getMonth();
6602 inst.drawYear = inst.selectedYear = date.getFullYear();
6604 this._notifyChange(inst);
6605 this._adjustDate(target);
6608 /* Action for selecting a new month/year. */
6609 _selectMonthYear: function(id, select, period) {
6611 var inst = this._getInst(target[0]);
6612 inst._selectingMonthYear = false;
6613 inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
6614 inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
6615 parseInt(select.options[select.selectedIndex].value,10);
6616 this._notifyChange(inst);
6617 this._adjustDate(target);
6620 /* Restore input focus after not changing month/year. */
6621 _clickMonthYear: function(id) {
6623 var inst = this._getInst(target[0]);
6624 if (inst.input && inst._selectingMonthYear && !$.browser.msie)
6625 inst.input[0].focus();
6626 inst._selectingMonthYear = !inst._selectingMonthYear;
6629 /* Action for selecting a day. */
6630 _selectDay: function(id, month, year, td) {
6632 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
6635 var inst = this._getInst(target[0]);
6636 inst.selectedDay = inst.currentDay = $('a', td).html();
6637 inst.selectedMonth = inst.currentMonth = month;
6638 inst.selectedYear = inst.currentYear = year;
6639 if (inst.stayOpen) {
6640 inst.endDay = inst.endMonth = inst.endYear = null;
6642 this._selectDate(id, this._formatDate(inst,
6643 inst.currentDay, inst.currentMonth, inst.currentYear));
6644 if (inst.stayOpen) {
6645 inst.rangeStart = this._daylightSavingAdjust(
6646 new Date(inst.currentYear, inst.currentMonth, inst.currentDay));
6647 this._updateDatepicker(inst);
6651 /* Erase the input field and hide the date picker. */
6652 _clearDate: function(id) {
6654 var inst = this._getInst(target[0]);
6655 inst.stayOpen = false;
6656 inst.endDay = inst.endMonth = inst.endYear = inst.rangeStart = null;
6657 this._selectDate(target, '');
6660 /* Update the input field with the selected date. */
6661 _selectDate: function(id, dateStr) {
6663 var inst = this._getInst(target[0]);
6664 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
6666 inst.input.val(dateStr);
6667 this._updateAlternate(inst);
6668 var onSelect = this._get(inst, 'onSelect');
6670 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
6671 else if (inst.input)
6672 inst.input.trigger('change'); // fire the change event
6674 this._updateDatepicker(inst);
6675 else if (!inst.stayOpen) {
6676 this._hideDatepicker(null, this._get(inst, 'duration'));
6677 this._lastInput = inst.input[0];
6678 if (typeof(inst.input[0]) != 'object')
6679 inst.input[0].focus(); // restore focus
6680 this._lastInput = null;
6684 /* Update any alternate field to synchronise with the main field. */
6685 _updateAlternate: function(inst) {
6686 var altField = this._get(inst, 'altField');
6687 if (altField) { // update alternate field too
6688 var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
6689 var date = this._getDate(inst);
6690 dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
6691 $(altField).each(function() { $(this).val(dateStr); });
6695 /* Set as beforeShowDay function to prevent selection of weekends.
6696 @param date Date - the date to customise
6697 @return [boolean, string] - is this date selectable?, what is its CSS class? */
6698 noWeekends: function(date) {
6699 var day = date.getDay();
6700 return [(day > 0 && day < 6), ''];
6703 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
6704 @param date Date - the date to get the week for
6705 @return number - the number of the week within the year that contains this date */
6706 iso8601Week: function(date) {
6707 var checkDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
6708 var firstMon = new Date(checkDate.getFullYear(), 1 - 1, 4); // First week always contains 4 Jan
6709 var firstDay = firstMon.getDay() || 7; // Day of week: Mon = 1, ..., Sun = 7
6710 firstMon.setDate(firstMon.getDate() + 1 - firstDay); // Preceding Monday
6711 if (firstDay < 4 && checkDate < firstMon) { // Adjust first three days in year if necessary
6712 checkDate.setDate(checkDate.getDate() - 3); // Generate for previous year
6713 return $.datepicker.iso8601Week(checkDate);
6714 } else if (checkDate > new Date(checkDate.getFullYear(), 12 - 1, 28)) { // Check last three days in year
6715 firstDay = new Date(checkDate.getFullYear() + 1, 1 - 1, 4).getDay() || 7;
6716 if (firstDay > 4 && (checkDate.getDay() || 7) < firstDay - 3) { // Adjust if necessary
6720 return Math.floor(((checkDate - firstMon) / 86400000) / 7) + 1; // Weeks to given date
6723 /* Parse a string value into a date object.
6724 See formatDate below for the possible formats.
6726 @param format string - the expected format of the date
6727 @param value string - the date in the above format
6728 @param settings Object - attributes include:
6729 shortYearCutoff number - the cutoff year for determining the century (optional)
6730 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
6731 dayNames string[7] - names of the days from Sunday (optional)
6732 monthNamesShort string[12] - abbreviated names of the months (optional)
6733 monthNames string[12] - names of the months (optional)
6734 @return Date - the extracted date value or null if value is blank */
6735 parseDate: function (format, value, settings) {
6736 if (format == null || value == null)
6737 throw 'Invalid arguments';
6738 value = (typeof value == 'object' ? value.toString() : value + '');
6741 var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
6742 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
6743 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
6744 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
6745 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
6750 var literal = false;
6751 // Check whether a format character is doubled
6752 var lookAhead = function(match) {
6753 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
6758 // Extract a number from the string value
6759 var getNumber = function(match) {
6761 var origSize = (match == '@' ? 14 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2)));
6762 var size = origSize;
6764 while (size > 0 && iValue < value.length &&
6765 value.charAt(iValue) >= '0' && value.charAt(iValue) <= '9') {
6766 num = num * 10 + parseInt(value.charAt(iValue++),10);
6769 if (size == origSize)
6770 throw 'Missing number at position ' + iValue;
6773 // Extract a name from the string value and convert to an index
6774 var getName = function(match, shortNames, longNames) {
6775 var names = (lookAhead(match) ? longNames : shortNames);
6777 for (var j = 0; j < names.length; j++)
6778 size = Math.max(size, names[j].length);
6781 while (size > 0 && iValue < value.length) {
6782 name += value.charAt(iValue++);
6783 for (var i = 0; i < names.length; i++)
6784 if (name == names[i])
6788 throw 'Unknown name at position ' + iInit;
6790 // Confirm that a literal character matches the string value
6791 var checkLiteral = function() {
6792 if (value.charAt(iValue) != format.charAt(iFormat))
6793 throw 'Unexpected literal at position ' + iValue;
6797 for (var iFormat = 0; iFormat < format.length; iFormat++) {
6799 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
6804 switch (format.charAt(iFormat)) {
6806 day = getNumber('d');
6809 getName('D', dayNamesShort, dayNames);
6812 doy = getNumber('o');
6815 month = getNumber('m');
6818 month = getName('M', monthNamesShort, monthNames);
6821 year = getNumber('y');
6824 var date = new Date(getNumber('@'));
6825 year = date.getFullYear();
6826 month = date.getMonth() + 1;
6827 day = date.getDate();
6840 year = new Date().getFullYear();
6841 else if (year < 100)
6842 year += new Date().getFullYear() - new Date().getFullYear() % 100 +
6843 (year <= shortYearCutoff ? 0 : -100);
6848 var dim = this._getDaysInMonth(year, month - 1);
6855 var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
6856 if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
6857 throw 'Invalid date'; // E.g. 31/02/*
6861 /* Standard date formats. */
6862 ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
6863 COOKIE: 'D, dd M yy',
6864 ISO_8601: 'yy-mm-dd',
6865 RFC_822: 'D, d M y',
6866 RFC_850: 'DD, dd-M-y',
6867 RFC_1036: 'D, d M y',
6868 RFC_1123: 'D, d M yy',
6869 RFC_2822: 'D, d M yy',
6870 RSS: 'D, d M y', // RFC 822
6872 W3C: 'yy-mm-dd', // ISO 8601
6874 /* Format a date object into a string value.
6875 The format can be combinations of the following:
6876 d - day of month (no leading zero)
6877 dd - day of month (two digit)
6878 o - day of year (no leading zeros)
6879 oo - day of year (three digit)
6882 m - month of year (no leading zero)
6883 mm - month of year (two digit)
6884 M - month name short
6885 MM - month name long
6886 y - year (two digit)
6887 yy - year (four digit)
6888 @ - Unix timestamp (ms since 01/01/1970)
6889 '...' - literal text
6892 @param format string - the desired format of the date
6893 @param date Date - the date value to format
6894 @param settings Object - attributes include:
6895 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
6896 dayNames string[7] - names of the days from Sunday (optional)
6897 monthNamesShort string[12] - abbreviated names of the months (optional)
6898 monthNames string[12] - names of the months (optional)
6899 @return string - the date in the above format */
6900 formatDate: function (format, date, settings) {
6903 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
6904 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
6905 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
6906 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
6907 // Check whether a format character is doubled
6908 var lookAhead = function(match) {
6909 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
6914 // Format a number, with leading zero if necessary
6915 var formatNumber = function(match, value, len) {
6916 var num = '' + value;
6917 if (lookAhead(match))
6918 while (num.length < len)
6922 // Format a name, short or long as requested
6923 var formatName = function(match, value, shortNames, longNames) {
6924 return (lookAhead(match) ? longNames[value] : shortNames[value]);
6927 var literal = false;
6929 for (var iFormat = 0; iFormat < format.length; iFormat++) {
6931 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
6934 output += format.charAt(iFormat);
6936 switch (format.charAt(iFormat)) {
6938 output += formatNumber('d', date.getDate(), 2);
6941 output += formatName('D', date.getDay(), dayNamesShort, dayNames);
6944 var doy = date.getDate();
6945 for (var m = date.getMonth() - 1; m >= 0; m--)
6946 doy += this._getDaysInMonth(date.getFullYear(), m);
6947 output += formatNumber('o', doy, 3);
6950 output += formatNumber('m', date.getMonth() + 1, 2);
6953 output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
6956 output += (lookAhead('y') ? date.getFullYear() :
6957 (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
6960 output += date.getTime();
6969 output += format.charAt(iFormat);
6975 /* Extract all possible characters from the date format. */
6976 _possibleChars: function (format) {
6978 var literal = false;
6979 for (var iFormat = 0; iFormat < format.length; iFormat++)
6981 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
6984 chars += format.charAt(iFormat);
6986 switch (format.charAt(iFormat)) {
6987 case 'd': case 'm': case 'y': case '@':
6988 chars += '0123456789';
6991 return null; // Accept anything
6999 chars += format.charAt(iFormat);
7004 /* Get a setting value, defaulting if necessary. */
7005 _get: function(inst, name) {
7006 return inst.settings[name] !== undefined ?
7007 inst.settings[name] : this._defaults[name];
7010 /* Parse existing date and initialise date picker. */
7011 _setDateFromField: function(inst) {
7012 var dateFormat = this._get(inst, 'dateFormat');
7013 var dates = inst.input ? inst.input.val() : null;
7014 inst.endDay = inst.endMonth = inst.endYear = null;
7015 var date = defaultDate = this._getDefaultDate(inst);
7016 var settings = this._getFormatConfig(inst);
7018 date = this.parseDate(dateFormat, dates, settings) || defaultDate;
7023 inst.selectedDay = date.getDate();
7024 inst.drawMonth = inst.selectedMonth = date.getMonth();
7025 inst.drawYear = inst.selectedYear = date.getFullYear();
7026 inst.currentDay = (dates ? date.getDate() : 0);
7027 inst.currentMonth = (dates ? date.getMonth() : 0);
7028 inst.currentYear = (dates ? date.getFullYear() : 0);
7029 this._adjustInstDate(inst);
7032 /* Retrieve the default date shown on opening. */
7033 _getDefaultDate: function(inst) {
7034 var date = this._determineDate(this._get(inst, 'defaultDate'), new Date());
7035 var minDate = this._getMinMaxDate(inst, 'min', true);
7036 var maxDate = this._getMinMaxDate(inst, 'max');
7037 date = (minDate && date < minDate ? minDate : date);
7038 date = (maxDate && date > maxDate ? maxDate : date);
7042 /* A date may be specified as an exact value or a relative one. */
7043 _determineDate: function(date, defaultDate) {
7044 var offsetNumeric = function(offset) {
7045 var date = new Date();
7046 date.setDate(date.getDate() + offset);
7049 var offsetString = function(offset, getDaysInMonth) {
7050 var date = new Date();
7051 var year = date.getFullYear();
7052 var month = date.getMonth();
7053 var day = date.getDate();
7054 var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
7055 var matches = pattern.exec(offset);
7057 switch (matches[2] || 'd') {
7058 case 'd' : case 'D' :
7059 day += parseInt(matches[1],10); break;
7060 case 'w' : case 'W' :
7061 day += parseInt(matches[1],10) * 7; break;
7062 case 'm' : case 'M' :
7063 month += parseInt(matches[1],10);
7064 day = Math.min(day, getDaysInMonth(year, month));
7066 case 'y': case 'Y' :
7067 year += parseInt(matches[1],10);
7068 day = Math.min(day, getDaysInMonth(year, month));
7071 matches = pattern.exec(offset);
7073 return new Date(year, month, day);
7075 date = (date == null ? defaultDate :
7076 (typeof date == 'string' ? offsetString(date, this._getDaysInMonth) :
7077 (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
7078 date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
7083 date.setMilliseconds(0);
7085 return this._daylightSavingAdjust(date);
7088 /* Handle switch to/from daylight saving.
7089 Hours may be non-zero on daylight saving cut-over:
7090 > 12 when midnight changeover, but then cannot generate
7091 midnight datetime, so jump to 1AM, otherwise reset.
7092 @param date (Date) the date to check
7093 @return (Date) the corrected date */
7094 _daylightSavingAdjust: function(date) {
7095 if (!date) return null;
7096 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
7100 /* Set the date(s) directly. */
7101 _setDate: function(inst, date, endDate) {
7102 var clear = !(date);
7103 var origMonth = inst.selectedMonth;
7104 var origYear = inst.selectedYear;
7105 date = this._determineDate(date, new Date());
7106 inst.selectedDay = inst.currentDay = date.getDate();
7107 inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
7108 inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
7109 if (origMonth != inst.selectedMonth || origYear != inst.selectedYear)
7110 this._notifyChange(inst);
7111 this._adjustInstDate(inst);
7113 inst.input.val(clear ? '' : this._formatDate(inst));
7117 /* Retrieve the date(s) directly. */
7118 _getDate: function(inst) {
7119 var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
7120 this._daylightSavingAdjust(new Date(
7121 inst.currentYear, inst.currentMonth, inst.currentDay)));
7125 /* Generate the HTML for the current state of the date picker. */
7126 _generateHTML: function(inst) {
7127 var today = new Date();
7128 today = this._daylightSavingAdjust(
7129 new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
7130 var isRTL = this._get(inst, 'isRTL');
7131 var showButtonPanel = this._get(inst, 'showButtonPanel');
7132 var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
7133 var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
7134 var numMonths = this._getNumberOfMonths(inst);
7135 var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
7136 var stepMonths = this._get(inst, 'stepMonths');
7137 var stepBigMonths = this._get(inst, 'stepBigMonths');
7138 var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
7139 var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
7140 new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
7141 var minDate = this._getMinMaxDate(inst, 'min', true);
7142 var maxDate = this._getMinMaxDate(inst, 'max');
7143 var drawMonth = inst.drawMonth - showCurrentAtPos;
7144 var drawYear = inst.drawYear;
7145 if (drawMonth < 0) {
7150 var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
7151 maxDate.getMonth() - numMonths[1] + 1, maxDate.getDate()));
7152 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
7153 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
7155 if (drawMonth < 0) {
7161 inst.drawMonth = drawMonth;
7162 inst.drawYear = drawYear;
7163 var prevText = this._get(inst, 'prevText');
7164 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
7165 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
7166 this._getFormatConfig(inst)));
7167 var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
7168 '<a class="ui-datepicker-prev ui-corner-all" onclick="jQuery.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
7169 ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
7170 (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>'));
7171 var nextText = this._get(inst, 'nextText');
7172 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
7173 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
7174 this._getFormatConfig(inst)));
7175 var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
7176 '<a class="ui-datepicker-next ui-corner-all" onclick="jQuery.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
7177 ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
7178 (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>'));
7179 var currentText = this._get(inst, 'currentText');
7180 var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
7181 currentText = (!navigationAsDateFormat ? currentText :
7182 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
7183 var controls = '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="jQuery.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>';
7184 var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
7185 (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="jQuery.datepicker._gotoToday(\'#' + inst.id + '\');"' +
7186 '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
7187 var firstDay = parseInt(this._get(inst, 'firstDay'),10);
7188 firstDay = (isNaN(firstDay) ? 0 : firstDay);
7189 var dayNames = this._get(inst, 'dayNames');
7190 var dayNamesShort = this._get(inst, 'dayNamesShort');
7191 var dayNamesMin = this._get(inst, 'dayNamesMin');
7192 var monthNames = this._get(inst, 'monthNames');
7193 var monthNamesShort = this._get(inst, 'monthNamesShort');
7194 var beforeShowDay = this._get(inst, 'beforeShowDay');
7195 var showOtherMonths = this._get(inst, 'showOtherMonths');
7196 var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
7197 var endDate = inst.endDay ? this._daylightSavingAdjust(
7198 new Date(inst.endYear, inst.endMonth, inst.endDay)) : currentDate;
7199 var defaultDate = this._getDefaultDate(inst);
7201 for (var row = 0; row < numMonths[0]; row++) {
7203 for (var col = 0; col < numMonths[1]; col++) {
7204 var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
7205 var cornerClass = ' ui-corner-all';
7208 calender += '<div class="ui-datepicker-group ui-datepicker-group-';
7210 case 0: calender += 'first'; cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
7211 case numMonths[1]-1: calender += 'last'; cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
7212 default: calender += 'middle'; cornerClass = ''; break;
7216 calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
7217 (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
7218 (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
7219 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
7220 selectedDate, row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
7221 '</div><table class="ui-datepicker-calendar"><thead>' +
7224 for (var dow = 0; dow < 7; dow++) { // days of the week
7225 var day = (dow + firstDay) % 7;
7226 thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
7227 '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
7229 calender += thead + '</tr></thead><tbody>';
7230 var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
7231 if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
7232 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
7233 var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
7234 var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
7235 var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
7236 for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
7239 for (var dow = 0; dow < 7; dow++) { // create date picker days
7240 var daySettings = (beforeShowDay ?
7241 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
7242 var otherMonth = (printDate.getMonth() != drawMonth);
7243 var unselectable = otherMonth || !daySettings[0] ||
7244 (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
7245 tbody += '<td class="' +
7246 ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
7247 (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
7248 ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
7249 (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
7250 // or defaultDate is current printedDate and defaultDate is selectedDate
7251 ' ' + this._dayOverClass : '') + // highlight selected day
7252 (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
7253 (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
7254 (printDate.getTime() >= currentDate.getTime() && printDate.getTime() <= endDate.getTime() ? // in current range
7255 ' ' + this._currentClass : '') + // highlight selected day
7256 (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
7257 ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
7258 (unselectable ? '' : ' onclick="jQuery.datepicker._selectDay(\'#' +
7259 inst.id + '\',' + drawMonth + ',' + drawYear + ', this);return false;"') + '>' + // actions
7260 (otherMonth ? (showOtherMonths ? printDate.getDate() : ' ') : // display for other months
7261 (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
7262 (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
7263 (printDate.getTime() >= currentDate.getTime() && printDate.getTime() <= endDate.getTime() ? // in current range
7264 ' ui-state-active' : '') + // highlight selected day
7265 '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display for this month
7266 printDate.setDate(printDate.getDate() + 1);
7267 printDate = this._daylightSavingAdjust(printDate);
7269 calender += tbody + '</tr>';
7272 if (drawMonth > 11) {
7276 calender += '</tbody></table>' + (isMultiMonth ? '</div>' : '');
7281 html += (!inst.inline ? buttonPanel : '') +
7282 ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
7283 '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
7284 inst._keyEvent = false;
7288 /* Generate the month and year header. */
7289 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
7290 selectedDate, secondary, monthNames, monthNamesShort) {
7291 minDate = (inst.rangeStart && minDate && selectedDate < minDate ? selectedDate : minDate);
7292 var changeMonth = this._get(inst, 'changeMonth');
7293 var changeYear = this._get(inst, 'changeYear');
7294 var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
7295 var html = '<div class="ui-datepicker-title">';
7298 if (secondary || !changeMonth)
7299 monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span> ';
7301 var inMinYear = (minDate && minDate.getFullYear() == drawYear);
7302 var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
7303 monthHtml += '<select class="ui-datepicker-month" ' +
7304 'onchange="jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
7305 'onclick="jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
7307 for (var month = 0; month < 12; month++) {
7308 if ((!inMinYear || month >= minDate.getMonth()) &&
7309 (!inMaxYear || month <= maxDate.getMonth()))
7310 monthHtml += '<option value="' + month + '"' +
7311 (month == drawMonth ? ' selected="selected"' : '') +
7312 '>' + monthNamesShort[month] + '</option>';
7314 monthHtml += '</select>';
7316 if (!showMonthAfterYear)
7317 html += monthHtml + ((secondary || changeMonth || changeYear) && (!(changeMonth && changeYear)) ? ' ' : '');
7319 if (secondary || !changeYear)
7320 html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
7322 // determine range of years to display
7323 var years = this._get(inst, 'yearRange').split(':');
7326 if (years.length != 2) {
7327 year = drawYear - 10;
7328 endYear = drawYear + 10;
7329 } else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') {
7330 year = drawYear + parseInt(years[0], 10);
7331 endYear = drawYear + parseInt(years[1], 10);
7333 year = parseInt(years[0], 10);
7334 endYear = parseInt(years[1], 10);
7336 year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
7337 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
7338 html += '<select class="ui-datepicker-year" ' +
7339 'onchange="jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
7340 'onclick="jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
7342 for (; year <= endYear; year++) {
7343 html += '<option value="' + year + '"' +
7344 (year == drawYear ? ' selected="selected"' : '') +
7345 '>' + year + '</option>';
7347 html += '</select>';
7349 if (showMonthAfterYear)
7350 html += (secondary || changeMonth || changeYear ? ' ' : '') + monthHtml;
7351 html += '</div>'; // Close datepicker_header
7355 /* Adjust one of the date sub-fields. */
7356 _adjustInstDate: function(inst, offset, period) {
7357 var year = inst.drawYear + (period == 'Y' ? offset : 0);
7358 var month = inst.drawMonth + (period == 'M' ? offset : 0);
7359 var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
7360 (period == 'D' ? offset : 0);
7361 var date = this._daylightSavingAdjust(new Date(year, month, day));
7362 // ensure it is within the bounds set
7363 var minDate = this._getMinMaxDate(inst, 'min', true);
7364 var maxDate = this._getMinMaxDate(inst, 'max');
7365 date = (minDate && date < minDate ? minDate : date);
7366 date = (maxDate && date > maxDate ? maxDate : date);
7367 inst.selectedDay = date.getDate();
7368 inst.drawMonth = inst.selectedMonth = date.getMonth();
7369 inst.drawYear = inst.selectedYear = date.getFullYear();
7370 if (period == 'M' || period == 'Y')
7371 this._notifyChange(inst);
7374 /* Notify change of month/year. */
7375 _notifyChange: function(inst) {
7376 var onChange = this._get(inst, 'onChangeMonthYear');
7378 onChange.apply((inst.input ? inst.input[0] : null),
7379 [inst.selectedYear, inst.selectedMonth + 1, inst]);
7382 /* Determine the number of months to show. */
7383 _getNumberOfMonths: function(inst) {
7384 var numMonths = this._get(inst, 'numberOfMonths');
7385 return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
7388 /* Determine the current maximum date - ensure no time components are set - may be overridden for a range. */
7389 _getMinMaxDate: function(inst, minMax, checkRange) {
7390 var date = this._determineDate(this._get(inst, minMax + 'Date'), null);
7391 return (!checkRange || !inst.rangeStart ? date :
7392 (!date || inst.rangeStart > date ? inst.rangeStart : date));
7395 /* Find the number of days in a given month. */
7396 _getDaysInMonth: function(year, month) {
7397 return 32 - new Date(year, month, 32).getDate();
7400 /* Find the day of the week of the first of a month. */
7401 _getFirstDayOfMonth: function(year, month) {
7402 return new Date(year, month, 1).getDay();
7405 /* Determines if we should allow a "next/prev" month display change. */
7406 _canAdjustMonth: function(inst, offset, curYear, curMonth) {
7407 var numMonths = this._getNumberOfMonths(inst);
7408 var date = this._daylightSavingAdjust(new Date(
7409 curYear, curMonth + (offset < 0 ? offset : numMonths[1]), 1));
7411 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
7412 return this._isInRange(inst, date);
7415 /* Is the given date in the accepted range? */
7416 _isInRange: function(inst, date) {
7417 // during range selection, use minimum of selected date and range start
7418 var newMinDate = (!inst.rangeStart ? null : this._daylightSavingAdjust(
7419 new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay)));
7420 newMinDate = (newMinDate && inst.rangeStart < newMinDate ? inst.rangeStart : newMinDate);
7421 var minDate = newMinDate || this._getMinMaxDate(inst, 'min');
7422 var maxDate = this._getMinMaxDate(inst, 'max');
7423 return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
7426 /* Provide the configuration settings for formatting/parsing. */
7427 _getFormatConfig: function(inst) {
7428 var shortYearCutoff = this._get(inst, 'shortYearCutoff');
7429 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
7430 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
7431 return {shortYearCutoff: shortYearCutoff,
7432 dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
7433 monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
7436 /* Format the given date for display. */
7437 _formatDate: function(inst, day, month, year) {
7439 inst.currentDay = inst.selectedDay;
7440 inst.currentMonth = inst.selectedMonth;
7441 inst.currentYear = inst.selectedYear;
7443 var date = (day ? (typeof day == 'object' ? day :
7444 this._daylightSavingAdjust(new Date(year, month, day))) :
7445 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
7446 return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
7450 /* jQuery extend now ignores nulls! */
7451 function extendRemove(target, props) {
7452 $.extend(target, props);
7453 for (var name in props)
7454 if (props[name] == null || props[name] == undefined)
7455 target[name] = props[name];
7459 /* Determine whether an object is an array. */
7460 function isArray(a) {
7461 return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
7462 (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
7465 /* Invoke the datepicker functionality.
7466 @param options string - a command, optionally followed by additional parameters or
7467 Object - settings for attaching new datepicker functionality
7468 @return jQuery object */
7469 $.fn.datepicker = function(options){
7471 /* Initialise the date picker. */
7472 if (!$.datepicker.initialized) {
7473 $(document).mousedown($.datepicker._checkExternalClick).
7474 find('body').append($.datepicker.dpDiv);
7475 $.datepicker.initialized = true;
7478 var otherArgs = Array.prototype.slice.call(arguments, 1);
7479 if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate'))
7480 return $.datepicker['_' + options + 'Datepicker'].
7481 apply($.datepicker, [this[0]].concat(otherArgs));
7482 return this.each(function() {
7483 typeof options == 'string' ?
7484 $.datepicker['_' + options + 'Datepicker'].
7485 apply($.datepicker, [this].concat(otherArgs)) :
7486 $.datepicker._attachDatepicker(this, options);
7490 $.datepicker = new Datepicker(); // singleton instance
7491 $.datepicker.initialized = false;
7492 $.datepicker.uuid = new Date().getTime();
7493 $.datepicker.version = "1.6rc6";
7497 * jQuery UI Progressbar 1.6rc6
7499 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
7500 * Dual licensed under the MIT (MIT-LICENSE.txt)
7501 * and GPL (GPL-LICENSE.txt) licenses.
7503 * http://docs.jquery.com/UI/Progressbar
7510 $.widget("ui.progressbar", {
7515 options = this.options;
7518 .addClass("ui-progressbar"
7520 + " ui-widget-content"
7523 role: "progressbar",
7524 "aria-valuemin": this._valueMin(),
7525 "aria-valuemax": this._valueMax(),
7526 "aria-valuenow": this._value()
7529 this.valueDiv = $('<div class="ui-progressbar-value ui-widget-header ui-corner-left"></div>').appendTo(this.element);
7531 this._refreshValue();
7535 destroy: function() {
7538 .removeClass("ui-progressbar"
7540 + " ui-widget-content"
7543 .removeAttr("aria-valuemin")
7544 .removeAttr("aria-valuemax")
7545 .removeAttr("aria-valuenow")
7546 .removeData("progressbar")
7547 .unbind(".progressbar");
7549 this.valueDiv.remove();
7551 $.widget.prototype.destroy.apply(this, arguments);
7555 value: function(newValue) {
7556 arguments.length && this._setData("value", newValue);
7558 return this._value();
7561 _setData: function(key, value){
7564 this.options.value = value;
7565 this._refreshValue();
7566 this._trigger('change', null, {});
7570 $.widget.prototype._setData.apply(this, arguments);
7573 _value: function() {
7574 var val = this.options.value;
7575 if (val < this._valueMin()) val = this._valueMin();
7576 if (val > this._valueMax()) val = this._valueMax();
7581 _valueMin: function() {
7587 _valueMax: function() {
7593 _refreshValue: function() {
7594 var value = this.value();
7595 this.valueDiv[value == this._valueMax() ? 'addClass' : 'removeClass']("ui-corner-right");
7596 this.valueDiv.width(value + '%');
7597 this.element.attr("aria-valuenow", value);
7602 $.extend($.ui.progressbar, {
7611 * jQuery UI Effects 1.6rc6
7613 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
7614 * Dual licensed under the MIT (MIT-LICENSE.txt)
7615 * and GPL (GPL-LICENSE.txt) licenses.
7617 * http://docs.jquery.com/UI/Effects/
7621 $.effects = $.effects || {}; //Add the 'effects' scope
7623 $.extend($.effects, {
7626 // Saves a set of properties in a data storage
7627 save: function(element, set) {
7628 for(var i=0; i < set.length; i++) {
7629 if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
7633 // Restores a set of previously saved properties from a data storage
7634 restore: function(element, set) {
7635 for(var i=0; i < set.length; i++) {
7636 if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
7640 setMode: function(el, mode) {
7641 if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
7645 getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
7646 // this should be a little more flexible in the future to handle a string & hash
7648 switch (origin[0]) {
7649 case 'top': y = 0; break;
7650 case 'middle': y = 0.5; break;
7651 case 'bottom': y = 1; break;
7652 default: y = origin[0] / original.height;
7654 switch (origin[1]) {
7655 case 'left': x = 0; break;
7656 case 'center': x = 0.5; break;
7657 case 'right': x = 1; break;
7658 default: x = origin[1] / original.width;
7660 return {x: x, y: y};
7663 // Wraps the element around a wrapper that copies position properties
7664 createWrapper: function(element) {
7666 //if the element is already wrapped, return it
7667 if (element.parent().is('.ui-effects-wrapper'))
7668 return element.parent();
7670 //Cache width,height and float properties of the element, and create a wrapper around it
7671 var props = { width: element.outerWidth(true), height: element.outerHeight(true), 'float': element.css('float') };
7672 element.wrap('<div class="ui-effects-wrapper" style="font-size:100%;background:transparent;border:none;margin:0;padding:0"></div>');
7673 var wrapper = element.parent();
7675 //Transfer the positioning of the element to the wrapper
7676 if (element.css('position') == 'static') {
7677 wrapper.css({ position: 'relative' });
7678 element.css({ position: 'relative'} );
7680 var top = element.css('top'); if(isNaN(parseInt(top,10))) top = 'auto';
7681 var left = element.css('left'); if(isNaN(parseInt(left,10))) left = 'auto';
7682 wrapper.css({ position: element.css('position'), top: top, left: left, zIndex: element.css('z-index') }).show();
7683 element.css({position: 'relative', top: 0, left: 0 });
7690 removeWrapper: function(element) {
7691 if (element.parent().is('.ui-effects-wrapper'))
7692 return element.parent().replaceWith(element);
7696 setTransition: function(element, list, factor, value) {
7697 value = value || {};
7698 $.each(list, function(i, x){
7699 unit = element.cssUnit(x);
7700 if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
7705 //Base function to animate from one class to another in a seamless transition
7706 animateClass: function(value, duration, easing, callback) {
7708 var cb = (typeof easing == "function" ? easing : (callback ? callback : null));
7709 var ea = (typeof easing == "string" ? easing : null);
7711 return this.each(function() {
7713 var offset = {}; var that = $(this); var oldStyleAttr = that.attr("style") || '';
7714 if(typeof oldStyleAttr == 'object') oldStyleAttr = oldStyleAttr["cssText"]; /* Stupidly in IE, style is a object.. */
7715 if(value.toggle) { that.hasClass(value.toggle) ? value.remove = value.toggle : value.add = value.toggle; }
7717 //Let's get a style offset
7718 var oldStyle = $.extend({}, (document.defaultView ? document.defaultView.getComputedStyle(this,null) : this.currentStyle));
7719 if(value.add) that.addClass(value.add); if(value.remove) that.removeClass(value.remove);
7720 var newStyle = $.extend({}, (document.defaultView ? document.defaultView.getComputedStyle(this,null) : this.currentStyle));
7721 if(value.add) that.removeClass(value.add); if(value.remove) that.addClass(value.remove);
7723 // The main function to form the object for animation
7724 for(var n in newStyle) {
7725 if( typeof newStyle[n] != "function" && newStyle[n] /* No functions and null properties */
7726 && n.indexOf("Moz") == -1 && n.indexOf("length") == -1 /* No mozilla spezific render properties. */
7727 && newStyle[n] != oldStyle[n] /* Only values that have changed are used for the animation */
7728 && (n.match(/color/i) || (!n.match(/color/i) && !isNaN(parseInt(newStyle[n],10)))) /* Only things that can be parsed to integers or colors */
7729 && (oldStyle.position != "static" || (oldStyle.position == "static" && !n.match(/left|top|bottom|right/))) /* No need for positions when dealing with static positions */
7730 ) offset[n] = newStyle[n];
7733 that.animate(offset, duration, ea, function() { // Animate the newly constructed offset object
7734 // Change style attribute back to original. For stupid IE, we need to clear the damn object.
7735 if(typeof $(this).attr("style") == 'object') { $(this).attr("style")["cssText"] = ""; $(this).attr("style")["cssText"] = oldStyleAttr; } else $(this).attr("style", oldStyleAttr);
7736 if(value.add) $(this).addClass(value.add); if(value.remove) $(this).removeClass(value.remove);
7737 if(cb) cb.apply(this, arguments);
7745 function _normalizeArguments(a, m) {
7747 var o = a[1] && a[1].constructor == Object ? a[1] : {}; if(m) o.mode = m;
7748 var speed = a[1] && a[1].constructor != Object ? a[1] : o.duration; //either comes from options.duration or the second argument
7749 speed = $.fx.off ? 0 : typeof speed === "number" ? speed : $.fx.speeds[speed] || $.fx.speeds._default;
7750 var callback = o.callback || ( $.isFunction(a[2]) && a[2] ) || ( $.isFunction(a[3]) && a[3] );
7752 return [a[0], o, speed, callback];
7756 //Extend the methods of jQuery
7762 __toggle: $.fn.toggle,
7763 _addClass: $.fn.addClass,
7764 _removeClass: $.fn.removeClass,
7765 _toggleClass: $.fn.toggleClass,
7767 // New effect methods
7768 effect: function(fx, options, speed, callback) {
7769 return $.effects[fx] ? $.effects[fx].call(this, {method: fx, options: options || {}, duration: speed, callback: callback }) : null;
7773 if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])))
7774 return this._show.apply(this, arguments);
7776 return this.effect.apply(this, _normalizeArguments(arguments, 'show'));
7781 if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])))
7782 return this._hide.apply(this, arguments);
7784 return this.effect.apply(this, _normalizeArguments(arguments, 'hide'));
7789 if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])) || (arguments[0].constructor == Function))
7790 return this.__toggle.apply(this, arguments);
7792 return this.effect.apply(this, _normalizeArguments(arguments, 'toggle'));
7796 addClass: function(classNames, speed, easing, callback) {
7797 return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
7799 removeClass: function(classNames,speed,easing,callback) {
7800 return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
7802 toggleClass: function(classNames,speed,easing,callback) {
7803 return ( (typeof speed !== "boolean") && speed ) ? $.effects.animateClass.apply(this, [{ toggle: classNames },speed,easing,callback]) : this._toggleClass(classNames, speed);
7805 morph: function(remove,add,speed,easing,callback) {
7806 return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
7808 switchClass: function() {
7809 return this.morph.apply(this, arguments);
7813 cssUnit: function(key) {
7814 var style = this.css(key), val = [];
7815 $.each( ['em','px','%','pt'], function(i, unit){
7816 if(style.indexOf(unit) > 0)
7817 val = [parseFloat(style), unit];
7824 * jQuery Color Animations
7825 * Copyright 2007 John Resig
7826 * Released under the MIT and GPL licenses.
7829 // We override the animation for all of these color styles
7830 $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'], function(i,attr){
7831 $.fx.step[attr] = function(fx) {
7832 if ( fx.state == 0 ) {
7833 fx.start = getColor( fx.elem, attr );
7834 fx.end = getRGB( fx.end );
7837 fx.elem.style[attr] = "rgb(" + [
7838 Math.max(Math.min( parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0],10), 255), 0),
7839 Math.max(Math.min( parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1],10), 255), 0),
7840 Math.max(Math.min( parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2],10), 255), 0)
7845 // Color Conversion functions from highlightFade
7846 // By Blair Mitchelmore
7847 // http://jquery.offput.ca/highlightFade/
7849 // Parse strings looking for color tuples [255,255,255]
7850 function getRGB(color) {
7853 // Check if we're already dealing with an array of colors
7854 if ( color && color.constructor == Array && color.length == 3 )
7857 // Look for rgb(num,num,num)
7858 if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
7859 return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
7861 // Look for rgb(num%,num%,num%)
7862 if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
7863 return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
7866 if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
7867 return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
7870 if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
7871 return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
7873 // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
7874 if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
7875 return colors['transparent'];
7877 // Otherwise, we're most likely dealing with a named color
7878 return colors[$.trim(color).toLowerCase()];
7881 function getColor(elem, attr) {
7885 color = $.curCSS(elem, attr);
7887 // Keep going until we find an element that has color, or we hit the body
7888 if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
7891 attr = "backgroundColor";
7892 } while ( elem = elem.parentNode );
7894 return getRGB(color);
7897 // Some named colors to work with
7898 // From Interface by Stefan Petre
7899 // http://interface.eyecon.ro/
7903 azure:[240,255,255],
7904 beige:[245,245,220],
7910 darkcyan:[0,139,139],
7911 darkgrey:[169,169,169],
7912 darkgreen:[0,100,0],
7913 darkkhaki:[189,183,107],
7914 darkmagenta:[139,0,139],
7915 darkolivegreen:[85,107,47],
7916 darkorange:[255,140,0],
7917 darkorchid:[153,50,204],
7919 darksalmon:[233,150,122],
7920 darkviolet:[148,0,211],
7921 fuchsia:[255,0,255],
7925 khaki:[240,230,140],
7926 lightblue:[173,216,230],
7927 lightcyan:[224,255,255],
7928 lightgreen:[144,238,144],
7929 lightgrey:[211,211,211],
7930 lightpink:[255,182,193],
7931 lightyellow:[255,255,224],
7933 magenta:[255,0,255],
7942 silver:[192,192,192],
7943 white:[255,255,255],
7945 transparent: [255,255,255]
7949 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
7951 * Uses the built in easing capabilities added In jQuery 1.1
7952 * to offer multiple easing options
7954 * TERMS OF USE - jQuery Easing
7956 * Open source under the BSD License.
7958 * Copyright 2008 George McGinley Smith
7959 * All rights reserved.
7961 * Redistribution and use in source and binary forms, with or without modification,
7962 * are permitted provided that the following conditions are met:
7964 * Redistributions of source code must retain the above copyright notice, this list of
7965 * conditions and the following disclaimer.
7966 * Redistributions in binary form must reproduce the above copyright notice, this list
7967 * of conditions and the following disclaimer in the documentation and/or other materials
7968 * provided with the distribution.
7970 * Neither the name of the author nor the names of contributors may be used to endorse
7971 * or promote products derived from this software without specific prior written permission.
7973 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
7974 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
7975 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
7976 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
7977 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
7978 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
7979 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
7980 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
7981 * OF THE POSSIBILITY OF SUCH DAMAGE.
7985 // t: current time, b: begInnIng value, c: change In value, d: duration
7986 $.easing.jswing = $.easing.swing;
7991 swing: function (x, t, b, c, d) {
7992 //alert($.easing.default);
7993 return $.easing[$.easing.def](x, t, b, c, d);
7995 easeInQuad: function (x, t, b, c, d) {
7996 return c*(t/=d)*t + b;
7998 easeOutQuad: function (x, t, b, c, d) {
7999 return -c *(t/=d)*(t-2) + b;
8001 easeInOutQuad: function (x, t, b, c, d) {
8002 if ((t/=d/2) < 1) return c/2*t*t + b;
8003 return -c/2 * ((--t)*(t-2) - 1) + b;
8005 easeInCubic: function (x, t, b, c, d) {
8006 return c*(t/=d)*t*t + b;
8008 easeOutCubic: function (x, t, b, c, d) {
8009 return c*((t=t/d-1)*t*t + 1) + b;
8011 easeInOutCubic: function (x, t, b, c, d) {
8012 if ((t/=d/2) < 1) return c/2*t*t*t + b;
8013 return c/2*((t-=2)*t*t + 2) + b;
8015 easeInQuart: function (x, t, b, c, d) {
8016 return c*(t/=d)*t*t*t + b;
8018 easeOutQuart: function (x, t, b, c, d) {
8019 return -c * ((t=t/d-1)*t*t*t - 1) + b;
8021 easeInOutQuart: function (x, t, b, c, d) {
8022 if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
8023 return -c/2 * ((t-=2)*t*t*t - 2) + b;
8025 easeInQuint: function (x, t, b, c, d) {
8026 return c*(t/=d)*t*t*t*t + b;
8028 easeOutQuint: function (x, t, b, c, d) {
8029 return c*((t=t/d-1)*t*t*t*t + 1) + b;
8031 easeInOutQuint: function (x, t, b, c, d) {
8032 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
8033 return c/2*((t-=2)*t*t*t*t + 2) + b;
8035 easeInSine: function (x, t, b, c, d) {
8036 return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
8038 easeOutSine: function (x, t, b, c, d) {
8039 return c * Math.sin(t/d * (Math.PI/2)) + b;
8041 easeInOutSine: function (x, t, b, c, d) {
8042 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
8044 easeInExpo: function (x, t, b, c, d) {
8045 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
8047 easeOutExpo: function (x, t, b, c, d) {
8048 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
8050 easeInOutExpo: function (x, t, b, c, d) {
8052 if (t==d) return b+c;
8053 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
8054 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
8056 easeInCirc: function (x, t, b, c, d) {
8057 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
8059 easeOutCirc: function (x, t, b, c, d) {
8060 return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
8062 easeInOutCirc: function (x, t, b, c, d) {
8063 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
8064 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
8066 easeInElastic: function (x, t, b, c, d) {
8067 var s=1.70158;var p=0;var a=c;
8068 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
8069 if (a < Math.abs(c)) { a=c; var s=p/4; }
8070 else var s = p/(2*Math.PI) * Math.asin (c/a);
8071 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
8073 easeOutElastic: function (x, t, b, c, d) {
8074 var s=1.70158;var p=0;var a=c;
8075 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
8076 if (a < Math.abs(c)) { a=c; var s=p/4; }
8077 else var s = p/(2*Math.PI) * Math.asin (c/a);
8078 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
8080 easeInOutElastic: function (x, t, b, c, d) {
8081 var s=1.70158;var p=0;var a=c;
8082 if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
8083 if (a < Math.abs(c)) { a=c; var s=p/4; }
8084 else var s = p/(2*Math.PI) * Math.asin (c/a);
8085 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
8086 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
8088 easeInBack: function (x, t, b, c, d, s) {
8089 if (s == undefined) s = 1.70158;
8090 return c*(t/=d)*t*((s+1)*t - s) + b;
8092 easeOutBack: function (x, t, b, c, d, s) {
8093 if (s == undefined) s = 1.70158;
8094 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
8096 easeInOutBack: function (x, t, b, c, d, s) {
8097 if (s == undefined) s = 1.70158;
8098 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
8099 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
8101 easeInBounce: function (x, t, b, c, d) {
8102 return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
8104 easeOutBounce: function (x, t, b, c, d) {
8105 if ((t/=d) < (1/2.75)) {
8106 return c*(7.5625*t*t) + b;
8107 } else if (t < (2/2.75)) {
8108 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
8109 } else if (t < (2.5/2.75)) {
8110 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
8112 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
8115 easeInOutBounce: function (x, t, b, c, d) {
8116 if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
8117 return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
8123 * TERMS OF USE - EASING EQUATIONS
8125 * Open source under the BSD License.
8127 * Copyright 2001 Robert Penner
8128 * All rights reserved.
8130 * Redistribution and use in source and binary forms, with or without modification,
8131 * are permitted provided that the following conditions are met:
8133 * Redistributions of source code must retain the above copyright notice, this list of
8134 * conditions and the following disclaimer.
8135 * Redistributions in binary form must reproduce the above copyright notice, this list
8136 * of conditions and the following disclaimer in the documentation and/or other materials
8137 * provided with the distribution.
8139 * Neither the name of the author nor the names of contributors may be used to endorse
8140 * or promote products derived from this software without specific prior written permission.
8142 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
8143 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
8144 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
8145 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
8146 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
8147 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
8148 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
8149 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
8150 * OF THE POSSIBILITY OF SUCH DAMAGE.
8156 * jQuery UI Effects Blind 1.6rc6
8158 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
8159 * Dual licensed under the MIT (MIT-LICENSE.txt)
8160 * and GPL (GPL-LICENSE.txt) licenses.
8162 * http://docs.jquery.com/UI/Effects/Blind
8169 $.effects.blind = function(o) {
8171 return this.queue(function() {
8174 var el = $(this), props = ['position','top','left'];
8177 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
8178 var direction = o.options.direction || 'vertical'; // Default direction
8181 $.effects.save(el, props); el.show(); // Save & Show
8182 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
8183 var ref = (direction == 'vertical') ? 'height' : 'width';
8184 var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
8185 if(mode == 'show') wrapper.css(ref, 0); // Shift
8189 animation[ref] = mode == 'show' ? distance : 0;
8192 wrapper.animate(animation, o.duration, o.options.easing, function() {
8193 if(mode == 'hide') el.hide(); // Hide
8194 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
8195 if(o.callback) o.callback.apply(el[0], arguments); // Callback
8205 * jQuery UI Effects Bounce 1.6rc6
8207 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
8208 * Dual licensed under the MIT (MIT-LICENSE.txt)
8209 * and GPL (GPL-LICENSE.txt) licenses.
8211 * http://docs.jquery.com/UI/Effects/Bounce
8218 $.effects.bounce = function(o) {
8220 return this.queue(function() {
8223 var el = $(this), props = ['position','top','left'];
8226 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
8227 var direction = o.options.direction || 'up'; // Default direction
8228 var distance = o.options.distance || 20; // Default distance
8229 var times = o.options.times || 5; // Default # of times
8230 var speed = o.duration || 250; // Default speed per bounce
8231 if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
8234 $.effects.save(el, props); el.show(); // Save & Show
8235 $.effects.createWrapper(el); // Create Wrapper
8236 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
8237 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
8238 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
8239 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
8240 if (mode == 'hide') distance = distance / (times * 2);
8241 if (mode != 'hide') times--;
8244 if (mode == 'show') { // Show Bounce
8245 var animation = {opacity: 1};
8246 animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
8247 el.animate(animation, speed / 2, o.options.easing);
8248 distance = distance / 2;
8251 for (var i = 0; i < times; i++) { // Bounces
8252 var animation1 = {}, animation2 = {};
8253 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
8254 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
8255 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
8256 distance = (mode == 'hide') ? distance * 2 : distance / 2;
8258 if (mode == 'hide') { // Last Bounce
8259 var animation = {opacity: 0};
8260 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
8261 el.animate(animation, speed / 2, o.options.easing, function(){
8263 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
8264 if(o.callback) o.callback.apply(this, arguments); // Callback
8267 var animation1 = {}, animation2 = {};
8268 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
8269 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
8270 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
8271 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
8272 if(o.callback) o.callback.apply(this, arguments); // Callback
8275 el.queue('fx', function() { el.dequeue(); });
8283 * jQuery UI Effects Clip 1.6rc6
8285 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
8286 * Dual licensed under the MIT (MIT-LICENSE.txt)
8287 * and GPL (GPL-LICENSE.txt) licenses.
8289 * http://docs.jquery.com/UI/Effects/Clip
8296 $.effects.clip = function(o) {
8298 return this.queue(function() {
8301 var el = $(this), props = ['position','top','left','height','width'];
8304 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
8305 var direction = o.options.direction || 'vertical'; // Default direction
8308 $.effects.save(el, props); el.show(); // Save & Show
8309 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
8310 var animate = el[0].tagName == 'IMG' ? wrapper : el;
8312 size: (direction == 'vertical') ? 'height' : 'width',
8313 position: (direction == 'vertical') ? 'top' : 'left'
8315 var distance = (direction == 'vertical') ? animate.height() : animate.width();
8316 if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
8320 animation[ref.size] = mode == 'show' ? distance : 0;
8321 animation[ref.position] = mode == 'show' ? 0 : distance / 2;
8324 animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
8325 if(mode == 'hide') el.hide(); // Hide
8326 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
8327 if(o.callback) o.callback.apply(el[0], arguments); // Callback
8337 * jQuery UI Effects Drop 1.6rc6
8339 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
8340 * Dual licensed under the MIT (MIT-LICENSE.txt)
8341 * and GPL (GPL-LICENSE.txt) licenses.
8343 * http://docs.jquery.com/UI/Effects/Drop
8350 $.effects.drop = function(o) {
8352 return this.queue(function() {
8355 var el = $(this), props = ['position','top','left','opacity'];
8358 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
8359 var direction = o.options.direction || 'left'; // Default Direction
8362 $.effects.save(el, props); el.show(); // Save & Show
8363 $.effects.createWrapper(el); // Create Wrapper
8364 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
8365 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
8366 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
8367 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
8370 var animation = {opacity: mode == 'show' ? 1 : 0};
8371 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
8374 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
8375 if(mode == 'hide') el.hide(); // Hide
8376 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
8377 if(o.callback) o.callback.apply(this, arguments); // Callback
8387 * jQuery UI Effects Explode 1.6rc6
8389 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
8390 * Dual licensed under the MIT (MIT-LICENSE.txt)
8391 * and GPL (GPL-LICENSE.txt) licenses.
8393 * http://docs.jquery.com/UI/Effects/Explode
8400 $.effects.explode = function(o) {
8402 return this.queue(function() {
8404 var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
8405 var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
8407 o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
8408 var el = $(this).show().css('visibility', 'hidden');
8409 var offset = el.offset();
8411 //Substract the margins - not fixing the problem yet.
8412 offset.top -= parseInt(el.css("marginTop")) || 0;
8413 offset.left -= parseInt(el.css("marginLeft")) || 0;
8415 var width = el.outerWidth(true);
8416 var height = el.outerHeight(true);
8418 for(var i=0;i<rows;i++) { // =
8419 for(var j=0;j<cells;j++) { // ||
8423 .wrap('<div></div>')
8425 position: 'absolute',
8426 visibility: 'visible',
8427 left: -j*(width/cells),
8428 top: -i*(height/rows)
8431 .addClass('ui-effects-explode')
8433 position: 'absolute',
8436 height: height/rows,
8437 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
8438 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
8439 opacity: o.options.mode == 'show' ? 0 : 1
8441 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
8442 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
8443 opacity: o.options.mode == 'show' ? 1 : 0
8444 }, o.duration || 500);
8448 // Set a timeout, to call the callback approx. when the other animations have finished
8449 setTimeout(function() {
8451 o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
8452 if(o.callback) o.callback.apply(el[0]); // Callback
8455 $('div.ui-effects-explode').remove();
8457 }, o.duration || 500);
8466 * jQuery UI Effects Fold 1.6rc6
8468 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
8469 * Dual licensed under the MIT (MIT-LICENSE.txt)
8470 * and GPL (GPL-LICENSE.txt) licenses.
8472 * http://docs.jquery.com/UI/Effects/Fold
8479 $.effects.fold = function(o) {
8481 return this.queue(function() {
8484 var el = $(this), props = ['position','top','left'];
8487 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
8488 var size = o.options.size || 15; // Default fold size
8489 var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
8490 var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
8493 $.effects.save(el, props); el.show(); // Save & Show
8494 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
8495 var widthFirst = ((mode == 'show') != horizFirst);
8496 var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
8497 var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
8498 var percent = /([0-9]+)%/.exec(size);
8499 if(percent) size = parseInt(percent[1]) / 100 * distance[mode == 'hide' ? 0 : 1];
8500 if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
8503 var animation1 = {}, animation2 = {};
8504 animation1[ref[0]] = mode == 'show' ? distance[0] : size;
8505 animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
8508 wrapper.animate(animation1, duration, o.options.easing)
8509 .animate(animation2, duration, o.options.easing, function() {
8510 if(mode == 'hide') el.hide(); // Hide
8511 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
8512 if(o.callback) o.callback.apply(el[0], arguments); // Callback
8522 * jQuery UI Effects Highlight 1.6rc6
8524 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
8525 * Dual licensed under the MIT (MIT-LICENSE.txt)
8526 * and GPL (GPL-LICENSE.txt) licenses.
8528 * http://docs.jquery.com/UI/Effects/Highlight
8535 $.effects.highlight = function(o) {
8537 return this.queue(function() {
8540 var el = $(this), props = ['backgroundImage','backgroundColor','opacity'];
8543 var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
8544 var color = o.options.color || "#ffff99"; // Default highlight color
8545 var oldColor = el.css("backgroundColor");
8548 $.effects.save(el, props); el.show(); // Save & Show
8549 el.css({backgroundImage: 'none', backgroundColor: color}); // Shift
8552 var animation = {backgroundColor: oldColor };
8553 if (mode == "hide") animation['opacity'] = 0;
8556 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
8557 if(mode == "hide") el.hide();
8558 $.effects.restore(el, props);
8559 if (mode == "show" && $.browser.msie) this.style.removeAttribute('filter');
8560 if(o.callback) o.callback.apply(this, arguments);
8570 * jQuery UI Effects Pulsate 1.6rc6
8572 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
8573 * Dual licensed under the MIT (MIT-LICENSE.txt)
8574 * and GPL (GPL-LICENSE.txt) licenses.
8576 * http://docs.jquery.com/UI/Effects/Pulsate
8583 $.effects.pulsate = function(o) {
8585 return this.queue(function() {
8591 var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
8592 var times = o.options.times || 5; // Default # of times
8593 var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
8596 if (mode == 'hide') times--;
8597 if (el.is(':hidden')) { // Show fadeIn
8598 el.css('opacity', 0);
8600 el.animate({opacity: 1}, duration, o.options.easing);
8605 for (var i = 0; i < times; i++) { // Pulsate
8606 el.animate({opacity: 0}, duration, o.options.easing).animate({opacity: 1}, duration, o.options.easing);
8608 if (mode == 'hide') { // Last Pulse
8609 el.animate({opacity: 0}, duration, o.options.easing, function(){
8611 if(o.callback) o.callback.apply(this, arguments); // Callback
8614 el.animate({opacity: 0}, duration, o.options.easing).animate({opacity: 1}, duration, o.options.easing, function(){
8615 if(o.callback) o.callback.apply(this, arguments); // Callback
8618 el.queue('fx', function() { el.dequeue(); });
8626 * jQuery UI Effects Scale 1.6rc6
8628 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
8629 * Dual licensed under the MIT (MIT-LICENSE.txt)
8630 * and GPL (GPL-LICENSE.txt) licenses.
8632 * http://docs.jquery.com/UI/Effects/Scale
8639 $.effects.puff = function(o) {
8641 return this.queue(function() {
8647 var options = $.extend(true, {}, o.options);
8648 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
8649 var percent = parseInt(o.options.percent) || 150; // Set default puff percent
8650 options.fade = true; // It's not a puff if it doesn't fade! :)
8651 var original = {height: el.height(), width: el.width()}; // Save original
8654 var factor = percent / 100;
8655 el.from = (mode == 'hide') ? original : {height: original.height * factor, width: original.width * factor};
8658 options.from = el.from;
8659 options.percent = (mode == 'hide') ? percent : 100;
8660 options.mode = mode;
8663 el.effect('scale', options, o.duration, o.callback);
8669 $.effects.scale = function(o) {
8671 return this.queue(function() {
8677 var options = $.extend(true, {}, o.options);
8678 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
8679 var percent = parseInt(o.options.percent) || (parseInt(o.options.percent) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
8680 var direction = o.options.direction || 'both'; // Set default axis
8681 var origin = o.options.origin; // The origin of the scaling
8682 if (mode != 'effect') { // Set default origin and restore for show/hide
8683 options.origin = origin || ['middle','center'];
8684 options.restore = true;
8686 var original = {height: el.height(), width: el.width()}; // Save original
8687 el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
8690 var factor = { // Set scaling factor
8691 y: direction != 'horizontal' ? (percent / 100) : 1,
8692 x: direction != 'vertical' ? (percent / 100) : 1
8694 el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
8696 if (o.options.fade) { // Fade option to support puff
8697 if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
8698 if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
8702 options.from = el.from; options.to = el.to; options.mode = mode;
8705 el.effect('size', options, o.duration, o.callback);
8711 $.effects.size = function(o) {
8713 return this.queue(function() {
8716 var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];
8717 var props1 = ['position','top','left','overflow','opacity']; // Always restore
8718 var props2 = ['width','height','overflow']; // Copy for children
8719 var cProps = ['fontSize'];
8720 var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
8721 var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
8724 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
8725 var restore = o.options.restore || false; // Default restore
8726 var scale = o.options.scale || 'both'; // Default scale mode
8727 var origin = o.options.origin; // The origin of the sizing
8728 var original = {height: el.height(), width: el.width()}; // Save original
8729 el.from = o.options.from || original; // Default from state
8730 el.to = o.options.to || original; // Default to state
8732 if (origin) { // Calculate baseline shifts
8733 var baseline = $.effects.getBaseline(origin, original);
8734 el.from.top = (original.height - el.from.height) * baseline.y;
8735 el.from.left = (original.width - el.from.width) * baseline.x;
8736 el.to.top = (original.height - el.to.height) * baseline.y;
8737 el.to.left = (original.width - el.to.width) * baseline.x;
8739 var factor = { // Set scaling factor
8740 from: {y: el.from.height / original.height, x: el.from.width / original.width},
8741 to: {y: el.to.height / original.height, x: el.to.width / original.width}
8743 if (scale == 'box' || scale == 'both') { // Scale the css box
8744 if (factor.from.y != factor.to.y) { // Vertical props scaling
8745 props = props.concat(vProps);
8746 el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
8747 el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
8749 if (factor.from.x != factor.to.x) { // Horizontal props scaling
8750 props = props.concat(hProps);
8751 el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
8752 el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
8755 if (scale == 'content' || scale == 'both') { // Scale the content
8756 if (factor.from.y != factor.to.y) { // Vertical props scaling
8757 props = props.concat(cProps);
8758 el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
8759 el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
8762 $.effects.save(el, restore ? props : props1); el.show(); // Save & Show
8763 $.effects.createWrapper(el); // Create Wrapper
8764 el.css('overflow','hidden').css(el.from); // Shift
8767 if (scale == 'content' || scale == 'both') { // Scale the children
8768 vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
8769 hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
8770 props2 = props.concat(vProps).concat(hProps); // Concat
8771 el.find("*[width]").each(function(){
8773 if (restore) $.effects.save(child, props2);
8774 var c_original = {height: child.height(), width: child.width()}; // Save original
8775 child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
8776 child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
8777 if (factor.from.y != factor.to.y) { // Vertical props scaling
8778 child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
8779 child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
8781 if (factor.from.x != factor.to.x) { // Horizontal props scaling
8782 child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
8783 child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
8785 child.css(child.from); // Shift children
8786 child.animate(child.to, o.duration, o.options.easing, function(){
8787 if (restore) $.effects.restore(child, props2); // Restore children
8788 }); // Animate children
8793 el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
8794 if(mode == 'hide') el.hide(); // Hide
8795 $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
8796 if(o.callback) o.callback.apply(this, arguments); // Callback
8806 * jQuery UI Effects Shake 1.6rc6
8808 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
8809 * Dual licensed under the MIT (MIT-LICENSE.txt)
8810 * and GPL (GPL-LICENSE.txt) licenses.
8812 * http://docs.jquery.com/UI/Effects/Shake
8819 $.effects.shake = function(o) {
8821 return this.queue(function() {
8824 var el = $(this), props = ['position','top','left'];
8827 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
8828 var direction = o.options.direction || 'left'; // Default direction
8829 var distance = o.options.distance || 20; // Default distance
8830 var times = o.options.times || 3; // Default # of times
8831 var speed = o.duration || o.options.duration || 140; // Default speed per shake
8834 $.effects.save(el, props); el.show(); // Save & Show
8835 $.effects.createWrapper(el); // Create Wrapper
8836 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
8837 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
8840 var animation = {}, animation1 = {}, animation2 = {};
8841 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
8842 animation1[ref] = (motion == 'pos' ? '+=' : '-=') + distance * 2;
8843 animation2[ref] = (motion == 'pos' ? '-=' : '+=') + distance * 2;
8846 el.animate(animation, speed, o.options.easing);
8847 for (var i = 1; i < times; i++) { // Shakes
8848 el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
8850 el.animate(animation1, speed, o.options.easing).
8851 animate(animation, speed / 2, o.options.easing, function(){ // Last shake
8852 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
8853 if(o.callback) o.callback.apply(this, arguments); // Callback
8855 el.queue('fx', function() { el.dequeue(); });
8863 * jQuery UI Effects Slide 1.6rc6
8865 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
8866 * Dual licensed under the MIT (MIT-LICENSE.txt)
8867 * and GPL (GPL-LICENSE.txt) licenses.
8869 * http://docs.jquery.com/UI/Effects/Slide
8876 $.effects.slide = function(o) {
8878 return this.queue(function() {
8881 var el = $(this), props = ['position','top','left'];
8884 var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
8885 var direction = o.options.direction || 'left'; // Default Direction
8888 $.effects.save(el, props); el.show(); // Save & Show
8889 $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
8890 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
8891 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
8892 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
8893 if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift
8897 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
8900 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
8901 if(mode == 'hide') el.hide(); // Hide
8902 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
8903 if(o.callback) o.callback.apply(this, arguments); // Callback
8913 * jQuery UI Effects Transfer 1.6rc6
8915 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
8916 * Dual licensed under the MIT (MIT-LICENSE.txt)
8917 * and GPL (GPL-LICENSE.txt) licenses.
8919 * http://docs.jquery.com/UI/Effects/Transfer
8926 $.effects.transfer = function(o) {
8928 return this.queue(function() {
8934 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
8935 var target = $(o.options.to); // Find Target
8936 var position = el.offset();
8937 var transfer = $('<div class="ui-effects-transfer"></div>').appendTo(document.body);
8938 if(o.options.className) transfer.addClass(o.options.className);
8941 transfer.addClass(o.options.className);
8944 left: position.left,
8945 height: el.outerHeight() - parseInt(transfer.css('borderTopWidth')) - parseInt(transfer.css('borderBottomWidth')),
8946 width: el.outerWidth() - parseInt(transfer.css('borderLeftWidth')) - parseInt(transfer.css('borderRightWidth')),
8947 position: 'absolute'
8951 position = target.offset();
8954 left: position.left,
8955 height: target.outerHeight() - parseInt(transfer.css('borderTopWidth')) - parseInt(transfer.css('borderBottomWidth')),
8956 width: target.outerWidth() - parseInt(transfer.css('borderLeftWidth')) - parseInt(transfer.css('borderRightWidth'))
8960 transfer.animate(animation, o.duration, o.options.easing, function() {
8961 transfer.remove(); // Remove div
8962 if(o.callback) o.callback.apply(el[0], arguments); // Callback