2 * jQuery UI Dialog 1.8.11
4 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT or GPL Version 2 licenses.
6 * http://jquery.org/license
8 * http://docs.jquery.com/UI/Dialog
14 * jquery.ui.draggable.js
16 * jquery.ui.position.js
17 * jquery.ui.resizable.js
18 * jquery.ui.droppable.js
20 (function( $, undefined ) {
25 'ui-widget-content ' +
27 sizeRelatedOptions
= {
36 resizableRelatedOptions
= {
43 $.widget("ui.dialog", {
62 // ensure that the titlebar is never outside the document
63 using: function(pos
) {
64 var topOffset
= $(this).css(pos
).offset().top
;
66 $(this).css('top', pos
.top
- topOffset
);
79 this.originalTitle
= this.element
.attr('title');
80 // #5742 - .attr() might return a DOMElement
81 if ( typeof this.originalTitle
!== "string" ) {
82 this.originalTitle
= "";
85 this.options
.title
= this.options
.title
|| this.originalTitle
;
87 options
= self
.options
,
89 title
= options
.title
|| ' ',
90 titleId
= $.ui
.dialog
.getTitleId(self
.element
),
92 uiDialog
= (self
.uiDialog
= $('<div></div>'))
93 .appendTo(document
.body
)
95 .addClass(uiDialogClasses
+ options
.dialogClass
)
97 zIndex
: options
.zIndex
99 // setting tabIndex makes the div focusable
100 // setting outline to 0 prevents a border on focus in Mozilla
101 .attr('tabIndex', -1).css('outline', 0).keydown(function(event
) {
102 if (options
.closeOnEscape
&& event
.keyCode
&&
103 event
.keyCode
=== $.ui
.keyCode
.ESCAPE
) {
106 event
.preventDefault();
111 'aria-labelledby': titleId
113 .mousedown(function(event
) {
114 self
.moveToTop(false, event
);
117 uiDialogContent
= self
.element
121 'ui-dialog-content ' +
125 uiDialogTitlebar
= (self
.uiDialogTitlebar
= $('<div></div>'))
127 'ui-dialog-titlebar ' +
128 'ui-widget-header ' +
132 .prependTo(uiDialog
),
134 uiDialogTitlebarClose
= $('<a href="#"></a>')
136 'ui-dialog-titlebar-close ' +
139 .attr('role', 'button')
142 uiDialogTitlebarClose
.addClass('ui-state-hover');
145 uiDialogTitlebarClose
.removeClass('ui-state-hover');
149 uiDialogTitlebarClose
.addClass('ui-state-focus');
152 uiDialogTitlebarClose
.removeClass('ui-state-focus');
154 .click(function(event
) {
158 .appendTo(uiDialogTitlebar
),
160 uiDialogTitlebarCloseText
= (self
.uiDialogTitlebarCloseText
= $('<span></span>'))
165 .text(options
.closeText
)
166 .appendTo(uiDialogTitlebarClose
),
168 uiDialogTitle
= $('<span></span>')
169 .addClass('ui-dialog-title')
172 .prependTo(uiDialogTitlebar
);
174 //handling of deprecated beforeclose (vs beforeClose) option
175 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
176 //TODO: remove in 1.9pre
177 if ($.isFunction(options
.beforeclose
) && !$.isFunction(options
.beforeClose
)) {
178 options
.beforeClose
= options
.beforeclose
;
181 uiDialogTitlebar
.find("*").add(uiDialogTitlebar
).disableSelection();
183 if (options
.draggable
&& $.fn
.draggable
) {
184 self
._makeDraggable();
186 if (options
.resizable
&& $.fn
.resizable
) {
187 self
._makeResizable();
190 self
._createButtons(options
.buttons
);
191 self
._isOpen
= false;
199 if ( this.options
.autoOpen
) {
204 destroy: function() {
208 self
.overlay
.destroy();
210 self
.uiDialog
.hide();
213 .removeData('dialog')
214 .removeClass('ui-dialog-content ui-widget-content')
215 .hide().appendTo('body');
216 self
.uiDialog
.remove();
218 if (self
.originalTitle
) {
219 self
.element
.attr('title', self
.originalTitle
);
226 return this.uiDialog
;
229 close: function(event
) {
233 if (false === self
._trigger('beforeClose', event
)) {
238 self
.overlay
.destroy();
240 self
.uiDialog
.unbind('keypress.ui-dialog');
242 self
._isOpen
= false;
244 if (self
.options
.hide
) {
245 self
.uiDialog
.hide(self
.options
.hide
, function() {
246 self
._trigger('close', event
);
249 self
.uiDialog
.hide();
250 self
._trigger('close', event
);
253 $.ui
.dialog
.overlay
.resize();
255 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
256 if (self
.options
.modal
) {
258 $('.ui-dialog').each(function() {
259 if (this !== self
.uiDialog
[0]) {
260 thisZ
= $(this).css('z-index');
262 maxZ
= Math
.max(maxZ
, thisZ
);
266 $.ui
.dialog
.maxZ
= maxZ
;
276 // the force parameter allows us to move modal dialogs to their correct
278 moveToTop: function(force
, event
) {
280 options
= self
.options
,
283 if ((options
.modal
&& !force
) ||
284 (!options
.stack
&& !options
.modal
)) {
285 return self
._trigger('focus', event
);
288 if (options
.zIndex
> $.ui
.dialog
.maxZ
) {
289 $.ui
.dialog
.maxZ
= options
.zIndex
;
292 $.ui
.dialog
.maxZ
+= 1;
293 self
.overlay
.$el
.css('z-index', $.ui
.dialog
.overlay
.maxZ
= $.ui
.dialog
.maxZ
);
296 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
297 // http://ui.jquery.com/bugs/ticket/3193
298 saveScroll
= { scrollTop
: self
.element
.attr('scrollTop'), scrollLeft
: self
.element
.attr('scrollLeft') };
299 $.ui
.dialog
.maxZ
+= 1;
300 self
.uiDialog
.css('z-index', $.ui
.dialog
.maxZ
);
301 self
.element
.attr(saveScroll
);
302 self
._trigger('focus', event
);
308 if (this._isOpen
) { return; }
311 options
= self
.options
,
312 uiDialog
= self
.uiDialog
;
314 self
.overlay
= options
.modal
? new $.ui
.dialog
.overlay(self
) : null;
316 self
._position(options
.position
);
317 uiDialog
.show(options
.show
);
318 self
.moveToTop(true);
320 // prevent tabbing out of modal dialogs
322 uiDialog
.bind('keypress.ui-dialog', function(event
) {
323 if (event
.keyCode
!== $.ui
.keyCode
.TAB
) {
327 var tabbables
= $(':tabbable', this),
328 first
= tabbables
.filter(':first'),
329 last
= tabbables
.filter(':last');
331 if (event
.target
=== last
[0] && !event
.shiftKey
) {
334 } else if (event
.target
=== first
[0] && event
.shiftKey
) {
341 // set focus to the first tabbable element in the content area or the first button
342 // if there are no tabbable elements, set focus on the dialog itself
343 $(self
.element
.find(':tabbable').get().concat(
344 uiDialog
.find('.ui-dialog-buttonpane :tabbable').get().concat(
345 uiDialog
.get()))).eq(0).focus();
348 self
._trigger('open');
353 _createButtons: function(buttons
) {
356 uiDialogButtonPane
= $('<div></div>')
358 'ui-dialog-buttonpane ' +
359 'ui-widget-content ' +
362 uiButtonSet
= $( "<div></div>" )
363 .addClass( "ui-dialog-buttonset" )
364 .appendTo( uiDialogButtonPane
);
366 // if we already have a button pane, remove it
367 self
.uiDialog
.find('.ui-dialog-buttonpane').remove();
369 if (typeof buttons
=== 'object' && buttons
!== null) {
370 $.each(buttons
, function() {
371 return !(hasButtons
= true);
375 $.each(buttons
, function(name
, props
) {
376 props
= $.isFunction( props
) ?
377 { click
: props
, text
: name
} :
379 var button
= $('<button type="button"></button>')
383 props
.click
.apply(self
.element
[0], arguments
);
385 .appendTo(uiButtonSet
);
390 uiDialogButtonPane
.appendTo(self
.uiDialog
);
394 _makeDraggable: function() {
396 options
= self
.options
,
400 function filteredUi(ui
) {
402 position
: ui
.position
,
407 self
.uiDialog
.draggable({
408 cancel
: '.ui-dialog-content, .ui-dialog-titlebar-close',
409 handle
: '.ui-dialog-titlebar',
410 containment
: 'document',
411 start: function(event
, ui
) {
412 heightBeforeDrag
= options
.height
=== "auto" ? "auto" : $(this).height();
413 $(this).height($(this).height()).addClass("ui-dialog-dragging");
414 self
._trigger('dragStart', event
, filteredUi(ui
));
416 drag: function(event
, ui
) {
417 self
._trigger('drag', event
, filteredUi(ui
));
419 stop: function(event
, ui
) {
420 options
.position
= [ui
.position
.left
- doc
.scrollLeft(),
421 ui
.position
.top
- doc
.scrollTop()];
422 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag
);
423 self
._trigger('dragStop', event
, filteredUi(ui
));
424 $.ui
.dialog
.overlay
.resize();
429 _makeResizable: function(handles
) {
430 handles
= (handles
=== undefined ? this.options
.resizable
: handles
);
432 options
= self
.options
,
433 // .ui-resizable has position: relative defined in the stylesheet
434 // but dialogs have to use absolute or fixed positioning
435 position
= self
.uiDialog
.css('position'),
436 resizeHandles
= (typeof handles
=== 'string' ?
438 'n,e,s,w,se,sw,ne,nw'
441 function filteredUi(ui
) {
443 originalPosition
: ui
.originalPosition
,
444 originalSize
: ui
.originalSize
,
445 position
: ui
.position
,
450 self
.uiDialog
.resizable({
451 cancel
: '.ui-dialog-content',
452 containment
: 'document',
453 alsoResize
: self
.element
,
454 maxWidth
: options
.maxWidth
,
455 maxHeight
: options
.maxHeight
,
456 minWidth
: options
.minWidth
,
457 minHeight
: self
._minHeight(),
458 handles
: resizeHandles
,
459 start: function(event
, ui
) {
460 $(this).addClass("ui-dialog-resizing");
461 self
._trigger('resizeStart', event
, filteredUi(ui
));
463 resize: function(event
, ui
) {
464 self
._trigger('resize', event
, filteredUi(ui
));
466 stop: function(event
, ui
) {
467 $(this).removeClass("ui-dialog-resizing");
468 options
.height
= $(this).height();
469 options
.width
= $(this).width();
470 self
._trigger('resizeStop', event
, filteredUi(ui
));
471 $.ui
.dialog
.overlay
.resize();
474 .css('position', position
)
475 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
478 _minHeight: function() {
479 var options
= this.options
;
481 if (options
.height
=== 'auto') {
482 return options
.minHeight
;
484 return Math
.min(options
.minHeight
, options
.height
);
488 _position: function(position
) {
494 // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
495 // if (typeof position == 'string' || $.isArray(position)) {
496 // myAt = $.isArray(position) ? position : position.split(' ');
498 if (typeof position
=== 'string' || (typeof position
=== 'object' && '0' in position
)) {
499 myAt
= position
.split
? position
.split(' ') : [position
[0], position
[1]];
500 if (myAt
.length
=== 1) {
504 $.each(['left', 'top'], function(i
, offsetPosition
) {
505 if (+myAt
[i
] === myAt
[i
]) {
507 myAt
[i
] = offsetPosition
;
514 offset
: offset
.join(" ")
518 position
= $.extend({}, $.ui
.dialog
.prototype.options
.position
, position
);
520 position
= $.ui
.dialog
.prototype.options
.position
;
523 // need to show the dialog to get the actual offset in the position plugin
524 isVisible
= this.uiDialog
.is(':visible');
526 this.uiDialog
.show();
529 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
530 .css({ top
: 0, left
: 0 })
531 .position($.extend({ of: window
}, position
));
533 this.uiDialog
.hide();
537 _setOptions: function( options
) {
539 resizableOptions
= {},
542 $.each( options
, function( key
, value
) {
543 self
._setOption( key
, value
);
545 if ( key
in sizeRelatedOptions
) {
548 if ( key
in resizableRelatedOptions
) {
549 resizableOptions
[ key
] = value
;
556 if ( this.uiDialog
.is( ":data(resizable)" ) ) {
557 this.uiDialog
.resizable( "option", resizableOptions
);
561 _setOption: function(key
, value
){
563 uiDialog
= self
.uiDialog
;
566 //handling of deprecated beforeclose (vs beforeClose) option
567 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
568 //TODO: remove in 1.9pre
573 self
._createButtons(value
);
576 // ensure that we always pass a string
577 self
.uiDialogTitlebarCloseText
.text("" + value
);
581 .removeClass(self
.options
.dialogClass
)
582 .addClass(uiDialogClasses
+ value
);
586 uiDialog
.addClass('ui-dialog-disabled');
588 uiDialog
.removeClass('ui-dialog-disabled');
592 var isDraggable
= uiDialog
.is( ":data(draggable)" );
593 if ( isDraggable
&& !value
) {
594 uiDialog
.draggable( "destroy" );
597 if ( !isDraggable
&& value
) {
598 self
._makeDraggable();
602 self
._position(value
);
605 // currently resizable, becoming non-resizable
606 var isResizable
= uiDialog
.is( ":data(resizable)" );
607 if (isResizable
&& !value
) {
608 uiDialog
.resizable('destroy');
611 // currently resizable, changing handles
612 if (isResizable
&& typeof value
=== 'string') {
613 uiDialog
.resizable('option', 'handles', value
);
616 // currently non-resizable, becoming resizable
617 if (!isResizable
&& value
!== false) {
618 self
._makeResizable(value
);
622 // convert whatever was passed in o a string, for html() to not throw up
623 $(".ui-dialog-title", self
.uiDialogTitlebar
).html("" + (value
|| ' '));
627 $.Widget
.prototype._setOption
.apply(self
, arguments
);
631 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
632 * divs will both have width and height set, so we need to reset them
634 var options
= this.options
,
637 isVisible
= this.uiDialog
.is( ":visible" );
639 // reset content sizing
640 this.element
.show().css({
646 if (options
.minWidth
> options
.width
) {
647 options
.width
= options
.minWidth
;
650 // reset wrapper sizing
651 // determine the height of all the non-content elements
652 nonContentHeight
= this.uiDialog
.css({
657 minContentHeight
= Math
.max( 0, options
.minHeight
- nonContentHeight
);
659 if ( options
.height
=== "auto" ) {
660 // only needed for IE6 support
661 if ( $.support
.minHeight
) {
663 minHeight
: minContentHeight
,
667 this.uiDialog
.show();
668 var autoHeight
= this.element
.css( "height", "auto" ).height();
670 this.uiDialog
.hide();
672 this.element
.height( Math
.max( autoHeight
, minContentHeight
) );
675 this.element
.height( Math
.max( options
.height
- nonContentHeight
, 0 ) );
678 if (this.uiDialog
.is(':data(resizable)')) {
679 this.uiDialog
.resizable('option', 'minHeight', this._minHeight());
684 $.extend($.ui
.dialog
, {
690 getTitleId: function($el
) {
691 var id
= $el
.attr('id');
696 return 'ui-dialog-title-' + id
;
699 overlay: function(dialog
) {
700 this.$el
= $.ui
.dialog
.overlay
.create(dialog
);
704 $.extend($.ui
.dialog
.overlay
, {
706 // reuse old instances due to IE memory leak with alpha transparency (see #5185)
709 events
: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
710 function(event
) { return event
+ '.dialog-overlay'; }).join(' '),
711 create: function(dialog
) {
712 if (this.instances
.length
=== 0) {
713 // prevent use of anchors and inputs
714 // we use a setTimeout in case the overlay is created from an
715 // event that we're going to be cancelling (see #2804)
716 setTimeout(function() {
717 // handle $(el).dialog().dialog('close') (see #4065)
718 if ($.ui
.dialog
.overlay
.instances
.length
) {
719 $(document
).bind($.ui
.dialog
.overlay
.events
, function(event
) {
720 // stop events if the z-index of the target is < the z-index of the overlay
721 // we cannot return true when we don't want to cancel the event (#3523)
722 if ($(event
.target
).zIndex() < $.ui
.dialog
.overlay
.maxZ
) {
729 // allow closing by pressing the escape key
730 $(document
).bind('keydown.dialog-overlay', function(event
) {
731 if (dialog
.options
.closeOnEscape
&& event
.keyCode
&&
732 event
.keyCode
=== $.ui
.keyCode
.ESCAPE
) {
735 event
.preventDefault();
739 // handle window resize
740 $(window
).bind('resize.dialog-overlay', $.ui
.dialog
.overlay
.resize
);
743 var $el
= (this.oldInstances
.pop() || $('<div></div>').addClass('ui-widget-overlay'))
744 .appendTo(document
.body
)
747 height
: this.height()
754 this.instances
.push($el
);
758 destroy: function($el
) {
759 var indexOf
= $.inArray($el
, this.instances
);
761 this.oldInstances
.push(this.instances
.splice(indexOf
, 1)[0]);
764 if (this.instances
.length
=== 0) {
765 $([document
, window
]).unbind('.dialog-overlay');
770 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
772 $.each(this.instances
, function() {
773 maxZ
= Math
.max(maxZ
, this.css('z-index'));
782 if ($.browser
.msie
&& $.browser
.version
< 7) {
783 scrollHeight
= Math
.max(
784 document
.documentElement
.scrollHeight
,
785 document
.body
.scrollHeight
787 offsetHeight
= Math
.max(
788 document
.documentElement
.offsetHeight
,
789 document
.body
.offsetHeight
792 if (scrollHeight
< offsetHeight
) {
793 return $(window
).height() + 'px';
795 return scrollHeight
+ 'px';
797 // handle "good" browsers
799 return $(document
).height() + 'px';
807 if ($.browser
.msie
&& $.browser
.version
< 7) {
808 scrollWidth
= Math
.max(
809 document
.documentElement
.scrollWidth
,
810 document
.body
.scrollWidth
812 offsetWidth
= Math
.max(
813 document
.documentElement
.offsetWidth
,
814 document
.body
.offsetWidth
817 if (scrollWidth
< offsetWidth
) {
818 return $(window
).width() + 'px';
820 return scrollWidth
+ 'px';
822 // handle "good" browsers
824 return $(document
).width() + 'px';
829 /* If the dialog is draggable and the user drags it past the
830 * right edge of the window, the document becomes wider so we
831 * need to stretch the overlay. If the user then drags the
832 * dialog back to the left, the document will become narrower,
833 * so we need to shrink the overlay to the appropriate size.
834 * This is handled by shrinking the overlay before setting it
835 * to the full document size.
837 var $overlays
= $([]);
838 $.each($.ui
.dialog
.overlay
.instances
, function() {
839 $overlays
= $overlays
.add(this);
846 width
: $.ui
.dialog
.overlay
.width(),
847 height
: $.ui
.dialog
.overlay
.height()
852 $.extend($.ui
.dialog
.overlay
.prototype, {
853 destroy: function() {
854 $.ui
.dialog
.overlay
.destroy(this.$el
);
858 /* jquery.ui.droppable.js */
860 $.widget("ui.droppable", {
861 widgetEventPrefix
: "drop",
869 tolerance
: 'intersect'
871 _create: function() {
873 var o
= this.options
, accept
= o
.accept
;
874 this.isover
= 0; this.isout
= 1;
876 this.accept
= $.isFunction(accept
) ? accept : function(d
) {
880 //Store the droppable's proportions
881 this.proportions
= { width
: this.element
[0].offsetWidth
, height
: this.element
[0].offsetHeight
};
883 // Add the reference and positions to the manager
884 $.ui
.ddmanager
.droppables
[o
.scope
] = $.ui
.ddmanager
.droppables
[o
.scope
] || [];
885 $.ui
.ddmanager
.droppables
[o
.scope
].push(this);
887 (o
.addClasses
&& this.element
.addClass("ui-droppable"));
891 destroy: function() {
892 var drop
= $.ui
.ddmanager
.droppables
[this.options
.scope
];
893 for ( var i
= 0; i
< drop
.length
; i
++ )
894 if ( drop
[i
] == this )
898 .removeClass("ui-droppable ui-droppable-disabled")
899 .removeData("droppable")
900 .unbind(".droppable");
905 _setOption: function(key
, value
) {
907 if(key
== 'accept') {
908 this.accept
= $.isFunction(value
) ? value : function(d
) {
912 $.Widget
.prototype._setOption
.apply(this, arguments
);
915 _activate: function(event
) {
916 var draggable
= $.ui
.ddmanager
.current
;
917 if(this.options
.activeClass
) this.element
.addClass(this.options
.activeClass
);
918 (draggable
&& this._trigger('activate', event
, this.ui(draggable
)));
921 _deactivate: function(event
) {
922 var draggable
= $.ui
.ddmanager
.current
;
923 if(this.options
.activeClass
) this.element
.removeClass(this.options
.activeClass
);
924 (draggable
&& this._trigger('deactivate', event
, this.ui(draggable
)));
927 _over: function(event
) {
929 var draggable
= $.ui
.ddmanager
.current
;
930 if (!draggable
|| (draggable
.currentItem
|| draggable
.element
)[0] == this.element
[0]) return; // Bail if draggable and droppable are same element
932 if (this.accept
.call(this.element
[0],(draggable
.currentItem
|| draggable
.element
))) {
933 if(this.options
.hoverClass
) this.element
.addClass(this.options
.hoverClass
);
934 this._trigger('over', event
, this.ui(draggable
));
939 _out: function(event
) {
941 var draggable
= $.ui
.ddmanager
.current
;
942 if (!draggable
|| (draggable
.currentItem
|| draggable
.element
)[0] == this.element
[0]) return; // Bail if draggable and droppable are same element
944 if (this.accept
.call(this.element
[0],(draggable
.currentItem
|| draggable
.element
))) {
945 if(this.options
.hoverClass
) this.element
.removeClass(this.options
.hoverClass
);
946 this._trigger('out', event
, this.ui(draggable
));
951 _drop: function(event
,custom
) {
953 var draggable
= custom
|| $.ui
.ddmanager
.current
;
954 if (!draggable
|| (draggable
.currentItem
|| draggable
.element
)[0] == this.element
[0]) return false; // Bail if draggable and droppable are same element
956 var childrenIntersection
= false;
957 this.element
.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
958 var inst
= $.data(this, 'droppable');
961 && !inst
.options
.disabled
962 && inst
.options
.scope
== draggable
.options
.scope
963 && inst
.accept
.call(inst
.element
[0], (draggable
.currentItem
|| draggable
.element
))
964 && $.ui
.intersect(draggable
, $.extend(inst
, { offset
: inst
.element
.offset() }), inst
.options
.tolerance
)
965 ) { childrenIntersection
= true; return false; }
967 if(childrenIntersection
) return false;
969 if(this.accept
.call(this.element
[0],(draggable
.currentItem
|| draggable
.element
))) {
970 if(this.options
.activeClass
) this.element
.removeClass(this.options
.activeClass
);
971 if(this.options
.hoverClass
) this.element
.removeClass(this.options
.hoverClass
);
972 this._trigger('drop', event
, this.ui(draggable
));
982 draggable
: (c
.currentItem
|| c
.element
),
984 position
: c
.position
,
985 offset
: c
.positionAbs
991 $.extend($.ui
.droppable
, {
995 $.ui
.intersect = function(draggable
, droppable
, toleranceMode
) {
997 if (!droppable
.offset
) return false;
999 var x1
= (draggable
.positionAbs
|| draggable
.position
.absolute
).left
, x2
= x1
+ draggable
.helperProportions
.width
,
1000 y1
= (draggable
.positionAbs
|| draggable
.position
.absolute
).top
, y2
= y1
+ draggable
.helperProportions
.height
;
1001 var l
= droppable
.offset
.left
, r
= l
+ droppable
.proportions
.width
,
1002 t
= droppable
.offset
.top
, b
= t
+ droppable
.proportions
.height
;
1004 switch (toleranceMode
) {
1006 return (l
<= x1
&& x2
<= r
1007 && t
<= y1
&& y2
<= b
);
1010 return (l
< x1
+ (draggable
.helperProportions
.width
/ 2) // Right Half
1011 && x2
- (draggable
.helperProportions
.width
/ 2) < r
// Left Half
1012 && t
< y1
+ (draggable
.helperProportions
.height
/ 2) // Bottom Half
1013 && y2
- (draggable
.helperProportions
.height
/ 2) < b
); // Top Half
1016 var draggableLeft
= ((draggable
.positionAbs
|| draggable
.position
.absolute
).left
+ (draggable
.clickOffset
|| draggable
.offset
.click
).left
),
1017 draggableTop
= ((draggable
.positionAbs
|| draggable
.position
.absolute
).top
+ (draggable
.clickOffset
|| draggable
.offset
.click
).top
),
1018 isOver
= $.ui
.isOver(draggableTop
, draggableLeft
, t
, l
, droppable
.proportions
.height
, droppable
.proportions
.width
);
1023 (y1
>= t
&& y1
<= b
) || // Top edge touching
1024 (y2
>= t
&& y2
<= b
) || // Bottom edge touching
1025 (y1
< t
&& y2
> b
) // Surrounded vertically
1027 (x1
>= l
&& x1
<= r
) || // Left edge touching
1028 (x2
>= l
&& x2
<= r
) || // Right edge touching
1029 (x1
< l
&& x2
> r
) // Surrounded horizontally
1040 This manager tracks offsets of draggables and droppables
1044 droppables
: { 'default': [] },
1045 prepareOffsets: function(t
, event
) {
1047 var m
= $.ui
.ddmanager
.droppables
[t
.options
.scope
] || [];
1048 var type
= event
? event
.type
: null; // workaround for #2317
1049 var list
= (t
.currentItem
|| t
.element
).find(":data(droppable)").andSelf();
1051 droppablesLoop
: for (var i
= 0; i
< m
.length
; i
++) {
1053 if(m
[i
].options
.disabled
|| (t
&& !m
[i
].accept
.call(m
[i
].element
[0],(t
.currentItem
|| t
.element
)))) continue; //No disabled and non-accepted
1054 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
1055 m
[i
].visible
= m
[i
].element
.css("display") != "none"; if(!m
[i
].visible
) continue; //If the element is not visible, continue
1057 if(type
== "mousedown") m
[i
]._activate
.call(m
[i
], event
); //Activate the droppable if used directly from draggables
1059 m
[i
].offset
= m
[i
].element
.offset();
1060 m
[i
].proportions
= { width
: m
[i
].element
[0].offsetWidth
, height
: m
[i
].element
[0].offsetHeight
};
1065 drop: function(draggable
, event
) {
1067 var dropped
= false;
1068 $.each($.ui
.ddmanager
.droppables
[draggable
.options
.scope
] || [], function() {
1070 if(!this.options
) return;
1071 if (!this.options
.disabled
&& this.visible
&& $.ui
.intersect(draggable
, this, this.options
.tolerance
))
1072 dropped
= dropped
|| this._drop
.call(this, event
);
1074 if (!this.options
.disabled
&& this.visible
&& this.accept
.call(this.element
[0],(draggable
.currentItem
|| draggable
.element
))) {
1075 this.isout
= 1; this.isover
= 0;
1076 this._deactivate
.call(this, event
);
1083 drag: function(draggable
, event
) {
1085 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
1086 if(draggable
.options
.refreshPositions
) $.ui
.ddmanager
.prepareOffsets(draggable
, event
);
1088 //Run through all droppables and check their positions based on specific tolerance options
1089 $.each($.ui
.ddmanager
.droppables
[draggable
.options
.scope
] || [], function() {
1091 if(this.options
.disabled
|| this.greedyChild
|| !this.visible
) return;
1092 var intersects
= $.ui
.intersect(draggable
, this, this.options
.tolerance
);
1094 var c
= !intersects
&& this.isover
== 1 ? 'isout' : (intersects
&& this.isover
== 0 ? 'isover' : null);
1098 if (this.options
.greedy
) {
1099 var parent
= this.element
.parents(':data(droppable):eq(0)');
1100 if (parent
.length
) {
1101 parentInstance
= $.data(parent
[0], 'droppable');
1102 parentInstance
.greedyChild
= (c
== 'isover' ? 1 : 0);
1106 // we just moved into a greedy child
1107 if (parentInstance
&& c
== 'isover') {
1108 parentInstance
['isover'] = 0;
1109 parentInstance
['isout'] = 1;
1110 parentInstance
._out
.call(parentInstance
, event
);
1113 this[c
] = 1; this[c
== 'isout' ? 'isover' : 'isout'] = 0;
1114 this[c
== "isover" ? "_over" : "_out"].call(this, event
);
1116 // we just moved out of a greedy child
1117 if (parentInstance
&& c
== 'isout') {
1118 parentInstance
['isout'] = 0;
1119 parentInstance
['isover'] = 1;
1120 parentInstance
._over
.call(parentInstance
, event
);