diff options
Diffstat (limited to 'ui/widgets')
-rw-r--r-- | ui/widgets/autocomplete.js | 4 | ||||
-rw-r--r-- | ui/widgets/button.js | 87 | ||||
-rw-r--r-- | ui/widgets/controlgroup.js | 2 | ||||
-rw-r--r-- | ui/widgets/dialog.js | 29 | ||||
-rw-r--r-- | ui/widgets/menu.js | 96 | ||||
-rw-r--r-- | ui/widgets/resizable.js | 5 | ||||
-rw-r--r-- | ui/widgets/sortable.js | 297 | ||||
-rw-r--r-- | ui/widgets/tabs.js | 2 |
8 files changed, 321 insertions, 201 deletions
diff --git a/ui/widgets/autocomplete.js b/ui/widgets/autocomplete.js index c5bddc074..60d326544 100644 --- a/ui/widgets/autocomplete.js +++ b/ui/widgets/autocomplete.js @@ -447,7 +447,7 @@ $.widget( "ui.autocomplete", { _response: function() { var index = ++this.requestIndex; - return $.proxy( function( content ) { + return function( content ) { if ( index === this.requestIndex ) { this.__response( content ); } @@ -456,7 +456,7 @@ $.widget( "ui.autocomplete", { if ( !this.pending ) { this._removeClass( "ui-autocomplete-loading" ); } - }, this ); + }.bind( this ); }, __response: function( content ) { diff --git a/ui/widgets/button.js b/ui/widgets/button.js index 50da9f9e2..42cfec06d 100644 --- a/ui/widgets/button.js +++ b/ui/widgets/button.js @@ -342,22 +342,81 @@ if ( $.uiBackCompat !== false ) { } ); $.fn.button = ( function( orig ) { - return function() { - if ( !this.length || ( this.length && this[ 0 ].tagName !== "INPUT" ) || - ( this.length && this[ 0 ].tagName === "INPUT" && ( - this.attr( "type" ) !== "checkbox" && this.attr( "type" ) !== "radio" - ) ) ) { - return orig.apply( this, arguments ); - } - if ( !$.ui.checkboxradio ) { - $.error( "Checkboxradio widget missing" ); - } - if ( arguments.length === 0 ) { - return this.checkboxradio( { - "icon": false + return function( options ) { + var isMethodCall = typeof options === "string"; + var args = Array.prototype.slice.call( arguments, 1 ); + var returnValue = this; + + if ( isMethodCall ) { + + // If this is an empty collection, we need to have the instance method + // return undefined instead of the jQuery instance + if ( !this.length && options === "instance" ) { + returnValue = undefined; + } else { + this.each( function() { + var methodValue; + var type = $( this ).attr( "type" ); + var name = type !== "checkbox" && type !== "radio" ? + "button" : + "checkboxradio"; + var instance = $.data( this, "ui-" + name ); + + if ( options === "instance" ) { + returnValue = instance; + return false; + } + + if ( !instance ) { + return $.error( "cannot call methods on button" + + " prior to initialization; " + + "attempted to call method '" + options + "'" ); + } + + if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) { + return $.error( "no such method '" + options + "' for button" + + " widget instance" ); + } + + methodValue = instance[ options ].apply( instance, args ); + + if ( methodValue !== instance && methodValue !== undefined ) { + returnValue = methodValue && methodValue.jquery ? + returnValue.pushStack( methodValue.get() ) : + methodValue; + return false; + } + } ); + } + } else { + + // Allow multiple hashes to be passed on init + if ( args.length ) { + options = $.widget.extend.apply( null, [ options ].concat( args ) ); + } + + this.each( function() { + var type = $( this ).attr( "type" ); + var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio"; + var instance = $.data( this, "ui-" + name ); + + if ( instance ) { + instance.option( options || {} ); + if ( instance._init ) { + instance._init(); + } + } else { + if ( name === "button" ) { + orig.call( $( this ), options ); + return; + } + + $( this ).checkboxradio( $.extend( { icon: false }, options ) ); + } } ); } - return this.checkboxradio.apply( this, arguments ); + + return returnValue; }; } )( $.fn.button ); diff --git a/ui/widgets/controlgroup.js b/ui/widgets/controlgroup.js index 6f357948d..c79f3fcaf 100644 --- a/ui/widgets/controlgroup.js +++ b/ui/widgets/controlgroup.js @@ -150,7 +150,7 @@ return $.widget( "ui.controlgroup", { } ); } ); - this.childWidgets = $( $.unique( childWidgets ) ); + this.childWidgets = $( $.uniqueSort( childWidgets ) ); this._addClass( this.childWidgets, "ui-controlgroup-item" ); }, diff --git a/ui/widgets/dialog.js b/ui/widgets/dialog.js index c8829331f..01780daf3 100644 --- a/ui/widgets/dialog.js +++ b/ui/widgets/dialog.js @@ -289,7 +289,7 @@ $.widget( "ui.dialog", { that._trigger( "focus" ); } ); - // Track the dialog immediately upon openening in case a focus event + // Track the dialog immediately upon opening in case a focus event // somehow occurs outside of the dialog before an element inside the // dialog is focused (#10152) this._makeFocusTarget(); @@ -863,20 +863,19 @@ $.widget( "ui.dialog", { if ( !this.document.data( "ui-dialog-overlays" ) ) { // Prevent use of anchors and inputs - // Using _on() for an event handler shared across many instances is - // safe because the dialogs stack and must be closed in reverse order - this._on( this.document, { - focusin: function( event ) { - if ( isOpening ) { - return; - } - - if ( !this._allowInteraction( event ) ) { - event.preventDefault(); - this._trackingInstances()[ 0 ]._focusTabbable(); - } + // This doesn't use `_on()` because it is a shared event handler + // across all open modal dialogs. + this.document.on( "focusin.ui-dialog", function( event ) { + if ( isOpening ) { + return; } - } ); + + var instance = this._trackingInstances()[ 0 ]; + if ( !instance._allowInteraction( event ) ) { + event.preventDefault(); + instance._focusTabbable(); + } + }.bind( this ) ); } this.overlay = $( "<div>" ) @@ -899,7 +898,7 @@ $.widget( "ui.dialog", { var overlays = this.document.data( "ui-dialog-overlays" ) - 1; if ( !overlays ) { - this._off( this.document, "focusin" ); + this.document.off( "focusin.ui-dialog" ); this.document.removeData( "ui-dialog-overlays" ); } else { this.document.data( "ui-dialog-overlays", overlays ); diff --git a/ui/widgets/menu.js b/ui/widgets/menu.js index 49da26865..302d202ae 100644 --- a/ui/widgets/menu.js +++ b/ui/widgets/menu.js @@ -64,6 +64,7 @@ return $.widget( "ui.menu", { // Flag used to prevent firing of the click handler // as the event bubbles up through nested menus this.mouseHandled = false; + this.lastMousePosition = { x: null, y: null }; this.element .uniqueId() .attr( { @@ -78,6 +79,8 @@ return $.widget( "ui.menu", { // them (focus should always stay on UL during navigation). "mousedown .ui-menu-item": function( event ) { event.preventDefault(); + + this._activateItem( event ); }, "click .ui-menu-item": function( event ) { var target = $( event.target ); @@ -107,36 +110,15 @@ return $.widget( "ui.menu", { } } }, - "mouseenter .ui-menu-item": function( event ) { - - // Ignore mouse events while typeahead is active, see #10458. - // Prevents focusing the wrong item when typeahead causes a scroll while the mouse - // is over an item in the menu - if ( this.previousFilter ) { - return; - } - - var actualTarget = $( event.target ).closest( ".ui-menu-item" ), - target = $( event.currentTarget ); - - // Ignore bubbled events on parent items, see #11641 - if ( actualTarget[ 0 ] !== target[ 0 ] ) { - return; - } - - // Remove ui-state-active class from siblings of the newly focused menu item - // to avoid a jump caused by adjacent elements both having a class with a border - this._removeClass( target.siblings().children( ".ui-state-active" ), - null, "ui-state-active" ); - this.focus( event, target ); - }, + "mouseenter .ui-menu-item": "_activateItem", + "mousemove .ui-menu-item": "_activateItem", mouseleave: "collapseAll", "mouseleave .ui-menu": "collapseAll", focus: function( event, keepActiveItem ) { // If there's already an active item, keep it active // If not, activate the first item - var item = this.active || this.element.find( this.options.items ).eq( 0 ); + var item = this.active || this._menuItems().first(); if ( !keepActiveItem ) { this.focus( event, item ); @@ -162,7 +144,7 @@ return $.widget( "ui.menu", { this._on( this.document, { click: function( event ) { if ( this._closeOnDocumentClick( event ) ) { - this.collapseAll( event ); + this.collapseAll( event, true ); } // Reset the mouseHandled flag @@ -171,6 +153,46 @@ return $.widget( "ui.menu", { } ); }, + _activateItem: function( event ) { + + // Ignore mouse events while typeahead is active, see #10458. + // Prevents focusing the wrong item when typeahead causes a scroll while the mouse + // is over an item in the menu + if ( this.previousFilter ) { + return; + } + + // If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356) + if ( event.clientX === this.lastMousePosition.x && + event.clientY === this.lastMousePosition.y ) { + return; + } + + this.lastMousePosition = { + x: event.clientX, + y: event.clientY + }; + + var actualTarget = $( event.target ).closest( ".ui-menu-item" ), + target = $( event.currentTarget ); + + // Ignore bubbled events on parent items, see #11641 + if ( actualTarget[ 0 ] !== target[ 0 ] ) { + return; + } + + // If the item is already active, there's nothing to do + if ( target.is( ".ui-state-active" ) ) { + return; + } + + // Remove ui-state-active class from siblings of the newly focused menu item + // to avoid a jump caused by adjacent elements both having a class with a border + this._removeClass( target.siblings().children( ".ui-state-active" ), + null, "ui-state-active" ); + this.focus( event, target ); + }, + _destroy: function() { var items = this.element.find( ".ui-menu-item" ) .removeAttr( "role aria-disabled" ), @@ -502,7 +524,7 @@ return $.widget( "ui.menu", { this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" ); this.activeMenu = currentMenu; - }, this.delay ); + }, all ? 0 : this.delay ); }, // With no arguments, closes the currently active menu - if nothing is active @@ -538,11 +560,7 @@ return $.widget( "ui.menu", { }, expand: function( event ) { - var newItem = this.active && - this.active - .children( ".ui-menu " ) - .find( this.options.items ) - .first(); + var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first(); if ( newItem && newItem.length ) { this._open( newItem.parent() ); @@ -570,21 +588,27 @@ return $.widget( "ui.menu", { return this.active && !this.active.nextAll( ".ui-menu-item" ).length; }, + _menuItems: function( menu ) { + return ( menu || this.element ) + .find( this.options.items ) + .filter( ".ui-menu-item" ); + }, + _move: function( direction, filter, event ) { var next; if ( this.active ) { if ( direction === "first" || direction === "last" ) { next = this.active [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) - .eq( -1 ); + .last(); } else { next = this.active [ direction + "All" ]( ".ui-menu-item" ) - .eq( 0 ); + .first(); } } if ( !next || !next.length || !this.active ) { - next = this.activeMenu.find( this.options.items )[ filter ](); + next = this._menuItems( this.activeMenu )[ filter ](); } this.focus( event, next ); @@ -610,7 +634,7 @@ return $.widget( "ui.menu", { this.focus( event, item ); } else { - this.focus( event, this.activeMenu.find( this.options.items ) + this.focus( event, this._menuItems( this.activeMenu ) [ !this.active ? "first" : "last" ]() ); } }, @@ -634,7 +658,7 @@ return $.widget( "ui.menu", { this.focus( event, item ); } else { - this.focus( event, this.activeMenu.find( this.options.items ).first() ); + this.focus( event, this._menuItems( this.activeMenu ).first() ); } }, diff --git a/ui/widgets/resizable.js b/ui/widgets/resizable.js index b5264ee53..36dd12514 100644 --- a/ui/widgets/resizable.js +++ b/ui/widgets/resizable.js @@ -187,15 +187,14 @@ $.widget( "ui.resizable", $.ui.mouse, { _destroy: function() { this._mouseDestroy(); + this._addedHandles.remove(); var wrapper, _destroy = function( exp ) { $( exp ) .removeData( "resizable" ) .removeData( "ui-resizable" ) - .off( ".resizable" ) - .find( ".ui-resizable-handle" ) - .remove(); + .off( ".resizable" ); }; // TODO: Unwrap at same DOM position diff --git a/ui/widgets/sortable.js b/ui/widgets/sortable.js index fcb33ace1..78fad26b9 100644 --- a/ui/widgets/sortable.js +++ b/ui/widgets/sortable.js @@ -195,6 +195,11 @@ return $.widget( "ui.sortable", $.ui.mouse, { // mouseCapture this.refreshPositions(); + //Prepare the dragged items parent + this.appendTo = $( o.appendTo !== "parent" ? + o.appendTo : + this.currentItem.parent() ); + //Create and append the visible helper this.helper = this._createHelper( event ); @@ -209,9 +214,6 @@ return $.widget( "ui.sortable", $.ui.mouse, { //Cache the margins of the original element this._cacheMargins(); - //Get the next scrolling parent - this.scrollParent = this.helper.scrollParent(); - //The element's absolute position on the page minus margins this.offset = this.currentItem.offset(); this.offset = { @@ -236,15 +238,6 @@ return $.widget( "ui.sortable", $.ui.mouse, { this.helper.css( "position", "absolute" ); this.cssPosition = this.helper.css( "position" ); - $.extend( this.offset, { - parent: this._getParentOffset() - } ); - - //Generate the original position - this.originalPosition = this._generatePosition( event ); - this.originalPageX = event.pageX; - this.originalPageY = event.pageY; - //Adjust the mouse offset relative to the helper if "cursorAt" is supplied ( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) ); @@ -263,6 +256,13 @@ return $.widget( "ui.sortable", $.ui.mouse, { //Create the placeholder this._createPlaceholder(); + //Get the next scrolling parent + this.scrollParent = this.placeholder.scrollParent(); + + $.extend( this.offset, { + parent: this._getParentOffset() + } ); + //Set a containment if given in the options if ( o.containment ) { this._setContainment(); @@ -330,77 +330,82 @@ return $.widget( "ui.sortable", $.ui.mouse, { this._addClass( this.helper, "ui-sortable-helper" ); - // Execute the drag once - this causes the helper not to be visiblebefore getting its - // correct position - this._mouseDrag( event ); - return true; + //Move the helper, if needed + if ( !this.helper.parent().is( this.appendTo ) ) { + this.helper.detach().appendTo( this.appendTo ); - }, + //Update position + this.offset.parent = this._getParentOffset(); + } - _mouseDrag: function( event ) { - var i, item, itemElement, intersection, - o = this.options, - scrolled = false; + //Generate the original position + this.position = this.originalPosition = this._generatePosition( event ); + this.originalPageX = event.pageX; + this.originalPageY = event.pageY; + this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" ); - //Compute the helpers position - this.position = this._generatePosition( event ); - this.positionAbs = this._convertPositionTo( "absolute" ); + this._mouseDrag( event ); - if ( !this.lastPositionAbs ) { - this.lastPositionAbs = this.positionAbs; - } + return true; - //Do scrolling - if ( this.options.scroll ) { - if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && - this.scrollParent[ 0 ].tagName !== "HTML" ) { + }, - if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) - - event.pageY < o.scrollSensitivity ) { - this.scrollParent[ 0 ].scrollTop = - scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed; - } else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) { - this.scrollParent[ 0 ].scrollTop = - scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed; - } + _scroll: function( event ) { + var o = this.options, + scrolled = false; - if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) - - event.pageX < o.scrollSensitivity ) { - this.scrollParent[ 0 ].scrollLeft = scrolled = - this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed; - } else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) { - this.scrollParent[ 0 ].scrollLeft = scrolled = - this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed; - } + if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && + this.scrollParent[ 0 ].tagName !== "HTML" ) { - } else { + if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) - + event.pageY < o.scrollSensitivity ) { + this.scrollParent[ 0 ].scrollTop = + scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed; + } else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) { + this.scrollParent[ 0 ].scrollTop = + scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed; + } - if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) { - scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed ); - } else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) < - o.scrollSensitivity ) { - scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed ); - } + if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) - + event.pageX < o.scrollSensitivity ) { + this.scrollParent[ 0 ].scrollLeft = scrolled = + this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed; + } else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) { + this.scrollParent[ 0 ].scrollLeft = scrolled = + this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed; + } - if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) { - scrolled = this.document.scrollLeft( - this.document.scrollLeft() - o.scrollSpeed - ); - } else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) < - o.scrollSensitivity ) { - scrolled = this.document.scrollLeft( - this.document.scrollLeft() + o.scrollSpeed - ); - } + } else { + if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) { + scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed ); + } else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) < + o.scrollSensitivity ) { + scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed ); } - if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) { - $.ui.ddmanager.prepareOffsets( this, event ); + if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) { + scrolled = this.document.scrollLeft( + this.document.scrollLeft() - o.scrollSpeed + ); + } else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) < + o.scrollSensitivity ) { + scrolled = this.document.scrollLeft( + this.document.scrollLeft() + o.scrollSpeed + ); } + } - //Regenerate the absolute position used for position checks + return scrolled; + }, + + _mouseDrag: function( event ) { + var i, item, itemElement, intersection, + o = this.options; + + //Compute the helpers position + this.position = this._generatePosition( event ); this.positionAbs = this._convertPositionTo( "absolute" ); //Set the helper position @@ -411,56 +416,79 @@ return $.widget( "ui.sortable", $.ui.mouse, { this.helper[ 0 ].style.top = this.position.top + "px"; } - //Rearrange - for ( i = this.items.length - 1; i >= 0; i-- ) { + //Post events to containers + this._contactContainers( event ); - //Cache variables and intersection, continue if no intersection - item = this.items[ i ]; - itemElement = item.item[ 0 ]; - intersection = this._intersectsWithPointer( item ); - if ( !intersection ) { - continue; - } + if ( this.innermostContainer !== null ) { - // Only put the placeholder inside the current Container, skip all - // items from other containers. This works because when moving - // an item from one container to another the - // currentContainer is switched before the placeholder is moved. - // - // Without this, moving items in "sub-sortables" can cause - // the placeholder to jitter between the outer and inner container. - if ( item.instance !== this.currentContainer ) { - continue; + //Do scrolling + if ( o.scroll ) { + if ( this._scroll( event ) !== false ) { + + //Update item positions used in position checks + this._refreshItemPositions( true ); + + if ( $.ui.ddmanager && !o.dropBehaviour ) { + $.ui.ddmanager.prepareOffsets( this, event ); + } + } } - // Cannot intersect with itself - // no useless actions that have been done before - // no action if the item moved is the parent of the item checked - if ( itemElement !== this.currentItem[ 0 ] && - this.placeholder[ intersection === 1 ? "next" : "prev" ]()[ 0 ] !== itemElement && - !$.contains( this.placeholder[ 0 ], itemElement ) && - ( this.options.type === "semi-dynamic" ? - !$.contains( this.element[ 0 ], itemElement ) : - true - ) - ) { - - this.direction = intersection === 1 ? "down" : "up"; - - if ( this.options.tolerance === "pointer" || this._intersectsWithSides( item ) ) { - this._rearrange( event, item ); - } else { - break; + this.dragDirection = { + vertical: this._getDragVerticalDirection(), + horizontal: this._getDragHorizontalDirection() + }; + + //Rearrange + for ( i = this.items.length - 1; i >= 0; i-- ) { + + //Cache variables and intersection, continue if no intersection + item = this.items[ i ]; + itemElement = item.item[ 0 ]; + intersection = this._intersectsWithPointer( item ); + if ( !intersection ) { + continue; + } + + // Only put the placeholder inside the current Container, skip all + // items from other containers. This works because when moving + // an item from one container to another the + // currentContainer is switched before the placeholder is moved. + // + // Without this, moving items in "sub-sortables" can cause + // the placeholder to jitter between the outer and inner container. + if ( item.instance !== this.currentContainer ) { + continue; } - this._trigger( "change", event, this._uiHash() ); - break; + // Cannot intersect with itself + // no useless actions that have been done before + // no action if the item moved is the parent of the item checked + if ( itemElement !== this.currentItem[ 0 ] && + this.placeholder[ intersection === 1 ? + "next" : "prev" ]()[ 0 ] !== itemElement && + !$.contains( this.placeholder[ 0 ], itemElement ) && + ( this.options.type === "semi-dynamic" ? + !$.contains( this.element[ 0 ], itemElement ) : + true + ) + ) { + + this.direction = intersection === 1 ? "down" : "up"; + + if ( this.options.tolerance === "pointer" || + this._intersectsWithSides( item ) ) { + this._rearrange( event, item ); + } else { + break; + } + + this._trigger( "change", event, this._uiHash() ); + break; + } } } - //Post events to containers - this._contactContainers( event ); - //Interconnect with droppables if ( $.ui.ddmanager ) { $.ui.ddmanager.drag( this, event ); @@ -663,8 +691,8 @@ return $.widget( "ui.sortable", $.ui.mouse, { return false; } - verticalDirection = this._getDragVerticalDirection(); - horizontalDirection = this._getDragHorizontalDirection(); + verticalDirection = this.dragDirection.vertical; + horizontalDirection = this.dragDirection.horizontal; return this.floating ? ( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) @@ -678,8 +706,8 @@ return $.widget( "ui.sortable", $.ui.mouse, { this.offset.click.top, item.top + ( item.height / 2 ), item.height ), isOverRightHalf = this._isOverAxis( this.positionAbs.left + this.offset.click.left, item.left + ( item.width / 2 ), item.width ), - verticalDirection = this._getDragVerticalDirection(), - horizontalDirection = this._getDragHorizontalDirection(); + verticalDirection = this.dragDirection.vertical, + horizontalDirection = this.dragDirection.horizontal; if ( this.floating && horizontalDirection ) { return ( ( horizontalDirection === "right" && isOverRightHalf ) || @@ -821,26 +849,14 @@ return $.widget( "ui.sortable", $.ui.mouse, { }, - refreshPositions: function( fast ) { - - // Determine whether items are being displayed horizontally - this.floating = this.items.length ? - this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) : - false; - - //This has to be redone because due to the item being moved out/into the offsetParent, - // the offsetParent's position will change - if ( this.offsetParent && this.helper ) { - this.offset.parent = this._getParentOffset(); - } - + _refreshItemPositions: function( fast ) { var i, item, t, p; for ( i = this.items.length - 1; i >= 0; i-- ) { item = this.items[ i ]; //We ignore calculating positions of all connected containers when we're not over them - if ( item.instance !== this.currentContainer && this.currentContainer && + if ( this.currentContainer && item.instance !== this.currentContainer && item.item[ 0 ] !== this.currentItem[ 0 ] ) { continue; } @@ -858,6 +874,20 @@ return $.widget( "ui.sortable", $.ui.mouse, { item.left = p.left; item.top = p.top; } + }, + + refreshPositions: function( fast ) { + + // Determine whether items are being displayed horizontally + this.floating = this.items.length ? + this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) : + false; + + if ( this.innermostContainer !== null ) { + this._refreshItemPositions( fast ); + } + + var i, p; if ( this.options.custom && this.options.custom.refreshContainers ) { this.options.custom.refreshContainers.call( this ); @@ -1003,6 +1033,8 @@ return $.widget( "ui.sortable", $.ui.mouse, { } + this.innermostContainer = innermostContainer; + // If no intersecting containers found, return if ( !innermostContainer ) { return; @@ -1071,6 +1103,15 @@ return $.widget( "ui.sortable", $.ui.mouse, { //Update the placeholder this.options.placeholder.update( this.currentContainer, this.placeholder ); + //Update scrollParent + this.scrollParent = this.placeholder.scrollParent(); + + //Update overflowOffset + if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && + this.scrollParent[ 0 ].tagName !== "HTML" ) { + this.overflowOffset = this.scrollParent.offset(); + } + this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) ); this.containers[ innermostIndex ].containerCache.over = 1; } @@ -1086,9 +1127,7 @@ return $.widget( "ui.sortable", $.ui.mouse, { //Add the helper to the DOM if that didn't happen already if ( !helper.parents( "body" ).length ) { - $( o.appendTo !== "parent" ? - o.appendTo : - this.currentItem[ 0 ].parentNode )[ 0 ].appendChild( helper[ 0 ] ); + this.appendTo[ 0 ].appendChild( helper[ 0 ] ); } if ( helper[ 0 ] === this.currentItem[ 0 ] ) { diff --git a/ui/widgets/tabs.js b/ui/widgets/tabs.js index 58a65ebe8..14f94ae83 100644 --- a/ui/widgets/tabs.js +++ b/ui/widgets/tabs.js @@ -96,7 +96,7 @@ $.widget( "ui.tabs", { // Take disabling tabs via class attribute from HTML // into account and update option properly. if ( $.isArray( options.disabled ) ) { - options.disabled = $.unique( options.disabled.concat( + options.disabled = $.uniqueSort( options.disabled.concat( $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { return that.tabs.index( li ); } ) |