aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Nagel <info@felixnagel.com>2017-08-26 13:08:14 +0200
committerFelix Nagel <info@felixnagel.com>2017-08-26 13:08:14 +0200
commit1b885ff76899fb70cce28371968d314ea74b7d7a (patch)
tree1a3a19be9d874f9daffd1238950c073ec086ffc2
parent2b611bad90fa6f19e3bf02912c6cd5c08903c993 (diff)
parent74f8a0ac952f6f45f773312292baef1c26d81300 (diff)
downloadjquery-ui-datepicker.tar.gz
jquery-ui-datepicker.zip
Merge branch 'master' into datepickerdatepicker
# Conflicts: # ui/i18n/datepicker-pt.js
-rw-r--r--demos/autocomplete/combobox.html2
-rw-r--r--demos/effect/easing.html2
-rw-r--r--tests/lib/bootstrap.js6
-rw-r--r--tests/lib/qunit-assert-domequal.js8
-rw-r--r--tests/unit/button/deprecated.html8
-rw-r--r--tests/unit/button/deprecated.js18
-rw-r--r--tests/unit/core/core.js4
-rw-r--r--tests/unit/menu/events.js26
-rw-r--r--tests/unit/menu/menu.html10
-rw-r--r--tests/unit/resizable/options.js10
-rw-r--r--tests/unit/selectmenu/core.js4
-rw-r--r--tests/unit/selectmenu/events.js4
-rw-r--r--tests/unit/widget/extend.js7
-rw-r--r--themes/base/slider.css2
-rw-r--r--ui/data.js2
-rw-r--r--ui/effect.js8
-rw-r--r--ui/focusable.js2
-rw-r--r--ui/jquery-1-7.js14
-rw-r--r--ui/labels.js4
-rw-r--r--ui/position.js6
-rw-r--r--ui/tabbable.js2
-rw-r--r--ui/widget.js33
-rw-r--r--ui/widgets/autocomplete.js4
-rw-r--r--ui/widgets/button.js87
-rw-r--r--ui/widgets/controlgroup.js2
-rw-r--r--ui/widgets/dialog.js29
-rw-r--r--ui/widgets/menu.js96
-rw-r--r--ui/widgets/resizable.js5
-rw-r--r--ui/widgets/sortable.js297
-rw-r--r--ui/widgets/tabs.js2
30 files changed, 472 insertions, 232 deletions
diff --git a/demos/autocomplete/combobox.html b/demos/autocomplete/combobox.html
index 403c48550..32c69b97a 100644
--- a/demos/autocomplete/combobox.html
+++ b/demos/autocomplete/combobox.html
@@ -48,7 +48,7 @@
.autocomplete({
delay: 0,
minLength: 0,
- source: $.proxy( this, "_source" )
+ source: this._source.bind( this )
})
.tooltip({
classes: {
diff --git a/demos/effect/easing.html b/demos/effect/easing.html
index b22c69580..4bee1c41f 100644
--- a/demos/effect/easing.html
+++ b/demos/effect/easing.html
@@ -34,7 +34,7 @@
canvas.width = width;
canvas.height = height;
var drawHeight = height * 0.8,
- cradius = 10;
+ cradius = 10,
ctx = canvas.getContext( "2d" );
ctx.fillStyle = "black";
diff --git a/tests/lib/bootstrap.js b/tests/lib/bootstrap.js
index e3d344cec..ffb273837 100644
--- a/tests/lib/bootstrap.js
+++ b/tests/lib/bootstrap.js
@@ -181,9 +181,9 @@ function migrateUrl() {
}
}
- // Load the jQuery 1.7 fixes, if necessary
- if ( parseFloat( parseUrl().jquery ) === 1.7 ) {
- modules.push( "ui/jquery-1-7" );
+ // Load the jQuery fixes, if necessary
+ if ( parseFloat( parseUrl().jquery ) < 3 ) {
+ modules.unshift( "ui/jquery-1-7" );
}
requireTests( modules, noBackCompat );
diff --git a/tests/lib/qunit-assert-domequal.js b/tests/lib/qunit-assert-domequal.js
index b22bd90b9..35695c4f1 100644
--- a/tests/lib/qunit-assert-domequal.js
+++ b/tests/lib/qunit-assert-domequal.js
@@ -59,6 +59,12 @@ domEqual.attributes = [
"title"
];
+function camelCase( string ) {
+ return string.replace( /-([\da-z])/gi, function( all, letter ) {
+ return letter.toUpperCase();
+ } );
+}
+
function getElementStyles( elem ) {
var styles = {};
var style = elem.ownerDocument.defaultView ?
@@ -71,7 +77,7 @@ function getElementStyles( elem ) {
while ( len-- ) {
key = style[ len ];
if ( typeof style[ key ] === "string" ) {
- styles[ $.camelCase( key ) ] = style[ key ];
+ styles[ camelCase( key ) ] = style[ key ];
}
}
diff --git a/tests/unit/button/deprecated.html b/tests/unit/button/deprecated.html
index 73f62921c..8b5270baa 100644
--- a/tests/unit/button/deprecated.html
+++ b/tests/unit/button/deprecated.html
@@ -56,6 +56,14 @@
<button id="button1">Button</button>
<a href="#" id="anchor-button">Anchor Button</a>
+<div class="mixed">
+ <a href="#" id="mixed-anchor">Anchor</a>
+ <button id="mixed-button" disabled>Button</button>
+ <input type="button" value="Button" id="mixed-input">
+ <input type="checkbox" id="mixed-check" name="check"><label for="mixed-check">Check</label>
+ <input type="radio" id="mixed-radio" name="radio"><label for="mixed-radio">Radio</label>
+</div>
+
</div>
</body>
</html>
diff --git a/tests/unit/button/deprecated.js b/tests/unit/button/deprecated.js
index 81a0281b7..86fca797e 100644
--- a/tests/unit/button/deprecated.js
+++ b/tests/unit/button/deprecated.js
@@ -194,4 +194,22 @@ QUnit.test( "icon / icons options properly proxied", function( assert ) {
"Icons secondary option sets iconPosition option to end on init" );
} );
+QUnit.test( "Calling button on a collection of mixed types works correctly", function( assert ) {
+ assert.expect( 5 );
+
+ var group = $( ".mixed" ).children();
+
+ group.button();
+
+ $.each( {
+ anchor: "button",
+ button: "button",
+ check: "checkboxradio",
+ input: "button",
+ radio: "checkboxradio"
+ }, function( type, widget ) {
+ assert.ok( $( "#mixed-" + type )[ widget ]( "instance" ), type + " is a " + widget );
+ } );
+} );
+
} );
diff --git a/tests/unit/core/core.js b/tests/unit/core/core.js
index 770ea4138..b5b6b3b81 100644
--- a/tests/unit/core/core.js
+++ b/tests/unit/core/core.js
@@ -142,7 +142,7 @@ QUnit.test( "uniqueId / removeUniqueId", function( assert ) {
} );
QUnit.test( "Labels", function( assert ) {
- assert.expect( 2 );
+ assert.expect( 3 );
var expected = [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" ];
var dom = $( "#labels-fragment" );
@@ -165,6 +165,8 @@ QUnit.test( "Labels", function( assert ) {
// Detach the dom to test on a fragment
dom.detach();
testLabels( "document fragments" );
+
+ assert.equal( $().labels().length, 0, "No element" );
} );
( function() {
diff --git a/tests/unit/menu/events.js b/tests/unit/menu/events.js
index a8ccb0282..fd57373c1 100644
--- a/tests/unit/menu/events.js
+++ b/tests/unit/menu/events.js
@@ -670,7 +670,9 @@ QUnit.test( "handle keyboard navigation and mouse click on menu with dividers an
element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
- assert.equal( logOutput(), "keydown,3,4,7", "Keydown focus skips divider and group label" );
+ element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+ element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+ assert.equal( logOutput(), "keydown,1,2,3,4,7", "Keydown focus skips divider and group label" );
ready();
}
} );
@@ -755,4 +757,26 @@ QUnit.test( "#10571: When typing in a menu, only menu-items should be focused",
} );
} );
+QUnit.test( "#15157: Must not focus menu dividers with the keyboard", function( assert ) {
+ var ready = assert.async();
+ assert.expect( 6 );
+
+ var element = $( "#menu-with-dividers" ).menu( {
+ focus: function( event, ui ) {
+ assert.hasClasses( ui.item, "ui-menu-item", "Should have menu item class" );
+ log( ui.item.text() );
+ }
+ } );
+
+ element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+ element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+ element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+ element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+ element.simulate( "keydown", { keyCode: $.ui.keyCode.UP } );
+ setTimeout( function() {
+ assert.equal( logOutput(), "beginning,middle,end,beginning,end", "Should wrap around items" );
+ ready();
+ } );
+} );
+
} );
diff --git a/tests/unit/menu/menu.html b/tests/unit/menu/menu.html
index 2d871a4b3..8d70b19df 100644
--- a/tests/unit/menu/menu.html
+++ b/tests/unit/menu/menu.html
@@ -323,6 +323,16 @@
<li class="foo"><div>Addyston</div></li>
<li class="foo"><div>Adelphi</div></li>
</ul>
+
+<ul id="menu-with-dividers">
+ <li>-</li>
+ <li>beginning</li>
+ <li>-</li>
+ <li>middle</li>
+ <li>-</li>
+ <li>end</li>
+ <li>-</li>
+</ul>
</div>
</body>
</html>
diff --git a/tests/unit/resizable/options.js b/tests/unit/resizable/options.js
index 4080bac0e..81206abf8 100644
--- a/tests/unit/resizable/options.js
+++ b/tests/unit/resizable/options.js
@@ -434,8 +434,10 @@ QUnit.test( "zIndex, applied to all handles", function( assert ) {
} );
QUnit.test( "setOption handles", function( assert ) {
- assert.expect( 15 );
+ assert.expect( 19 );
+ // https://bugs.jqueryui.com/ticket/3423
+ // https://bugs.jqueryui.com/ticket/15084
var target = $( "<div></div>" ).resizable(),
target2 = $( "<div>" +
"<div class='ui-resizable-handle ui-resizable-e'></div>" +
@@ -470,6 +472,12 @@ QUnit.test( "setOption handles", function( assert ) {
target2.resizable( "option", "handles", "e, s, w" );
checkHandles( target2, [ "e", "s", "w" ] );
+
+ target.resizable( "destroy" );
+ checkHandles( target, [ ] );
+
+ target2.resizable( "destroy" );
+ checkHandles( target2, [ "e", "w" ] );
} );
QUnit.test( "alsoResize + containment", function( assert ) {
diff --git a/tests/unit/selectmenu/core.js b/tests/unit/selectmenu/core.js
index cef6dc5bf..708452312 100644
--- a/tests/unit/selectmenu/core.js
+++ b/tests/unit/selectmenu/core.js
@@ -251,13 +251,13 @@ $.each( [
wrappers = menu.find( "li.ui-menu-item .ui-menu-item-wrapper" );
button.trigger( "click" );
- wrappers.first().simulate( "mouseover" ).trigger( "click" );
+ wrappers.first().simulate( "mouseover", { clientX: 2, clientY: 2 } ).trigger( "click" );
assert.equal( element[ 0 ].selectedIndex, 0, "First item is selected" );
button.simulate( "keydown", { keyCode: $.ui.keyCode.UP } );
assert.equal( element[ 0 ].selectedIndex, 0, "No looping beyond first item" );
button.trigger( "click" );
- wrappers.last().simulate( "mouseover" ).trigger( "click" );
+ wrappers.last().simulate( "mouseover", { clientX: 3, clientY: 3 } ).trigger( "click" );
assert.equal( element[ 0 ].selectedIndex, wrappers.length - 1, "Last item is selected" );
button.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
assert.equal( element[ 0 ].selectedIndex, wrappers.length - 1, "No looping behind last item" );
diff --git a/tests/unit/selectmenu/events.js b/tests/unit/selectmenu/events.js
index 4aed70ac8..ffc0429ee 100644
--- a/tests/unit/selectmenu/events.js
+++ b/tests/unit/selectmenu/events.js
@@ -89,9 +89,9 @@ QUnit.test( "focus", function( assert ) {
button.trigger( "click" );
links = menu.find( "li.ui-menu-item" );
optionIndex = 0;
- links.eq( optionIndex ).simulate( "mouseover" );
+ links.eq( optionIndex ).simulate( "mouseover", { clientX: 2, clientY: 2 } );
optionIndex += 1;
- links.eq( optionIndex ).simulate( "mouseover" );
+ links.eq( optionIndex ).simulate( "mouseover", { clientX: 3, clientY: 3 } );
// This tests for unwanted, additional focus event on close
that.element.selectmenu( "close" );
diff --git a/tests/unit/widget/extend.js b/tests/unit/widget/extend.js
index 36575200b..b27d925f0 100644
--- a/tests/unit/widget/extend.js
+++ b/tests/unit/widget/extend.js
@@ -5,7 +5,7 @@ define( [
], function( QUnit, $ ) {
QUnit.test( "$.widget.extend()", function( assert ) {
- assert.expect( 27 );
+ assert.expect( 28 );
var ret, empty, optionsWithLength, optionsWithDate, myKlass, customObject, optionsWithCustomObject, nullUndef,
target, recursive, obj, input, output,
@@ -108,6 +108,11 @@ QUnit.test( "$.widget.extend()", function( assert ) {
assert.deepEqual( input, output, "don't clone arrays" );
input.key[ 0 ] = 10;
assert.deepEqual( input, output, "don't clone arrays" );
+
+ input = Object.create( null );
+ input.foo = "f";
+ output = $.widget.extend( {}, input );
+ assert.deepEqual( input, output, "Object with no prototype" );
} );
} );
diff --git a/themes/base/slider.css b/themes/base/slider.css
index cffdc9691..724d513c2 100644
--- a/themes/base/slider.css
+++ b/themes/base/slider.css
@@ -17,7 +17,7 @@
z-index: 2;
width: 1.2em;
height: 1.2em;
- cursor: default;
+ cursor: pointer;
-ms-touch-action: none;
touch-action: none;
}
diff --git a/ui/data.js b/ui/data.js
index d0417b8f9..c02e7ffde 100644
--- a/ui/data.js
+++ b/ui/data.js
@@ -23,7 +23,7 @@
factory( jQuery );
}
} ( function( $ ) {
-return $.extend( $.expr[ ":" ], {
+return $.extend( $.expr.pseudos, {
data: $.expr.createPseudo ?
$.expr.createPseudo( function( dataName ) {
return function( elem ) {
diff --git a/ui/effect.js b/ui/effect.js
index 31e6024a1..2d17affd1 100644
--- a/ui/effect.js
+++ b/ui/effect.js
@@ -746,6 +746,12 @@ $.each(
}
);
+function camelCase( string ) {
+ return string.replace( /-([\da-z])/gi, function( all, letter ) {
+ return letter.toUpperCase();
+ } );
+}
+
function getElementStyles( elem ) {
var key, len,
style = elem.ownerDocument.defaultView ?
@@ -758,7 +764,7 @@ function getElementStyles( elem ) {
while ( len-- ) {
key = style[ len ];
if ( typeof style[ key ] === "string" ) {
- styles[ $.camelCase( key ) ] = style[ key ];
+ styles[ camelCase( key ) ] = style[ key ];
}
}
diff --git a/ui/focusable.js b/ui/focusable.js
index cf4f728b8..b1a7b61e2 100644
--- a/ui/focusable.js
+++ b/ui/focusable.js
@@ -73,7 +73,7 @@ function visible( element ) {
return visibility !== "hidden";
}
-$.extend( $.expr[ ":" ], {
+$.extend( $.expr.pseudos, {
focusable: function( element ) {
return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
}
diff --git a/ui/jquery-1-7.js b/ui/jquery-1-7.js
index bd40e332f..5e7907a15 100644
--- a/ui/jquery-1-7.js
+++ b/ui/jquery-1-7.js
@@ -1,5 +1,5 @@
/*!
- * jQuery UI Support for jQuery core 1.7.x @VERSION
+ * jQuery UI Support for jQuery core 1.7.x and newer @VERSION
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
@@ -86,4 +86,16 @@ if ( $.fn.jquery.substring( 0, 3 ) === "1.7" ) {
};
}
+// Support: jQuery 1.9.x or older
+// $.expr[ ":" ] is deprecated.
+if ( !$.expr.pseudos ) {
+ $.expr.pseudos = $.expr[ ":" ];
+}
+
+// Support: jQuery 1.11.x or older
+// $.unique has been renamed to $.uniqueSort
+if ( !$.uniqueSort ) {
+ $.uniqueSort = $.unique;
+}
+
} ) );
diff --git a/ui/labels.js b/ui/labels.js
index 2a78d886b..1bf56ac41 100644
--- a/ui/labels.js
+++ b/ui/labels.js
@@ -27,6 +27,10 @@
return $.fn.labels = function() {
var ancestor, selector, id, labels, ancestors;
+ if ( !this.length ) {
+ return this.pushStack( [] );
+ }
+
// Check control.labels first
if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
return this.pushStack( this[ 0 ].labels );
diff --git a/ui/position.js b/ui/position.js
index 2f7fa5f01..3994e9acc 100644
--- a/ui/position.js
+++ b/ui/position.js
@@ -84,9 +84,9 @@ $.position = {
return cachedScrollbarWidth;
}
var w1, w2,
- div = $( "<div " +
- "style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'>" +
- "<div style='height:100px;width:auto;'></div></div>" ),
+ div = $( "<div style=" +
+ "'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" +
+ "<div style='height:300px;width:auto;'></div></div>" ),
innerDiv = div.children()[ 0 ];
$( "body" ).append( div );
diff --git a/ui/tabbable.js b/ui/tabbable.js
index 3baa641ce..bb79466e8 100644
--- a/ui/tabbable.js
+++ b/ui/tabbable.js
@@ -24,7 +24,7 @@
}
} ( function( $ ) {
-return $.extend( $.expr[ ":" ], {
+return $.extend( $.expr.pseudos, {
tabbable: function( element ) {
var tabIndex = $.attr( element, "tabindex" ),
hasTabindex = tabIndex != null;
diff --git a/ui/widget.js b/ui/widget.js
index 726f70735..c101e59d4 100644
--- a/ui/widget.js
+++ b/ui/widget.js
@@ -26,6 +26,7 @@
}( function( $ ) {
var widgetUuid = 0;
+var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
var widgetSlice = Array.prototype.slice;
$.cleanData = ( function( orig ) {
@@ -64,7 +65,7 @@ $.widget = function( name, base, prototype ) {
}
// Create selector for plugin
- $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
+ $.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
return !!$.data( elem, fullName );
};
@@ -183,7 +184,7 @@ $.widget.extend = function( target ) {
for ( ; inputIndex < inputLength; inputIndex++ ) {
for ( key in input[ inputIndex ] ) {
value = input[ inputIndex ][ key ];
- if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
+ if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) {
// Clone objects
if ( $.isPlainObject( value ) ) {
@@ -493,12 +494,30 @@ $.Widget.prototype = {
classes: this.options.classes || {}
}, options );
+ function bindRemoveEvent() {
+ options.element.each( function( _, element ) {
+ var isTracked = $.map( that.classesElementLookup, function( elements ) {
+ return elements;
+ } )
+ .some( function( elements ) {
+ return elements.is( element );
+ } );
+
+ if ( !isTracked ) {
+ that._on( $( element ), {
+ remove: "_untrackClassesElement"
+ } );
+ }
+ } );
+ }
+
function processClassString( classes, checkOption ) {
var current, i;
for ( i = 0; i < classes.length; i++ ) {
current = that.classesElementLookup[ classes[ i ] ] || $();
if ( options.add ) {
- current = $( $.unique( current.get().concat( options.element.get() ) ) );
+ bindRemoveEvent();
+ current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) );
} else {
current = $( current.not( options.element ).get() );
}
@@ -510,10 +529,6 @@ $.Widget.prototype = {
}
}
- this._on( options.element, {
- "remove": "_untrackClassesElement"
- } );
-
if ( options.keys ) {
processClassString( options.keys.match( /\S+/g ) || [], true );
}
@@ -531,6 +546,8 @@ $.Widget.prototype = {
that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
}
} );
+
+ this._off( $( event.target ) );
},
_removeClass: function( element, keys, extra ) {
@@ -611,7 +628,7 @@ $.Widget.prototype = {
_off: function( element, eventName ) {
eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
this.eventNamespace;
- element.off( eventName ).off( eventName );
+ element.off( eventName );
// Clear the stack to avoid memory leaks (#10056)
this.bindings = $( this.bindings.not( element ).get() );
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 );
} )