Merge remote branch 'kevmccor/edihistory_3'
[openemr.git] / library / js / jquery-ui.js
blob9583d85dec70cc28447708f788a36002c54fa2df
1 /*
2  * jQuery UI 1.7.2
3  *
4  * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
5  * Dual licensed under the MIT (MIT-LICENSE.txt)
6  * and GPL (GPL-LICENSE.txt) licenses.
7  *
8  * http://docs.jquery.com/UI
9  */
10 ;jQuery.ui || (function($) {
12 var _remove = $.fn.remove,
13         isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9);
15 //Helper functions and ui object
16 $.ui = {
17         version: "1.7.2",
19         // $.ui.plugin is deprecated.  Use the proxy pattern instead.
20         plugin: {
21                 add: function(module, option, set) {
22                         var proto = $.ui[module].prototype;
23                         for(var i in set) {
24                                 proto.plugins[i] = proto.plugins[i] || [];
25                                 proto.plugins[i].push([option, set[i]]);
26                         }
27                 },
28                 call: function(instance, name, args) {
29                         var set = instance.plugins[name];
30                         if(!set || !instance.element[0].parentNode) { return; }
32                         for (var i = 0; i < set.length; i++) {
33                                 if (instance.options[set[i][0]]) {
34                                         set[i][1].apply(instance.element, args);
35                                 }
36                         }
37                 }
38         },
40         contains: function(a, b) {
41                 return document.compareDocumentPosition
42                         ? a.compareDocumentPosition(b) & 16
43                         : a !== b && a.contains(b);
44         },
46         hasScroll: function(el, a) {
48                 //If overflow is hidden, the element might have extra content, but the user wants to hide it
49                 if ($(el).css('overflow') == 'hidden') { return false; }
51                 var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop',
52                         has = false;
54                 if (el[scroll] > 0) { return true; }
56                 // TODO: determine which cases actually cause this to happen
57                 // if the element doesn't have the scroll set, see if it's possible to
58                 // set the scroll
59                 el[scroll] = 1;
60                 has = (el[scroll] > 0);
61                 el[scroll] = 0;
62                 return has;
63         },
65         isOverAxis: function(x, reference, size) {
66                 //Determines when x coordinate is over "b" element axis
67                 return (x > reference) && (x < (reference + size));
68         },
70         isOver: function(y, x, top, left, height, width) {
71                 //Determines when x, y coordinates is over "b" element
72                 return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width);
73         },
75         keyCode: {
76                 BACKSPACE: 8,
77                 CAPS_LOCK: 20,
78                 COMMA: 188,
79                 CONTROL: 17,
80                 DELETE: 46,
81                 DOWN: 40,
82                 END: 35,
83                 ENTER: 13,
84                 ESCAPE: 27,
85                 HOME: 36,
86                 INSERT: 45,
87                 LEFT: 37,
88                 NUMPAD_ADD: 107,
89                 NUMPAD_DECIMAL: 110,
90                 NUMPAD_DIVIDE: 111,
91                 NUMPAD_ENTER: 108,
92                 NUMPAD_MULTIPLY: 106,
93                 NUMPAD_SUBTRACT: 109,
94                 PAGE_DOWN: 34,
95                 PAGE_UP: 33,
96                 PERIOD: 190,
97                 RIGHT: 39,
98                 SHIFT: 16,
99                 SPACE: 32,
100                 TAB: 9,
101                 UP: 38
102         }
105 // WAI-ARIA normalization
106 if (isFF2) {
107         var attr = $.attr,
108                 removeAttr = $.fn.removeAttr,
109                 ariaNS = "http://www.w3.org/2005/07/aaa",
110                 ariaState = /^aria-/,
111                 ariaRole = /^wairole:/;
113         $.attr = function(elem, name, value) {
114                 var set = value !== undefined;
116                 return (name == 'role'
117                         ? (set
118                                 ? attr.call(this, elem, name, "wairole:" + value)
119                                 : (attr.apply(this, arguments) || "").replace(ariaRole, ""))
120                         : (ariaState.test(name)
121                                 ? (set
122                                         ? elem.setAttributeNS(ariaNS,
123                                                 name.replace(ariaState, "aaa:"), value)
124                                         : attr.call(this, elem, name.replace(ariaState, "aaa:")))
125                                 : attr.apply(this, arguments)));
126         };
128         $.fn.removeAttr = function(name) {
129                 return (ariaState.test(name)
130                         ? this.each(function() {
131                                 this.removeAttributeNS(ariaNS, name.replace(ariaState, ""));
132                         }) : removeAttr.call(this, name));
133         };
136 //jQuery plugins
137 $.fn.extend({
138         remove: function() {
139                 // Safari has a native remove event which actually removes DOM elements,
140                 // so we have to use triggerHandler instead of trigger (#3037).
141                 $("*", this).add(this).each(function() {
142                         $(this).triggerHandler("remove");
143                 });
144                 return _remove.apply(this, arguments );
145         },
147         enableSelection: function() {
148                 return this
149                         .attr('unselectable', 'off')
150                         .css('MozUserSelect', '')
151                         .unbind('selectstart.ui');
152         },
154         disableSelection: function() {
155                 return this
156                         .attr('unselectable', 'on')
157                         .css('MozUserSelect', 'none')
158                         .bind('selectstart.ui', function() { return false; });
159         },
161         scrollParent: function() {
162                 var scrollParent;
163                 if(($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
164                         scrollParent = this.parents().filter(function() {
165                                 return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
166                         }).eq(0);
167                 } else {
168                         scrollParent = this.parents().filter(function() {
169                                 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
170                         }).eq(0);
171                 }
173                 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
174         }
178 //Additional selectors
179 $.extend($.expr[':'], {
180         data: function(elem, i, match) {
181                 return !!$.data(elem, match[3]);
182         },
184         focusable: function(element) {
185                 var nodeName = element.nodeName.toLowerCase(),
186                         tabIndex = $.attr(element, 'tabindex');
187                 return (/input|select|textarea|button|object/.test(nodeName)
188                         ? !element.disabled
189                         : 'a' == nodeName || 'area' == nodeName
190                                 ? element.href || !isNaN(tabIndex)
191                                 : !isNaN(tabIndex))
192                         // the element and all of its ancestors must be visible
193                         // the browser may report that the area is hidden
194                         && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
195         },
197         tabbable: function(element) {
198                 var tabIndex = $.attr(element, 'tabindex');
199                 return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
200         }
204 // $.widget is a factory to create jQuery plugins
205 // taking some boilerplate code out of the plugin code
206 function getter(namespace, plugin, method, args) {
207         function getMethods(type) {
208                 var methods = $[namespace][plugin][type] || [];
209                 return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods);
210         }
212         var methods = getMethods('getter');
213         if (args.length == 1 && typeof args[0] == 'string') {
214                 methods = methods.concat(getMethods('getterSetter'));
215         }
216         return ($.inArray(method, methods) != -1);
219 $.widget = function(name, prototype) {
220         var namespace = name.split(".")[0];
221         name = name.split(".")[1];
223         // create plugin method
224         $.fn[name] = function(options) {
225                 var isMethodCall = (typeof options == 'string'),
226                         args = Array.prototype.slice.call(arguments, 1);
228                 // prevent calls to internal methods
229                 if (isMethodCall && options.substring(0, 1) == '_') {
230                         return this;
231                 }
233                 // handle getter methods
234                 if (isMethodCall && getter(namespace, name, options, args)) {
235                         var instance = $.data(this[0], name);
236                         return (instance ? instance[options].apply(instance, args)
237                                 : undefined);
238                 }
240                 // handle initialization and non-getter methods
241                 return this.each(function() {
242                         var instance = $.data(this, name);
244                         // constructor
245                         (!instance && !isMethodCall &&
246                                 $.data(this, name, new $[namespace][name](this, options))._init());
248                         // method call
249                         (instance && isMethodCall && $.isFunction(instance[options]) &&
250                                 instance[options].apply(instance, args));
251                 });
252         };
254         // create widget constructor
255         $[namespace] = $[namespace] || {};
256         $[namespace][name] = function(element, options) {
257                 var self = this;
259                 this.namespace = namespace;
260                 this.widgetName = name;
261                 this.widgetEventPrefix = $[namespace][name].eventPrefix || name;
262                 this.widgetBaseClass = namespace + '-' + name;
264                 this.options = $.extend({},
265                         $.widget.defaults,
266                         $[namespace][name].defaults,
267                         $.metadata && $.metadata.get(element)[name],
268                         options);
270                 this.element = $(element)
271                         .bind('setData.' + name, function(event, key, value) {
272                                 if (event.target == element) {
273                                         return self._setData(key, value);
274                                 }
275                         })
276                         .bind('getData.' + name, function(event, key) {
277                                 if (event.target == element) {
278                                         return self._getData(key);
279                                 }
280                         })
281                         .bind('remove', function() {
282                                 return self.destroy();
283                         });
284         };
286         // add widget prototype
287         $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);
289         // TODO: merge getter and getterSetter properties from widget prototype
290         // and plugin prototype
291         $[namespace][name].getterSetter = 'option';
294 $.widget.prototype = {
295         _init: function() {},
296         destroy: function() {
297                 this.element.removeData(this.widgetName)
298                         .removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled')
299                         .removeAttr('aria-disabled');
300         },
302         option: function(key, value) {
303                 var options = key,
304                         self = this;
306                 if (typeof key == "string") {
307                         if (value === undefined) {
308                                 return this._getData(key);
309                         }
310                         options = {};
311                         options[key] = value;
312                 }
314                 $.each(options, function(key, value) {
315                         self._setData(key, value);
316                 });
317         },
318         _getData: function(key) {
319                 return this.options[key];
320         },
321         _setData: function(key, value) {
322                 this.options[key] = value;
324                 if (key == 'disabled') {
325                         this.element
326                                 [value ? 'addClass' : 'removeClass'](
327                                         this.widgetBaseClass + '-disabled' + ' ' +
328                                         this.namespace + '-state-disabled')
329                                 .attr("aria-disabled", value);
330                 }
331         },
333         enable: function() {
334                 this._setData('disabled', false);
335         },
336         disable: function() {
337                 this._setData('disabled', true);
338         },
340         _trigger: function(type, event, data) {
341                 var callback = this.options[type],
342                         eventName = (type == this.widgetEventPrefix
343                                 ? type : this.widgetEventPrefix + type);
345                 event = $.Event(event);
346                 event.type = eventName;
348                 // copy original event properties over to the new event
349                 // this would happen if we could call $.event.fix instead of $.Event
350                 // but we don't have a way to force an event to be fixed multiple times
351                 if (event.originalEvent) {
352                         for (var i = $.event.props.length, prop; i;) {
353                                 prop = $.event.props[--i];
354                                 event[prop] = event.originalEvent[prop];
355                         }
356                 }
358                 this.element.trigger(event, data);
360                 return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false
361                         || event.isDefaultPrevented());
362         }
365 $.widget.defaults = {
366         disabled: false
370 /** Mouse Interaction Plugin **/
372 $.ui.mouse = {
373         _mouseInit: function() {
374                 var self = this;
376                 this.element
377                         .bind('mousedown.'+this.widgetName, function(event) {
378                                 return self._mouseDown(event);
379                         })
380                         .bind('click.'+this.widgetName, function(event) {
381                                 if(self._preventClickEvent) {
382                                         self._preventClickEvent = false;
383                                         event.stopImmediatePropagation();
384                                         return false;
385                                 }
386                         });
388                 // Prevent text selection in IE
389                 if ($.browser.msie) {
390                         this._mouseUnselectable = this.element.attr('unselectable');
391                         this.element.attr('unselectable', 'on');
392                 }
394                 this.started = false;
395         },
397         // TODO: make sure destroying one instance of mouse doesn't mess with
398         // other instances of mouse
399         _mouseDestroy: function() {
400                 this.element.unbind('.'+this.widgetName);
402                 // Restore text selection in IE
403                 ($.browser.msie
404                         && this.element.attr('unselectable', this._mouseUnselectable));
405         },
407         _mouseDown: function(event) {
408                 // don't let more than one widget handle mouseStart
409                 // TODO: figure out why we have to use originalEvent
410                 event.originalEvent = event.originalEvent || {};
411                 if (event.originalEvent.mouseHandled) { return; }
413                 // we may have missed mouseup (out of window)
414                 (this._mouseStarted && this._mouseUp(event));
416                 this._mouseDownEvent = event;
418                 var self = this,
419                         btnIsLeft = (event.which == 1),
420                         elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
421                 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
422                         return true;
423                 }
425                 this.mouseDelayMet = !this.options.delay;
426                 if (!this.mouseDelayMet) {
427                         this._mouseDelayTimer = setTimeout(function() {
428                                 self.mouseDelayMet = true;
429                         }, this.options.delay);
430                 }
432                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
433                         this._mouseStarted = (this._mouseStart(event) !== false);
434                         if (!this._mouseStarted) {
435                                 event.preventDefault();
436                                 return true;
437                         }
438                 }
440                 // these delegates are required to keep context
441                 this._mouseMoveDelegate = function(event) {
442                         return self._mouseMove(event);
443                 };
444                 this._mouseUpDelegate = function(event) {
445                         return self._mouseUp(event);
446                 };
447                 $(document)
448                         .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
449                         .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
451                 // preventDefault() is used to prevent the selection of text here -
452                 // however, in Safari, this causes select boxes not to be selectable
453                 // anymore, so this fix is needed
454                 ($.browser.safari || event.preventDefault());
456                 event.originalEvent.mouseHandled = true;
457                 return true;
458         },
460         _mouseMove: function(event) {
461                 // IE mouseup check - mouseup happened when mouse was out of window
462                 if ($.browser.msie && !event.button) {
463                         return this._mouseUp(event);
464                 }
466                 if (this._mouseStarted) {
467                         this._mouseDrag(event);
468                         return event.preventDefault();
469                 }
471                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
472                         this._mouseStarted =
473                                 (this._mouseStart(this._mouseDownEvent, event) !== false);
474                         (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
475                 }
477                 return !this._mouseStarted;
478         },
480         _mouseUp: function(event) {
481                 $(document)
482                         .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
483                         .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
485                 if (this._mouseStarted) {
486                         this._mouseStarted = false;
487                         this._preventClickEvent = (event.target == this._mouseDownEvent.target);
488                         this._mouseStop(event);
489                 }
491                 return false;
492         },
494         _mouseDistanceMet: function(event) {
495                 return (Math.max(
496                                 Math.abs(this._mouseDownEvent.pageX - event.pageX),
497                                 Math.abs(this._mouseDownEvent.pageY - event.pageY)
498                         ) >= this.options.distance
499                 );
500         },
502         _mouseDelayMet: function(event) {
503                 return this.mouseDelayMet;
504         },
506         // These are placeholder methods, to be overriden by extending plugin
507         _mouseStart: function(event) {},
508         _mouseDrag: function(event) {},
509         _mouseStop: function(event) {},
510         _mouseCapture: function(event) { return true; }
513 $.ui.mouse.defaults = {
514         cancel: null,
515         distance: 1,
516         delay: 0
519 })(jQuery);
521  * jQuery UI Draggable 1.7.2
523  * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
524  * Dual licensed under the MIT (MIT-LICENSE.txt)
525  * and GPL (GPL-LICENSE.txt) licenses.
527  * http://docs.jquery.com/UI/Draggables
529  * Depends:
530  *      ui.core.js
531  */
532 (function($) {
534 $.widget("ui.draggable", $.extend({}, $.ui.mouse, {
536         _init: function() {
538                 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
539                         this.element[0].style.position = 'relative';
541                 (this.options.addClasses && this.element.addClass("ui-draggable"));
542                 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
544                 this._mouseInit();
546         },
548         destroy: function() {
549                 if(!this.element.data('draggable')) return;
550                 this.element
551                         .removeData("draggable")
552                         .unbind(".draggable")
553                         .removeClass("ui-draggable"
554                                 + " ui-draggable-dragging"
555                                 + " ui-draggable-disabled");
556                 this._mouseDestroy();
557         },
559         _mouseCapture: function(event) {
561                 var o = this.options;
563                 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
564                         return false;
566                 //Quit if we're not on a valid handle
567                 this.handle = this._getHandle(event);
568                 if (!this.handle)
569                         return false;
571                 return true;
573         },
575         _mouseStart: function(event) {
577                 var o = this.options;
579                 //Create and append the visible helper
580                 this.helper = this._createHelper(event);
582                 //Cache the helper size
583                 this._cacheHelperProportions();
585                 //If ddmanager is used for droppables, set the global draggable
586                 if($.ui.ddmanager)
587                         $.ui.ddmanager.current = this;
589                 /*
590                  * - Position generation -
591                  * This block generates everything position related - it's the core of draggables.
592                  */
594                 //Cache the margins of the original element
595                 this._cacheMargins();
597                 //Store the helper's css position
598                 this.cssPosition = this.helper.css("position");
599                 this.scrollParent = this.helper.scrollParent();
601                 //The element's absolute position on the page minus margins
602                 this.offset = this.element.offset();
603                 this.offset = {
604                         top: this.offset.top - this.margins.top,
605                         left: this.offset.left - this.margins.left
606                 };
608                 $.extend(this.offset, {
609                         click: { //Where the click happened, relative to the element
610                                 left: event.pageX - this.offset.left,
611                                 top: event.pageY - this.offset.top
612                         },
613                         parent: this._getParentOffset(),
614                         relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
615                 });
617                 //Generate the original position
618                 this.originalPosition = this._generatePosition(event);
619                 this.originalPageX = event.pageX;
620                 this.originalPageY = event.pageY;
622                 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
623                 if(o.cursorAt)
624                         this._adjustOffsetFromHelper(o.cursorAt);
626                 //Set a containment if given in the options
627                 if(o.containment)
628                         this._setContainment();
630                 //Call plugins and callbacks
631                 this._trigger("start", event);
633                 //Recache the helper size
634                 this._cacheHelperProportions();
636                 //Prepare the droppable offsets
637                 if ($.ui.ddmanager && !o.dropBehaviour)
638                         $.ui.ddmanager.prepareOffsets(this, event);
640                 this.helper.addClass("ui-draggable-dragging");
641                 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
642                 return true;
643         },
645         _mouseDrag: function(event, noPropagation) {
647                 //Compute the helpers position
648                 this.position = this._generatePosition(event);
649                 this.positionAbs = this._convertPositionTo("absolute");
651                 //Call plugins and callbacks and use the resulting position if something is returned
652                 if (!noPropagation) {
653                         var ui = this._uiHash();
654                         this._trigger('drag', event, ui);
655                         this.position = ui.position;
656                 }
658                 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
659                 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
660                 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
662                 return false;
663         },
665         _mouseStop: function(event) {
667                 //If we are using droppables, inform the manager about the drop
668                 var dropped = false;
669                 if ($.ui.ddmanager && !this.options.dropBehaviour)
670                         dropped = $.ui.ddmanager.drop(this, event);
672                 //if a drop comes from outside (a sortable)
673                 if(this.dropped) {
674                         dropped = this.dropped;
675                         this.dropped = false;
676                 }
678                 if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
679                         var self = this;
680                         $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
681                                 self._trigger("stop", event);
682                                 self._clear();
683                         });
684                 } else {
685                         this._trigger("stop", event);
686                         this._clear();
687                 }
689                 return false;
690         },
692         _getHandle: function(event) {
694                 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
695                 $(this.options.handle, this.element)
696                         .find("*")
697                         .andSelf()
698                         .each(function() {
699                                 if(this == event.target) handle = true;
700                         });
702                 return handle;
704         },
706         _createHelper: function(event) {
708                 var o = this.options;
709                 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
711                 if(!helper.parents('body').length)
712                         helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
714                 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
715                         helper.css("position", "absolute");
717                 return helper;
719         },
721         _adjustOffsetFromHelper: function(obj) {
722                 if(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left;
723                 if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
724                 if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top;
725                 if(obj.bottom != undefined) this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
726         },
728         _getParentOffset: function() {
730                 //Get the offsetParent and cache its position
731                 this.offsetParent = this.helper.offsetParent();
732                 var po = this.offsetParent.offset();
734                 // This is a special case where we need to modify a offset calculated on start, since the following happened:
735                 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
736                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
737                 //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
738                 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
739                         po.left += this.scrollParent.scrollLeft();
740                         po.top += this.scrollParent.scrollTop();
741                 }
743                 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
744                 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
745                         po = { top: 0, left: 0 };
747                 return {
748                         top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
749                         left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
750                 };
752         },
754         _getRelativeOffset: function() {
756                 if(this.cssPosition == "relative") {
757                         var p = this.element.position();
758                         return {
759                                 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
760                                 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
761                         };
762                 } else {
763                         return { top: 0, left: 0 };
764                 }
766         },
768         _cacheMargins: function() {
769                 this.margins = {
770                         left: (parseInt(this.element.css("marginLeft"),10) || 0),
771                         top: (parseInt(this.element.css("marginTop"),10) || 0)
772                 };
773         },
775         _cacheHelperProportions: function() {
776                 this.helperProportions = {
777                         width: this.helper.outerWidth(),
778                         height: this.helper.outerHeight()
779                 };
780         },
782         _setContainment: function() {
784                 var o = this.options;
785                 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
786                 if(o.containment == 'document' || o.containment == 'window') this.containment = [
787                         0 - this.offset.relative.left - this.offset.parent.left,
788                         0 - this.offset.relative.top - this.offset.parent.top,
789                         $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
790                         ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
791                 ];
793                 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
794                         var ce = $(o.containment)[0]; if(!ce) return;
795                         var co = $(o.containment).offset();
796                         var over = ($(ce).css("overflow") != 'hidden');
798                         this.containment = [
799                                 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
800                                 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
801                                 co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
802                                 co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
803                         ];
804                 } else if(o.containment.constructor == Array) {
805                         this.containment = o.containment;
806                 }
808         },
810         _convertPositionTo: function(d, pos) {
812                 if(!pos) pos = this.position;
813                 var mod = d == "absolute" ? 1 : -1;
814                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
816                 return {
817                         top: (
818                                 pos.top                                                                                                                                 // The absolute mouse position
819                                 + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
820                                 + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)
821                                 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
822                         ),
823                         left: (
824                                 pos.left                                                                                                                                // The absolute mouse position
825                                 + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
826                                 + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)
827                                 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
828                         )
829                 };
831         },
833         _generatePosition: function(event) {
835                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
837                 // This is another very weird special case that only happens for relative elements:
838                 // 1. If the css position is relative
839                 // 2. and the scroll parent is the document or similar to the offset parent
840                 // we have to refresh the relative offset during the scroll so there are no jumps
841                 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
842                         this.offset.relative = this._getRelativeOffset();
843                 }
845                 var pageX = event.pageX;
846                 var pageY = event.pageY;
848                 /*
849                  * - Position constraining -
850                  * Constrain the position to a mix of grid, containment.
851                  */
853                 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
855                         if(this.containment) {
856                                 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
857                                 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
858                                 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
859                                 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
860                         }
862                         if(o.grid) {
863                                 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
864                                 pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
866                                 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
867                                 pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
868                         }
870                 }
872                 return {
873                         top: (
874                                 pageY                                                                                                                           // The absolute mouse position
875                                 - this.offset.click.top                                                                                                 // Click offset (relative to the element)
876                                 - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
877                                 - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)
878                                 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
879                         ),
880                         left: (
881                                 pageX                                                                                                                           // The absolute mouse position
882                                 - this.offset.click.left                                                                                                // Click offset (relative to the element)
883                                 - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
884                                 - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)
885                                 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
886                         )
887                 };
889         },
891         _clear: function() {
892                 this.helper.removeClass("ui-draggable-dragging");
893                 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
894                 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
895                 this.helper = null;
896                 this.cancelHelperRemoval = false;
897         },
899         // From now on bulk stuff - mainly helpers
901         _trigger: function(type, event, ui) {
902                 ui = ui || this._uiHash();
903                 $.ui.plugin.call(this, type, [event, ui]);
904                 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
905                 return $.widget.prototype._trigger.call(this, type, event, ui);
906         },
908         plugins: {},
910         _uiHash: function(event) {
911                 return {
912                         helper: this.helper,
913                         position: this.position,
914                         absolutePosition: this.positionAbs, //deprecated
915                         offset: this.positionAbs
916                 };
917         }
919 }));
921 $.extend($.ui.draggable, {
922         version: "1.7.2",
923         eventPrefix: "drag",
924         defaults: {
925                 addClasses: true,
926                 appendTo: "parent",
927                 axis: false,
928                 cancel: ":input,option",
929                 connectToSortable: false,
930                 containment: false,
931                 cursor: "auto",
932                 cursorAt: false,
933                 delay: 0,
934                 distance: 1,
935                 grid: false,
936                 handle: false,
937                 helper: "original",
938                 iframeFix: false,
939                 opacity: false,
940                 refreshPositions: false,
941                 revert: false,
942                 revertDuration: 500,
943                 scope: "default",
944                 scroll: true,
945                 scrollSensitivity: 20,
946                 scrollSpeed: 20,
947                 snap: false,
948                 snapMode: "both",
949                 snapTolerance: 20,
950                 stack: false,
951                 zIndex: false
952         }
955 $.ui.plugin.add("draggable", "connectToSortable", {
956         start: function(event, ui) {
958                 var inst = $(this).data("draggable"), o = inst.options,
959                         uiSortable = $.extend({}, ui, { item: inst.element });
960                 inst.sortables = [];
961                 $(o.connectToSortable).each(function() {
962                         var sortable = $.data(this, 'sortable');
963                         if (sortable && !sortable.options.disabled) {
964                                 inst.sortables.push({
965                                         instance: sortable,
966                                         shouldRevert: sortable.options.revert
967                                 });
968                                 sortable._refreshItems();       //Do a one-time refresh at start to refresh the containerCache
969                                 sortable._trigger("activate", event, uiSortable);
970                         }
971                 });
973         },
974         stop: function(event, ui) {
976                 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
977                 var inst = $(this).data("draggable"),
978                         uiSortable = $.extend({}, ui, { item: inst.element });
980                 $.each(inst.sortables, function() {
981                         if(this.instance.isOver) {
983                                 this.instance.isOver = 0;
985                                 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
986                                 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
988                                 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
989                                 if(this.shouldRevert) this.instance.options.revert = true;
991                                 //Trigger the stop of the sortable
992                                 this.instance._mouseStop(event);
994                                 this.instance.options.helper = this.instance.options._helper;
996                                 //If the helper has been the original item, restore properties in the sortable
997                                 if(inst.options.helper == 'original')
998                                         this.instance.currentItem.css({ top: 'auto', left: 'auto' });
1000                         } else {
1001                                 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1002                                 this.instance._trigger("deactivate", event, uiSortable);
1003                         }
1005                 });
1007         },
1008         drag: function(event, ui) {
1010                 var inst = $(this).data("draggable"), self = this;
1012                 var checkPos = function(o) {
1013                         var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
1014                         var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
1015                         var itemHeight = o.height, itemWidth = o.width;
1016                         var itemTop = o.top, itemLeft = o.left;
1018                         return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
1019                 };
1021                 $.each(inst.sortables, function(i) {
1022                         
1023                         //Copy over some variables to allow calling the sortable's native _intersectsWith
1024                         this.instance.positionAbs = inst.positionAbs;
1025                         this.instance.helperProportions = inst.helperProportions;
1026                         this.instance.offset.click = inst.offset.click;
1027                         
1028                         if(this.instance._intersectsWith(this.instance.containerCache)) {
1030                                 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1031                                 if(!this.instance.isOver) {
1033                                         this.instance.isOver = 1;
1034                                         //Now we fake the start of dragging for the sortable instance,
1035                                         //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1036                                         //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
1037                                         this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
1038                                         this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1039                                         this.instance.options.helper = function() { return ui.helper[0]; };
1041                                         event.target = this.instance.currentItem[0];
1042                                         this.instance._mouseCapture(event, true);
1043                                         this.instance._mouseStart(event, true, true);
1045                                         //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1046                                         this.instance.offset.click.top = inst.offset.click.top;
1047                                         this.instance.offset.click.left = inst.offset.click.left;
1048                                         this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1049                                         this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1051                                         inst._trigger("toSortable", event);
1052                                         inst.dropped = this.instance.element; //draggable revert needs that
1053                                         //hack so receive/update callbacks work (mostly)
1054                                         inst.currentItem = inst.element;
1055                                         this.instance.fromOutside = inst;
1057                                 }
1059                                 //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
1060                                 if(this.instance.currentItem) this.instance._mouseDrag(event);
1062                         } else {
1064                                 //If it doesn't intersect with the sortable, and it intersected before,
1065                                 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1066                                 if(this.instance.isOver) {
1068                                         this.instance.isOver = 0;
1069                                         this.instance.cancelHelperRemoval = true;
1070                                         
1071                                         //Prevent reverting on this forced stop
1072                                         this.instance.options.revert = false;
1073                                         
1074                                         // The out event needs to be triggered independently
1075                                         this.instance._trigger('out', event, this.instance._uiHash(this.instance));
1076                                         
1077                                         this.instance._mouseStop(event, true);
1078                                         this.instance.options.helper = this.instance.options._helper;
1080                                         //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1081                                         this.instance.currentItem.remove();
1082                                         if(this.instance.placeholder) this.instance.placeholder.remove();
1084                                         inst._trigger("fromSortable", event);
1085                                         inst.dropped = false; //draggable revert needs that
1086                                 }
1088                         };
1090                 });
1092         }
1095 $.ui.plugin.add("draggable", "cursor", {
1096         start: function(event, ui) {
1097                 var t = $('body'), o = $(this).data('draggable').options;
1098                 if (t.css("cursor")) o._cursor = t.css("cursor");
1099                 t.css("cursor", o.cursor);
1100         },
1101         stop: function(event, ui) {
1102                 var o = $(this).data('draggable').options;
1103                 if (o._cursor) $('body').css("cursor", o._cursor);
1104         }
1107 $.ui.plugin.add("draggable", "iframeFix", {
1108         start: function(event, ui) {
1109                 var o = $(this).data('draggable').options;
1110                 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1111                         $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
1112                         .css({
1113                                 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
1114                                 position: "absolute", opacity: "0.001", zIndex: 1000
1115                         })
1116                         .css($(this).offset())
1117                         .appendTo("body");
1118                 });
1119         },
1120         stop: function(event, ui) {
1121                 $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
1122         }
1125 $.ui.plugin.add("draggable", "opacity", {
1126         start: function(event, ui) {
1127                 var t = $(ui.helper), o = $(this).data('draggable').options;
1128                 if(t.css("opacity")) o._opacity = t.css("opacity");
1129                 t.css('opacity', o.opacity);
1130         },
1131         stop: function(event, ui) {
1132                 var o = $(this).data('draggable').options;
1133                 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
1134         }
1137 $.ui.plugin.add("draggable", "scroll", {
1138         start: function(event, ui) {
1139                 var i = $(this).data("draggable");
1140                 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
1141         },
1142         drag: function(event, ui) {
1144                 var i = $(this).data("draggable"), o = i.options, scrolled = false;
1146                 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
1148                         if(!o.axis || o.axis != 'x') {
1149                                 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
1150                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1151                                 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
1152                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1153                         }
1155                         if(!o.axis || o.axis != 'y') {
1156                                 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
1157                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1158                                 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
1159                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1160                         }
1162                 } else {
1164                         if(!o.axis || o.axis != 'x') {
1165                                 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
1166                                         scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1167                                 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
1168                                         scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1169                         }
1171                         if(!o.axis || o.axis != 'y') {
1172                                 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
1173                                         scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1174                                 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
1175                                         scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1176                         }
1178                 }
1180                 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
1181                         $.ui.ddmanager.prepareOffsets(i, event);
1183         }
1186 $.ui.plugin.add("draggable", "snap", {
1187         start: function(event, ui) {
1189                 var i = $(this).data("draggable"), o = i.options;
1190                 i.snapElements = [];
1192                 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
1193                         var $t = $(this); var $o = $t.offset();
1194                         if(this != i.element[0]) i.snapElements.push({
1195                                 item: this,
1196                                 width: $t.outerWidth(), height: $t.outerHeight(),
1197                                 top: $o.top, left: $o.left
1198                         });
1199                 });
1201         },
1202         drag: function(event, ui) {
1204                 var inst = $(this).data("draggable"), o = inst.options;
1205                 var d = o.snapTolerance;
1207                 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
1208                         y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
1210                 for (var i = inst.snapElements.length - 1; i >= 0; i--){
1212                         var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
1213                                 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
1215                         //Yes, I know, this is insane ;)
1216                         if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
1217                                 if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1218                                 inst.snapElements[i].snapping = false;
1219                                 continue;
1220                         }
1222                         if(o.snapMode != 'inner') {
1223                                 var ts = Math.abs(t - y2) <= d;
1224                                 var bs = Math.abs(b - y1) <= d;
1225                                 var ls = Math.abs(l - x2) <= d;
1226                                 var rs = Math.abs(r - x1) <= d;
1227                                 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1228                                 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1229                                 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1230                                 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1231                         }
1233                         var first = (ts || bs || ls || rs);
1235                         if(o.snapMode != 'outer') {
1236                                 var ts = Math.abs(t - y1) <= d;
1237                                 var bs = Math.abs(b - y2) <= d;
1238                                 var ls = Math.abs(l - x1) <= d;
1239                                 var rs = Math.abs(r - x2) <= d;
1240                                 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1241                                 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1242                                 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1243                                 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1244                         }
1246                         if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
1247                                 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1248                         inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1250                 };
1252         }
1255 $.ui.plugin.add("draggable", "stack", {
1256         start: function(event, ui) {
1258                 var o = $(this).data("draggable").options;
1260                 var group = $.makeArray($(o.stack.group)).sort(function(a,b) {
1261                         return (parseInt($(a).css("zIndex"),10) || o.stack.min) - (parseInt($(b).css("zIndex"),10) || o.stack.min);
1262                 });
1264                 $(group).each(function(i) {
1265                         this.style.zIndex = o.stack.min + i;
1266                 });
1268                 this[0].style.zIndex = o.stack.min + group.length;
1270         }
1273 $.ui.plugin.add("draggable", "zIndex", {
1274         start: function(event, ui) {
1275                 var t = $(ui.helper), o = $(this).data("draggable").options;
1276                 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
1277                 t.css('zIndex', o.zIndex);
1278         },
1279         stop: function(event, ui) {
1280                 var o = $(this).data("draggable").options;
1281                 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
1282         }
1285 })(jQuery);
1287  * jQuery UI Droppable 1.7.2
1289  * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
1290  * Dual licensed under the MIT (MIT-LICENSE.txt)
1291  * and GPL (GPL-LICENSE.txt) licenses.
1293  * http://docs.jquery.com/UI/Droppables
1295  * Depends:
1296  *      ui.core.js
1297  *      ui.draggable.js
1298  */
1299 (function($) {
1301 $.widget("ui.droppable", {
1303         _init: function() {
1305                 var o = this.options, accept = o.accept;
1306                 this.isover = 0; this.isout = 1;
1308                 this.options.accept = this.options.accept && $.isFunction(this.options.accept) ? this.options.accept : function(d) {
1309                         return d.is(accept);
1310                 };
1312                 //Store the droppable's proportions
1313                 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
1315                 // Add the reference and positions to the manager
1316                 $.ui.ddmanager.droppables[this.options.scope] = $.ui.ddmanager.droppables[this.options.scope] || [];
1317                 $.ui.ddmanager.droppables[this.options.scope].push(this);
1319                 (this.options.addClasses && this.element.addClass("ui-droppable"));
1321         },
1323         destroy: function() {
1324                 var drop = $.ui.ddmanager.droppables[this.options.scope];
1325                 for ( var i = 0; i < drop.length; i++ )
1326                         if ( drop[i] == this )
1327                                 drop.splice(i, 1);
1329                 this.element
1330                         .removeClass("ui-droppable ui-droppable-disabled")
1331                         .removeData("droppable")
1332                         .unbind(".droppable");
1333         },
1335         _setData: function(key, value) {
1337                 if(key == 'accept') {
1338                         this.options.accept = value && $.isFunction(value) ? value : function(d) {
1339                                 return d.is(value);
1340                         };
1341                 } else {
1342                         $.widget.prototype._setData.apply(this, arguments);
1343                 }
1345         },
1347         _activate: function(event) {
1348                 var draggable = $.ui.ddmanager.current;
1349                 if(this.options.activeClass) this.element.addClass(this.options.activeClass);
1350                 (draggable && this._trigger('activate', event, this.ui(draggable)));
1351         },
1353         _deactivate: function(event) {
1354                 var draggable = $.ui.ddmanager.current;
1355                 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1356                 (draggable && this._trigger('deactivate', event, this.ui(draggable)));
1357         },
1359         _over: function(event) {
1361                 var draggable = $.ui.ddmanager.current;
1362                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1364                 if (this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1365                         if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
1366                         this._trigger('over', event, this.ui(draggable));
1367                 }
1369         },
1371         _out: function(event) {
1373                 var draggable = $.ui.ddmanager.current;
1374                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1376                 if (this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1377                         if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1378                         this._trigger('out', event, this.ui(draggable));
1379                 }
1381         },
1383         _drop: function(event,custom) {
1385                 var draggable = custom || $.ui.ddmanager.current;
1386                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
1388                 var childrenIntersection = false;
1389                 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
1390                         var inst = $.data(this, 'droppable');
1391                         if(inst.options.greedy && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)) {
1392                                 childrenIntersection = true; return false;
1393                         }
1394                 });
1395                 if(childrenIntersection) return false;
1397                 if(this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1398                         if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1399                         if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1400                         this._trigger('drop', event, this.ui(draggable));
1401                         return this.element;
1402                 }
1404                 return false;
1406         },
1408         ui: function(c) {
1409                 return {
1410                         draggable: (c.currentItem || c.element),
1411                         helper: c.helper,
1412                         position: c.position,
1413                         absolutePosition: c.positionAbs, //deprecated
1414                         offset: c.positionAbs
1415                 };
1416         }
1420 $.extend($.ui.droppable, {
1421         version: "1.7.2",
1422         eventPrefix: 'drop',
1423         defaults: {
1424                 accept: '*',
1425                 activeClass: false,
1426                 addClasses: true,
1427                 greedy: false,
1428                 hoverClass: false,
1429                 scope: 'default',
1430                 tolerance: 'intersect'
1431         }
1434 $.ui.intersect = function(draggable, droppable, toleranceMode) {
1436         if (!droppable.offset) return false;
1438         var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
1439                 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
1440         var l = droppable.offset.left, r = l + droppable.proportions.width,
1441                 t = droppable.offset.top, b = t + droppable.proportions.height;
1443         switch (toleranceMode) {
1444                 case 'fit':
1445                         return (l < x1 && x2 < r
1446                                 && t < y1 && y2 < b);
1447                         break;
1448                 case 'intersect':
1449                         return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
1450                                 && x2 - (draggable.helperProportions.width / 2) < r // Left Half
1451                                 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
1452                                 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
1453                         break;
1454                 case 'pointer':
1455                         var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
1456                                 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
1457                                 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
1458                         return isOver;
1459                         break;
1460                 case 'touch':
1461                         return (
1462                                         (y1 >= t && y1 <= b) || // Top edge touching
1463                                         (y2 >= t && y2 <= b) || // Bottom edge touching
1464                                         (y1 < t && y2 > b)              // Surrounded vertically
1465                                 ) && (
1466                                         (x1 >= l && x1 <= r) || // Left edge touching
1467                                         (x2 >= l && x2 <= r) || // Right edge touching
1468                                         (x1 < l && x2 > r)              // Surrounded horizontally
1469                                 );
1470                         break;
1471                 default:
1472                         return false;
1473                         break;
1474                 }
1479         This manager tracks offsets of draggables and droppables
1481 $.ui.ddmanager = {
1482         current: null,
1483         droppables: { 'default': [] },
1484         prepareOffsets: function(t, event) {
1486                 var m = $.ui.ddmanager.droppables[t.options.scope];
1487                 var type = event ? event.type : null; // workaround for #2317
1488                 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
1490                 droppablesLoop: for (var i = 0; i < m.length; i++) {
1492                         if(m[i].options.disabled || (t && !m[i].options.accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;   //No disabled and non-accepted
1493                         for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
1494                         m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue;                                                                       //If the element is not visible, continue
1496                         m[i].offset = m[i].element.offset();
1497                         m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
1499                         if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
1501                 }
1503         },
1504         drop: function(draggable, event) {
1506                 var dropped = false;
1507                 $.each($.ui.ddmanager.droppables[draggable.options.scope], function() {
1509                         if(!this.options) return;
1510                         if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
1511                                 dropped = this._drop.call(this, event);
1513                         if (!this.options.disabled && this.visible && this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1514                                 this.isout = 1; this.isover = 0;
1515                                 this._deactivate.call(this, event);
1516                         }
1518                 });
1519                 return dropped;
1521         },
1522         drag: function(draggable, event) {
1524                 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
1525                 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
1527                 //Run through all droppables and check their positions based on specific tolerance options
1529                 $.each($.ui.ddmanager.droppables[draggable.options.scope], function() {
1531                         if(this.options.disabled || this.greedyChild || !this.visible) return;
1532                         var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
1534                         var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
1535                         if(!c) return;
1537                         var parentInstance;
1538                         if (this.options.greedy) {
1539                                 var parent = this.element.parents(':data(droppable):eq(0)');
1540                                 if (parent.length) {
1541                                         parentInstance = $.data(parent[0], 'droppable');
1542                                         parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
1543                                 }
1544                         }
1546                         // we just moved into a greedy child
1547                         if (parentInstance && c == 'isover') {
1548                                 parentInstance['isover'] = 0;
1549                                 parentInstance['isout'] = 1;
1550                                 parentInstance._out.call(parentInstance, event);
1551                         }
1553                         this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
1554                         this[c == "isover" ? "_over" : "_out"].call(this, event);
1556                         // we just moved out of a greedy child
1557                         if (parentInstance && c == 'isout') {
1558                                 parentInstance['isout'] = 0;
1559                                 parentInstance['isover'] = 1;
1560                                 parentInstance._over.call(parentInstance, event);
1561                         }
1562                 });
1564         }
1567 })(jQuery);
1569  * jQuery UI Resizable 1.7.2
1571  * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
1572  * Dual licensed under the MIT (MIT-LICENSE.txt)
1573  * and GPL (GPL-LICENSE.txt) licenses.
1575  * http://docs.jquery.com/UI/Resizables
1577  * Depends:
1578  *      ui.core.js
1579  */
1580 (function($) {
1582 $.widget("ui.resizable", $.extend({}, $.ui.mouse, {
1584         _init: function() {
1586                 var self = this, o = this.options;
1587                 this.element.addClass("ui-resizable");
1589                 $.extend(this, {
1590                         _aspectRatio: !!(o.aspectRatio),
1591                         aspectRatio: o.aspectRatio,
1592                         originalElement: this.element,
1593                         _proportionallyResizeElements: [],
1594                         _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
1595                 });
1597                 //Wrap the element if it cannot hold child nodes
1598                 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
1600                         //Opera fix for relative positioning
1601                         if (/relative/.test(this.element.css('position')) && $.browser.opera)
1602                                 this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
1604                         //Create a wrapper element and set the wrapper to the new current internal element
1605                         this.element.wrap(
1606                                 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
1607                                         position: this.element.css('position'),
1608                                         width: this.element.outerWidth(),
1609                                         height: this.element.outerHeight(),
1610                                         top: this.element.css('top'),
1611                                         left: this.element.css('left')
1612                                 })
1613                         );
1615                         //Overwrite the original this.element
1616                         this.element = this.element.parent().data(
1617                                 "resizable", this.element.data('resizable')
1618                         );
1620                         this.elementIsWrapper = true;
1622                         //Move margins to the wrapper
1623                         this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
1624                         this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
1626                         //Prevent Safari textarea resize
1627                         this.originalResizeStyle = this.originalElement.css('resize');
1628                         this.originalElement.css('resize', 'none');
1630                         //Push the actual element to our proportionallyResize internal array
1631                         this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
1633                         // avoid IE jump (hard set the margin)
1634                         this.originalElement.css({ margin: this.originalElement.css('margin') });
1636                         // fix handlers offset
1637                         this._proportionallyResize();
1639                 }
1641                 this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
1642                 if(this.handles.constructor == String) {
1644                         if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
1645                         var n = this.handles.split(","); this.handles = {};
1647                         for(var i = 0; i < n.length; i++) {
1649                                 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
1650                                 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
1652                                 // increase zIndex of sw, se, ne, nw axis
1653                                 //TODO : this modifies original option
1654                                 if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
1656                                 //TODO : What's going on here?
1657                                 if ('se' == handle) {
1658                                         axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
1659                                 };
1661                                 //Insert into internal handles object and append to element
1662                                 this.handles[handle] = '.ui-resizable-'+handle;
1663                                 this.element.append(axis);
1664                         }
1666                 }
1668                 this._renderAxis = function(target) {
1670                         target = target || this.element;
1672                         for(var i in this.handles) {
1674                                 if(this.handles[i].constructor == String)
1675                                         this.handles[i] = $(this.handles[i], this.element).show();
1677                                 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
1678                                 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
1680                                         var axis = $(this.handles[i], this.element), padWrapper = 0;
1682                                         //Checking the correct pad and border
1683                                         padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
1685                                         //The padding type i have to apply...
1686                                         var padPos = [ 'padding',
1687                                                 /ne|nw|n/.test(i) ? 'Top' :
1688                                                 /se|sw|s/.test(i) ? 'Bottom' :
1689                                                 /^e$/.test(i) ? 'Right' : 'Left' ].join("");
1691                                         target.css(padPos, padWrapper);
1693                                         this._proportionallyResize();
1695                                 }
1697                                 //TODO: What's that good for? There's not anything to be executed left
1698                                 if(!$(this.handles[i]).length)
1699                                         continue;
1701                         }
1702                 };
1704                 //TODO: make renderAxis a prototype function
1705                 this._renderAxis(this.element);
1707                 this._handles = $('.ui-resizable-handle', this.element)
1708                         .disableSelection();
1710                 //Matching axis name
1711                 this._handles.mouseover(function() {
1712                         if (!self.resizing) {
1713                                 if (this.className)
1714                                         var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
1715                                 //Axis, default = se
1716                                 self.axis = axis && axis[1] ? axis[1] : 'se';
1717                         }
1718                 });
1720                 //If we want to auto hide the elements
1721                 if (o.autoHide) {
1722                         this._handles.hide();
1723                         $(this.element)
1724                                 .addClass("ui-resizable-autohide")
1725                                 .hover(function() {
1726                                         $(this).removeClass("ui-resizable-autohide");
1727                                         self._handles.show();
1728                                 },
1729                                 function(){
1730                                         if (!self.resizing) {
1731                                                 $(this).addClass("ui-resizable-autohide");
1732                                                 self._handles.hide();
1733                                         }
1734                                 });
1735                 }
1737                 //Initialize the mouse interaction
1738                 this._mouseInit();
1740         },
1742         destroy: function() {
1744                 this._mouseDestroy();
1746                 var _destroy = function(exp) {
1747                         $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
1748                                 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
1749                 };
1751                 //TODO: Unwrap at same DOM position
1752                 if (this.elementIsWrapper) {
1753                         _destroy(this.element);
1754                         var wrapper = this.element;
1755                         wrapper.parent().append(
1756                                 this.originalElement.css({
1757                                         position: wrapper.css('position'),
1758                                         width: wrapper.outerWidth(),
1759                                         height: wrapper.outerHeight(),
1760                                         top: wrapper.css('top'),
1761                                         left: wrapper.css('left')
1762                                 })
1763                         ).end().remove();
1764                 }
1766                 this.originalElement.css('resize', this.originalResizeStyle);
1767                 _destroy(this.originalElement);
1769         },
1771         _mouseCapture: function(event) {
1773                 var handle = false;
1774                 for(var i in this.handles) {
1775                         if($(this.handles[i])[0] == event.target) handle = true;
1776                 }
1778                 return this.options.disabled || !!handle;
1780         },
1782         _mouseStart: function(event) {
1784                 var o = this.options, iniPos = this.element.position(), el = this.element;
1786                 this.resizing = true;
1787                 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
1789                 // bugfix for http://dev.jquery.com/ticket/1749
1790                 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
1791                         el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
1792                 }
1794                 //Opera fixing relative position
1795                 if ($.browser.opera && (/relative/).test(el.css('position')))
1796                         el.css({ position: 'relative', top: 'auto', left: 'auto' });
1798                 this._renderProxy();
1800                 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
1802                 if (o.containment) {
1803                         curleft += $(o.containment).scrollLeft() || 0;
1804                         curtop += $(o.containment).scrollTop() || 0;
1805                 }
1807                 //Store needed variables
1808                 this.offset = this.helper.offset();
1809                 this.position = { left: curleft, top: curtop };
1810                 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
1811                 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
1812                 this.originalPosition = { left: curleft, top: curtop };
1813                 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
1814                 this.originalMousePosition = { left: event.pageX, top: event.pageY };
1816                 //Aspect Ratio
1817                 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
1819             var cursor = $('.ui-resizable-' + this.axis).css('cursor');
1820             $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
1822                 el.addClass("ui-resizable-resizing");
1823                 this._propagate("start", event);
1824                 return true;
1825         },
1827         _mouseDrag: function(event) {
1829                 //Increase performance, avoid regex
1830                 var el = this.helper, o = this.options, props = {},
1831                         self = this, smp = this.originalMousePosition, a = this.axis;
1833                 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
1834                 var trigger = this._change[a];
1835                 if (!trigger) return false;
1837                 // Calculate the attrs that will be change
1838                 var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
1840                 if (this._aspectRatio || event.shiftKey)
1841                         data = this._updateRatio(data, event);
1843                 data = this._respectSize(data, event);
1845                 // plugins callbacks need to be called first
1846                 this._propagate("resize", event);
1848                 el.css({
1849                         top: this.position.top + "px", left: this.position.left + "px",
1850                         width: this.size.width + "px", height: this.size.height + "px"
1851                 });
1853                 if (!this._helper && this._proportionallyResizeElements.length)
1854                         this._proportionallyResize();
1856                 this._updateCache(data);
1858                 // calling the user callback at the end
1859                 this._trigger('resize', event, this.ui());
1861                 return false;
1862         },
1864         _mouseStop: function(event) {
1866                 this.resizing = false;
1867                 var o = this.options, self = this;
1869                 if(this._helper) {
1870                         var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
1871                                                 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
1872                                                         soffsetw = ista ? 0 : self.sizeDiff.width;
1874                         var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
1875                                 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
1876                                 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
1878                         if (!o.animate)
1879                                 this.element.css($.extend(s, { top: top, left: left }));
1881                         self.helper.height(self.size.height);
1882                         self.helper.width(self.size.width);
1884                         if (this._helper && !o.animate) this._proportionallyResize();
1885                 }
1887                 $('body').css('cursor', 'auto');
1889                 this.element.removeClass("ui-resizable-resizing");
1891                 this._propagate("stop", event);
1893                 if (this._helper) this.helper.remove();
1894                 return false;
1896         },
1898         _updateCache: function(data) {
1899                 var o = this.options;
1900                 this.offset = this.helper.offset();
1901                 if (isNumber(data.left)) this.position.left = data.left;
1902                 if (isNumber(data.top)) this.position.top = data.top;
1903                 if (isNumber(data.height)) this.size.height = data.height;
1904                 if (isNumber(data.width)) this.size.width = data.width;
1905         },
1907         _updateRatio: function(data, event) {
1909                 var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
1911                 if (data.height) data.width = (csize.height * this.aspectRatio);
1912                 else if (data.width) data.height = (csize.width / this.aspectRatio);
1914                 if (a == 'sw') {
1915                         data.left = cpos.left + (csize.width - data.width);
1916                         data.top = null;
1917                 }
1918                 if (a == 'nw') {
1919                         data.top = cpos.top + (csize.height - data.height);
1920                         data.left = cpos.left + (csize.width - data.width);
1921                 }
1923                 return data;
1924         },
1926         _respectSize: function(data, event) {
1928                 var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
1929                                 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
1930                                         isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
1932                 if (isminw) data.width = o.minWidth;
1933                 if (isminh) data.height = o.minHeight;
1934                 if (ismaxw) data.width = o.maxWidth;
1935                 if (ismaxh) data.height = o.maxHeight;
1937                 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
1938                 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
1940                 if (isminw && cw) data.left = dw - o.minWidth;
1941                 if (ismaxw && cw) data.left = dw - o.maxWidth;
1942                 if (isminh && ch)       data.top = dh - o.minHeight;
1943                 if (ismaxh && ch)       data.top = dh - o.maxHeight;
1945                 // fixing jump error on top/left - bug #2330
1946                 var isNotwh = !data.width && !data.height;
1947                 if (isNotwh && !data.left && data.top) data.top = null;
1948                 else if (isNotwh && !data.top && data.left) data.left = null;
1950                 return data;
1951         },
1953         _proportionallyResize: function() {
1955                 var o = this.options;
1956                 if (!this._proportionallyResizeElements.length) return;
1957                 var element = this.helper || this.element;
1959                 for (var i=0; i < this._proportionallyResizeElements.length; i++) {
1961                         var prel = this._proportionallyResizeElements[i];
1963                         if (!this.borderDif) {
1964                                 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
1965                                         p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
1967                                 this.borderDif = $.map(b, function(v, i) {
1968                                         var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
1969                                         return border + padding;
1970                                 });
1971                         }
1973                         if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
1974                                 continue;
1976                         prel.css({
1977                                 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
1978                                 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
1979                         });
1981                 };
1983         },
1985         _renderProxy: function() {
1987                 var el = this.element, o = this.options;
1988                 this.elementOffset = el.offset();
1990                 if(this._helper) {
1992                         this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
1994                         // fix ie6 offset TODO: This seems broken
1995                         var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
1996                         pxyoffset = ( ie6 ? 2 : -1 );
1998                         this.helper.addClass(this._helper).css({
1999                                 width: this.element.outerWidth() + pxyoffset,
2000                                 height: this.element.outerHeight() + pxyoffset,
2001                                 position: 'absolute',
2002                                 left: this.elementOffset.left - ie6offset +'px',
2003                                 top: this.elementOffset.top - ie6offset +'px',
2004                                 zIndex: ++o.zIndex //TODO: Don't modify option
2005                         });
2007                         this.helper
2008                                 .appendTo("body")
2009                                 .disableSelection();
2011                 } else {
2012                         this.helper = this.element;
2013                 }
2015         },
2017         _change: {
2018                 e: function(event, dx, dy) {
2019                         return { width: this.originalSize.width + dx };
2020                 },
2021                 w: function(event, dx, dy) {
2022                         var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2023                         return { left: sp.left + dx, width: cs.width - dx };
2024                 },
2025                 n: function(event, dx, dy) {
2026                         var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2027                         return { top: sp.top + dy, height: cs.height - dy };
2028                 },
2029                 s: function(event, dx, dy) {
2030                         return { height: this.originalSize.height + dy };
2031                 },
2032                 se: function(event, dx, dy) {
2033                         return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2034                 },
2035                 sw: function(event, dx, dy) {
2036                         return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2037                 },
2038                 ne: function(event, dx, dy) {
2039                         return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2040                 },
2041                 nw: function(event, dx, dy) {
2042                         return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2043                 }
2044         },
2046         _propagate: function(n, event) {
2047                 $.ui.plugin.call(this, n, [event, this.ui()]);
2048                 (n != "resize" && this._trigger(n, event, this.ui()));
2049         },
2051         plugins: {},
2053         ui: function() {
2054                 return {
2055                         originalElement: this.originalElement,
2056                         element: this.element,
2057                         helper: this.helper,
2058                         position: this.position,
2059                         size: this.size,
2060                         originalSize: this.originalSize,
2061                         originalPosition: this.originalPosition
2062                 };
2063         }
2065 }));
2067 $.extend($.ui.resizable, {
2068         version: "1.7.2",
2069         eventPrefix: "resize",
2070         defaults: {
2071                 alsoResize: false,
2072                 animate: false,
2073                 animateDuration: "slow",
2074                 animateEasing: "swing",
2075                 aspectRatio: false,
2076                 autoHide: false,
2077                 cancel: ":input,option",
2078                 containment: false,
2079                 delay: 0,
2080                 distance: 1,
2081                 ghost: false,
2082                 grid: false,
2083                 handles: "e,s,se",
2084                 helper: false,
2085                 maxHeight: null,
2086                 maxWidth: null,
2087                 minHeight: 10,
2088                 minWidth: 10,
2089                 zIndex: 1000
2090         }
2094  * Resizable Extensions
2095  */
2097 $.ui.plugin.add("resizable", "alsoResize", {
2099         start: function(event, ui) {
2101                 var self = $(this).data("resizable"), o = self.options;
2103                 _store = function(exp) {
2104                         $(exp).each(function() {
2105                                 $(this).data("resizable-alsoresize", {
2106                                         width: parseInt($(this).width(), 10), height: parseInt($(this).height(), 10),
2107                                         left: parseInt($(this).css('left'), 10), top: parseInt($(this).css('top'), 10)
2108                                 });
2109                         });
2110                 };
2112                 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
2113                         if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0];      _store(o.alsoResize); }
2114                         else { $.each(o.alsoResize, function(exp, c) { _store(exp); }); }
2115                 }else{
2116                         _store(o.alsoResize);
2117                 }
2118         },
2120         resize: function(event, ui){
2121                 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
2123                 var delta = {
2124                         height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
2125                         top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
2126                 },
2128                 _alsoResize = function(exp, c) {
2129                         $(exp).each(function() {
2130                                 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, css = c && c.length ? c : ['width', 'height', 'top', 'left'];
2132                                 $.each(css || ['width', 'height', 'top', 'left'], function(i, prop) {
2133                                         var sum = (start[prop]||0) + (delta[prop]||0);
2134                                         if (sum && sum >= 0)
2135                                                 style[prop] = sum || null;
2136                                 });
2138                                 //Opera fixing relative position
2139                                 if (/relative/.test(el.css('position')) && $.browser.opera) {
2140                                         self._revertToRelativePosition = true;
2141                                         el.css({ position: 'absolute', top: 'auto', left: 'auto' });
2142                                 }
2144                                 el.css(style);
2145                         });
2146                 };
2148                 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2149                         $.each(o.alsoResize, function(exp, c) { _alsoResize(exp, c); });
2150                 }else{
2151                         _alsoResize(o.alsoResize);
2152                 }
2153         },
2155         stop: function(event, ui){
2156                 var self = $(this).data("resizable");
2158                 //Opera fixing relative position
2159                 if (self._revertToRelativePosition && $.browser.opera) {
2160                         self._revertToRelativePosition = false;
2161                         el.css({ position: 'relative' });
2162                 }
2164                 $(this).removeData("resizable-alsoresize-start");
2165         }
2168 $.ui.plugin.add("resizable", "animate", {
2170         stop: function(event, ui) {
2171                 var self = $(this).data("resizable"), o = self.options;
2173                 var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2174                                         soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2175                                                 soffsetw = ista ? 0 : self.sizeDiff.width;
2177                 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
2178                                         left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2179                                                 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2181                 self.element.animate(
2182                         $.extend(style, top && left ? { top: top, left: left } : {}), {
2183                                 duration: o.animateDuration,
2184                                 easing: o.animateEasing,
2185                                 step: function() {
2187                                         var data = {
2188                                                 width: parseInt(self.element.css('width'), 10),
2189                                                 height: parseInt(self.element.css('height'), 10),
2190                                                 top: parseInt(self.element.css('top'), 10),
2191                                                 left: parseInt(self.element.css('left'), 10)
2192                                         };
2194                                         if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
2196                                         // propagating resize, and updating values for each animation step
2197                                         self._updateCache(data);
2198                                         self._propagate("resize", event);
2200                                 }
2201                         }
2202                 );
2203         }
2207 $.ui.plugin.add("resizable", "containment", {
2209         start: function(event, ui) {
2210                 var self = $(this).data("resizable"), o = self.options, el = self.element;
2211                 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
2212                 if (!ce) return;
2214                 self.containerElement = $(ce);
2216                 if (/document/.test(oc) || oc == document) {
2217                         self.containerOffset = { left: 0, top: 0 };
2218                         self.containerPosition = { left: 0, top: 0 };
2220                         self.parentData = {
2221                                 element: $(document), left: 0, top: 0,
2222                                 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
2223                         };
2224                 }
2226                 // i'm a node, so compute top, left, right, bottom
2227                 else {
2228                         var element = $(ce), p = [];
2229                         $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
2231                         self.containerOffset = element.offset();
2232                         self.containerPosition = element.position();
2233                         self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
2235                         var co = self.containerOffset, ch = self.containerSize.height,  cw = self.containerSize.width,
2236                                                 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
2238                         self.parentData = {
2239                                 element: ce, left: co.left, top: co.top, width: width, height: height
2240                         };
2241                 }
2242         },
2244         resize: function(event, ui) {
2245                 var self = $(this).data("resizable"), o = self.options,
2246                                 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
2247                                 pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
2249                 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
2251                 if (cp.left < (self._helper ? co.left : 0)) {
2252                         self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
2253                         if (pRatio) self.size.height = self.size.width / o.aspectRatio;
2254                         self.position.left = o.helper ? co.left : 0;
2255                 }
2257                 if (cp.top < (self._helper ? co.top : 0)) {
2258                         self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
2259                         if (pRatio) self.size.width = self.size.height * o.aspectRatio;
2260                         self.position.top = self._helper ? co.top : 0;
2261                 }
2263                 self.offset.left = self.parentData.left+self.position.left;
2264                 self.offset.top = self.parentData.top+self.position.top;
2266                 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
2267                                         hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
2269                 var isParent = self.containerElement.get(0) == self.element.parent().get(0),
2270                     isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
2272                 if(isParent && isOffsetRelative) woset -= self.parentData.left;
2274                 if (woset + self.size.width >= self.parentData.width) {
2275                         self.size.width = self.parentData.width - woset;
2276                         if (pRatio) self.size.height = self.size.width / self.aspectRatio;
2277                 }
2279                 if (hoset + self.size.height >= self.parentData.height) {
2280                         self.size.height = self.parentData.height - hoset;
2281                         if (pRatio) self.size.width = self.size.height * self.aspectRatio;
2282                 }
2283         },
2285         stop: function(event, ui){
2286                 var self = $(this).data("resizable"), o = self.options, cp = self.position,
2287                                 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
2289                 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
2291                 if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
2292                         $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2294                 if (self._helper && !o.animate && (/static/).test(ce.css('position')))
2295                         $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2297         }
2300 $.ui.plugin.add("resizable", "ghost", {
2302         start: function(event, ui) {
2304                 var self = $(this).data("resizable"), o = self.options, cs = self.size;
2306                 self.ghost = self.originalElement.clone();
2307                 self.ghost
2308                         .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
2309                         .addClass('ui-resizable-ghost')
2310                         .addClass(typeof o.ghost == 'string' ? o.ghost : '');
2312                 self.ghost.appendTo(self.helper);
2314         },
2316         resize: function(event, ui){
2317                 var self = $(this).data("resizable"), o = self.options;
2318                 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
2319         },
2321         stop: function(event, ui){
2322                 var self = $(this).data("resizable"), o = self.options;
2323                 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
2324         }
2328 $.ui.plugin.add("resizable", "grid", {
2330         resize: function(event, ui) {
2331                 var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
2332                 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
2333                 var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
2335                 if (/^(se|s|e)$/.test(a)) {
2336                         self.size.width = os.width + ox;
2337                         self.size.height = os.height + oy;
2338                 }
2339                 else if (/^(ne)$/.test(a)) {
2340                         self.size.width = os.width + ox;
2341                         self.size.height = os.height + oy;
2342                         self.position.top = op.top - oy;
2343                 }
2344                 else if (/^(sw)$/.test(a)) {
2345                         self.size.width = os.width + ox;
2346                         self.size.height = os.height + oy;
2347                         self.position.left = op.left - ox;
2348                 }
2349                 else {
2350                         self.size.width = os.width + ox;
2351                         self.size.height = os.height + oy;
2352                         self.position.top = op.top - oy;
2353                         self.position.left = op.left - ox;
2354                 }
2355         }
2359 var num = function(v) {
2360         return parseInt(v, 10) || 0;
2363 var isNumber = function(value) {
2364         return !isNaN(parseInt(value, 10));
2367 })(jQuery);
2369  * jQuery UI Selectable 1.7.2
2371  * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
2372  * Dual licensed under the MIT (MIT-LICENSE.txt)
2373  * and GPL (GPL-LICENSE.txt) licenses.
2375  * http://docs.jquery.com/UI/Selectables
2377  * Depends:
2378  *      ui.core.js
2379  */
2380 (function($) {
2382 $.widget("ui.selectable", $.extend({}, $.ui.mouse, {
2384         _init: function() {
2385                 var self = this;
2387                 this.element.addClass("ui-selectable");
2389                 this.dragged = false;
2391                 // cache selectee children based on filter
2392                 var selectees;
2393                 this.refresh = function() {
2394                         selectees = $(self.options.filter, self.element[0]);
2395                         selectees.each(function() {
2396                                 var $this = $(this);
2397                                 var pos = $this.offset();
2398                                 $.data(this, "selectable-item", {
2399                                         element: this,
2400                                         $element: $this,
2401                                         left: pos.left,
2402                                         top: pos.top,
2403                                         right: pos.left + $this.outerWidth(),
2404                                         bottom: pos.top + $this.outerHeight(),
2405                                         startselected: false,
2406                                         selected: $this.hasClass('ui-selected'),
2407                                         selecting: $this.hasClass('ui-selecting'),
2408                                         unselecting: $this.hasClass('ui-unselecting')
2409                                 });
2410                         });
2411                 };
2412                 this.refresh();
2414                 this.selectees = selectees.addClass("ui-selectee");
2416                 this._mouseInit();
2418                 this.helper = $(document.createElement('div'))
2419                         .css({border:'1px dotted black'})
2420                         .addClass("ui-selectable-helper");
2421         },
2423         destroy: function() {
2424                 this.element
2425                         .removeClass("ui-selectable ui-selectable-disabled")
2426                         .removeData("selectable")
2427                         .unbind(".selectable");
2428                 this._mouseDestroy();
2429         },
2431         _mouseStart: function(event) {
2432                 var self = this;
2434                 this.opos = [event.pageX, event.pageY];
2436                 if (this.options.disabled)
2437                         return;
2439                 var options = this.options;
2441                 this.selectees = $(options.filter, this.element[0]);
2443                 this._trigger("start", event);
2445                 $(options.appendTo).append(this.helper);
2446                 // position helper (lasso)
2447                 this.helper.css({
2448                         "z-index": 100,
2449                         "position": "absolute",
2450                         "left": event.clientX,
2451                         "top": event.clientY,
2452                         "width": 0,
2453                         "height": 0
2454                 });
2456                 if (options.autoRefresh) {
2457                         this.refresh();
2458                 }
2460                 this.selectees.filter('.ui-selected').each(function() {
2461                         var selectee = $.data(this, "selectable-item");
2462                         selectee.startselected = true;
2463                         if (!event.metaKey) {
2464                                 selectee.$element.removeClass('ui-selected');
2465                                 selectee.selected = false;
2466                                 selectee.$element.addClass('ui-unselecting');
2467                                 selectee.unselecting = true;
2468                                 // selectable UNSELECTING callback
2469                                 self._trigger("unselecting", event, {
2470                                         unselecting: selectee.element
2471                                 });
2472                         }
2473                 });
2475                 $(event.target).parents().andSelf().each(function() {
2476                         var selectee = $.data(this, "selectable-item");
2477                         if (selectee) {
2478                                 selectee.$element.removeClass("ui-unselecting").addClass('ui-selecting');
2479                                 selectee.unselecting = false;
2480                                 selectee.selecting = true;
2481                                 selectee.selected = true;
2482                                 // selectable SELECTING callback
2483                                 self._trigger("selecting", event, {
2484                                         selecting: selectee.element
2485                                 });
2486                                 return false;
2487                         }
2488                 });
2490         },
2492         _mouseDrag: function(event) {
2493                 var self = this;
2494                 this.dragged = true;
2496                 if (this.options.disabled)
2497                         return;
2499                 var options = this.options;
2501                 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
2502                 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
2503                 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
2504                 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
2506                 this.selectees.each(function() {
2507                         var selectee = $.data(this, "selectable-item");
2508                         //prevent helper from being selected if appendTo: selectable
2509                         if (!selectee || selectee.element == self.element[0])
2510                                 return;
2511                         var hit = false;
2512                         if (options.tolerance == 'touch') {
2513                                 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
2514                         } else if (options.tolerance == 'fit') {
2515                                 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
2516                         }
2518                         if (hit) {
2519                                 // SELECT
2520                                 if (selectee.selected) {
2521                                         selectee.$element.removeClass('ui-selected');
2522                                         selectee.selected = false;
2523                                 }
2524                                 if (selectee.unselecting) {
2525                                         selectee.$element.removeClass('ui-unselecting');
2526                                         selectee.unselecting = false;
2527                                 }
2528                                 if (!selectee.selecting) {
2529                                         selectee.$element.addClass('ui-selecting');
2530                                         selectee.selecting = true;
2531                                         // selectable SELECTING callback
2532                                         self._trigger("selecting", event, {
2533                                                 selecting: selectee.element
2534                                         });
2535                                 }
2536                         } else {
2537                                 // UNSELECT
2538                                 if (selectee.selecting) {
2539                                         if (event.metaKey && selectee.startselected) {
2540                                                 selectee.$element.removeClass('ui-selecting');
2541                                                 selectee.selecting = false;
2542                                                 selectee.$element.addClass('ui-selected');
2543                                                 selectee.selected = true;
2544                                         } else {
2545                                                 selectee.$element.removeClass('ui-selecting');
2546                                                 selectee.selecting = false;
2547                                                 if (selectee.startselected) {
2548                                                         selectee.$element.addClass('ui-unselecting');
2549                                                         selectee.unselecting = true;
2550                                                 }
2551                                                 // selectable UNSELECTING callback
2552                                                 self._trigger("unselecting", event, {
2553                                                         unselecting: selectee.element
2554                                                 });
2555                                         }
2556                                 }
2557                                 if (selectee.selected) {
2558                                         if (!event.metaKey && !selectee.startselected) {
2559                                                 selectee.$element.removeClass('ui-selected');
2560                                                 selectee.selected = false;
2562                                                 selectee.$element.addClass('ui-unselecting');
2563                                                 selectee.unselecting = true;
2564                                                 // selectable UNSELECTING callback
2565                                                 self._trigger("unselecting", event, {
2566                                                         unselecting: selectee.element
2567                                                 });
2568                                         }
2569                                 }
2570                         }
2571                 });
2573                 return false;
2574         },
2576         _mouseStop: function(event) {
2577                 var self = this;
2579                 this.dragged = false;
2581                 var options = this.options;
2583                 $('.ui-unselecting', this.element[0]).each(function() {
2584                         var selectee = $.data(this, "selectable-item");
2585                         selectee.$element.removeClass('ui-unselecting');
2586                         selectee.unselecting = false;
2587                         selectee.startselected = false;
2588                         self._trigger("unselected", event, {
2589                                 unselected: selectee.element
2590                         });
2591                 });
2592                 $('.ui-selecting', this.element[0]).each(function() {
2593                         var selectee = $.data(this, "selectable-item");
2594                         selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
2595                         selectee.selecting = false;
2596                         selectee.selected = true;
2597                         selectee.startselected = true;
2598                         self._trigger("selected", event, {
2599                                 selected: selectee.element
2600                         });
2601                 });
2602                 this._trigger("stop", event);
2604                 this.helper.remove();
2606                 return false;
2607         }
2609 }));
2611 $.extend($.ui.selectable, {
2612         version: "1.7.2",
2613         defaults: {
2614                 appendTo: 'body',
2615                 autoRefresh: true,
2616                 cancel: ":input,option",
2617                 delay: 0,
2618                 distance: 0,
2619                 filter: '*',
2620                 tolerance: 'touch'
2621         }
2624 })(jQuery);