From c6e2b52d70b8caf920f382402aba9f04de7e32b2 Mon Sep 17 00:00:00 2001 From: Scott González Date: Thu, 9 Mar 2017 12:17:06 -0500 Subject: Slider: Use `cursor: pointer` on handles Fixes #9371 Closes gh-1800 --- themes/base/slider.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; } -- cgit v1.2.3 From c426b9a203271ab5e5e5f165a1d686c8281164bf Mon Sep 17 00:00:00 2001 From: Konstantin Dinev Date: Tue, 28 Feb 2017 18:21:46 +0200 Subject: Resizable: Keep user-provided handles on destroy Closes gh-1798 Ref gh-1795 --- tests/unit/resizable/options.js | 10 +++++++++- ui/widgets/resizable.js | 5 ++--- 2 files changed, 11 insertions(+), 4 deletions(-) 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 = $( "
" ).resizable(), target2 = $( "
" + "
" + @@ -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/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 -- cgit v1.2.3 From ef2e9bab92ae898311baa295590cd487d9071319 Mon Sep 17 00:00:00 2001 From: Scott González Date: Wed, 16 Nov 2016 14:42:34 -0500 Subject: Widget: Improve `remove` event bindings for `classes` options Fixes #15078 Fixes #15082 Fixes #15095 Fixes #15136 Fixes #15152 Closes gh-1769 --- ui/widget.js | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/ui/widget.js b/ui/widget.js index 726f70735..f87675712 100644 --- a/ui/widget.js +++ b/ui/widget.js @@ -493,11 +493,29 @@ $.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 ) { + bindRemoveEvent(); current = $( $.unique( current.get().concat( options.element.get() ) ) ); } else { current = $( current.not( options.element ).get() ); @@ -510,10 +528,6 @@ $.Widget.prototype = { } } - this._on( options.element, { - "remove": "_untrackClassesElement" - } ); - if ( options.keys ) { processClassString( options.keys.match( /\S+/g ) || [], true ); } @@ -531,6 +545,8 @@ $.Widget.prototype = { that.classesElementLookup[ key ] = $( value.not( event.target ).get() ); } } ); + + this._off( $( event.target ) ); }, _removeClass: function( element, keys, extra ) { @@ -611,7 +627,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() ); -- cgit v1.2.3 From b3c0a7f71d0b351755b97858ad47de4e9a373606 Mon Sep 17 00:00:00 2001 From: Scott González Date: Fri, 21 Apr 2017 14:49:52 -0400 Subject: Widget: Handle `Object.create(null)` for options objects Fixes #15179 Closes gh-1809 --- tests/unit/widget/extend.js | 7 ++++++- ui/widget.js | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) 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/ui/widget.js b/ui/widget.js index f87675712..011396811 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 ) { @@ -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 ) ) { -- cgit v1.2.3 From 0d25a36eecb9e5598596208e4852b3c3fdbf5510 Mon Sep 17 00:00:00 2001 From: Scott González Date: Tue, 18 Apr 2017 17:37:15 -0400 Subject: Menu: Close menus immediately on selection or click outside Fixes #15034 Closes gh-1807 --- tests/unit/menu/events.js | 4 +++- ui/widgets/menu.js | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/unit/menu/events.js b/tests/unit/menu/events.js index a8ccb0282..90507bddc 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(); } } ); diff --git a/ui/widgets/menu.js b/ui/widgets/menu.js index 49da26865..19d9b90df 100644 --- a/ui/widgets/menu.js +++ b/ui/widgets/menu.js @@ -162,7 +162,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 @@ -502,7 +502,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 -- cgit v1.2.3 From adcf9b6f6ef9c6dfa88932b40307f581e65bc667 Mon Sep 17 00:00:00 2001 From: Scott González Date: Tue, 2 May 2017 12:42:49 -0400 Subject: Labels: Handle empty sets Fixes #15184 --- tests/unit/core/core.js | 4 +++- ui/labels.js | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) 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/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 ); -- cgit v1.2.3 From c866e455373028a62a0956455a229fef63e91fac Mon Sep 17 00:00:00 2001 From: "A. Wells" Date: Thu, 16 Feb 2017 13:48:45 -0500 Subject: Sortable: Fix various scrolling issues * Created _scroll extension point and migrated scroll code from _mouseDrag * Cleaned up logic for scrolled * Fixed appendTo functionality to match documentation * Remove unnecessary function calls * Move set-up position functions to appropriate place * Base scrollParent on placeholder and not helper * Update scrollParent when switching containers Fixes #3173 Fixes #15165 Fixes #15166 Fixes #15167 Fixes #15168 Fixes #15169 Fixes #15170 Closes gh-1793 --- ui/widgets/sortable.js | 297 ++++++++++++++++++++++++++++--------------------- 1 file changed, 168 insertions(+), 129 deletions(-) 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 ] ) { -- cgit v1.2.3 From abc9e7ce2f3b60a18bf1f461c7cbfccb3fa02b53 Mon Sep 17 00:00:00 2001 From: Alexander Schmitz Date: Wed, 19 Apr 2017 11:32:13 -0400 Subject: Button: Fix backcompat when called on collection of mixed elements Fixes #15109 Closes gh-1808 --- tests/unit/button/deprecated.html | 8 ++++ tests/unit/button/deprecated.js | 18 ++++++++ ui/widgets/button.js | 87 ++++++++++++++++++++++++++++++++------- 3 files changed, 99 insertions(+), 14 deletions(-) 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 @@ Anchor Button +
+ Anchor + + + + +
+
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/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 ); -- cgit v1.2.3 From a3e953b495905d0c67790e65032841451b470ce1 Mon Sep 17 00:00:00 2001 From: Scott González Date: Mon, 17 Apr 2017 12:26:22 -0400 Subject: Menu: Don't focus dividers when wrapping via keyboard navigation Fixes #15157 Closes gh-1804 --- tests/unit/menu/events.js | 22 ++++++++++++++++++++++ tests/unit/menu/menu.html | 10 ++++++++++ ui/widgets/menu.js | 24 +++++++++++++----------- 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/tests/unit/menu/events.js b/tests/unit/menu/events.js index 90507bddc..fd57373c1 100644 --- a/tests/unit/menu/events.js +++ b/tests/unit/menu/events.js @@ -757,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 @@
  • Addyston
  • Adelphi
  • + + diff --git a/ui/widgets/menu.js b/ui/widgets/menu.js index 19d9b90df..b2d976a2b 100644 --- a/ui/widgets/menu.js +++ b/ui/widgets/menu.js @@ -136,7 +136,7 @@ return $.widget( "ui.menu", { // 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 ); @@ -538,11 +538,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 +566,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 +612,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 +636,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() ); } }, -- cgit v1.2.3 From 7d992ae29d27cdab8787691a14e689e60c74c05c Mon Sep 17 00:00:00 2001 From: Scott González Date: Tue, 18 Apr 2017 13:57:23 -0400 Subject: Menu: Handle mouse movement mixed with keyboard navigation Fixes #9357 Closes gh-1805 --- ui/widgets/menu.js | 56 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/ui/widgets/menu.js b/ui/widgets/menu.js index b2d976a2b..5df9d3eef 100644 --- a/ui/widgets/menu.js +++ b/ui/widgets/menu.js @@ -78,6 +78,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,29 +109,8 @@ 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 ) { @@ -171,6 +152,35 @@ 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; + } + + 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" ), -- cgit v1.2.3 From 50efd6e1b063822c4a0ecb38f324ed3354f387c4 Mon Sep 17 00:00:00 2001 From: Scott González Date: Tue, 18 Apr 2017 16:51:23 -0400 Subject: Menu: Ignore mouse events triggered due to page scrolling Fixes #9356 Closes gh-1806 --- tests/unit/selectmenu/core.js | 4 ++-- tests/unit/selectmenu/events.js | 4 ++-- ui/widgets/menu.js | 12 ++++++++++++ 3 files changed, 16 insertions(+), 4 deletions(-) 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/ui/widgets/menu.js b/ui/widgets/menu.js index 5df9d3eef..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( { @@ -161,6 +162,17 @@ return $.widget( "ui.menu", { 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 ); -- cgit v1.2.3 From 0b7246b6eeadfa9e2696e22f3230f6452f8129dc Mon Sep 17 00:00:00 2001 From: Eirik Sletteberg Date: Fri, 2 Dec 2016 14:41:30 +0100 Subject: Core: Fix JQMIGRATE warning about `jQuery.expr[":"]` This commit polyfills `jQuery.expr.pseudos` for old versions of jQuery. Fixes #15185 Closes gh-1773 --- ui/data.js | 2 +- ui/focusable.js | 2 +- ui/jquery-1-7.js | 14 +++++++++++++- ui/tabbable.js | 2 +- ui/widget.js | 4 ++-- ui/widgets/controlgroup.js | 2 +- ui/widgets/tabs.js | 2 +- 7 files changed, 20 insertions(+), 8 deletions(-) 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/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/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 011396811..c101e59d4 100644 --- a/ui/widget.js +++ b/ui/widget.js @@ -65,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 ); }; @@ -517,7 +517,7 @@ $.Widget.prototype = { current = that.classesElementLookup[ classes[ i ] ] || $(); if ( options.add ) { bindRemoveEvent(); - current = $( $.unique( current.get().concat( options.element.get() ) ) ); + current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) ); } else { current = $( current.not( options.element ).get() ); } 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/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 ); } ) -- cgit v1.2.3 From efb1fee02b53c8fc17c3ffe68162f51b583e75f0 Mon Sep 17 00:00:00 2001 From: Scott González Date: Wed, 3 May 2017 13:12:34 -0400 Subject: Position: Increase scrollbar test div to handle larger scrollbars Fixes #15106 Closes gh-1811 --- ui/position.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 = $( "
    " + + "
    " ), innerDiv = div.children()[ 0 ]; $( "body" ).append( div ); -- cgit v1.2.3 From 39bbe70b54269903de5b4949cf91f1a625f24c3e Mon Sep 17 00:00:00 2001 From: Scott González Date: Wed, 10 May 2017 09:02:53 -0400 Subject: Tests: Load the `jquery-1-7` module for all 1.x versions --- tests/lib/bootstrap.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/lib/bootstrap.js b/tests/lib/bootstrap.js index 1a0149160..8d63c8135 100644 --- a/tests/lib/bootstrap.js +++ b/tests/lib/bootstrap.js @@ -172,8 +172,8 @@ function migrateUrl() { } } - // Load the jQuery 1.7 fixes, if necessary - if ( parseFloat( parseUrl().jquery ) === 1.7 ) { + // Load the jQuery 1.x fixes, if necessary + if ( parseFloat( parseUrl().jquery ) < 2 ) { modules.push( "ui/jquery-1-7" ); } -- cgit v1.2.3 From ceccf507be95d48ac50b0fd2e0f0389831941664 Mon Sep 17 00:00:00 2001 From: Robert Brignull Date: Sun, 7 May 2017 21:30:16 +0100 Subject: Demos: Fix a typo with an extra semicolon Closes gh-1812 --- demos/effect/easing.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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"; -- cgit v1.2.3 From ae31f2b3b478975f70526bdf3299464b9afa8bb1 Mon Sep 17 00:00:00 2001 From: Scott González Date: Mon, 15 May 2017 18:24:19 -0400 Subject: Tests: Load `jquery-1-7` module for jQuery 2.x as well --- tests/lib/bootstrap.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/lib/bootstrap.js b/tests/lib/bootstrap.js index 8d63c8135..7f1e12dd0 100644 --- a/tests/lib/bootstrap.js +++ b/tests/lib/bootstrap.js @@ -172,8 +172,8 @@ function migrateUrl() { } } - // Load the jQuery 1.x fixes, if necessary - if ( parseFloat( parseUrl().jquery ) < 2 ) { + // Load the jQuery fixes, if necessary + if ( parseFloat( parseUrl().jquery ) < 3 ) { modules.push( "ui/jquery-1-7" ); } -- cgit v1.2.3 From 0940cb9bd2b8967c8eac15f3097933f5aee7e551 Mon Sep 17 00:00:00 2001 From: Scott González Date: Mon, 8 May 2017 10:47:27 -0400 Subject: All: Remove uses of `jQuery.camelCase()` Ref #15160 Ref gh-1813 --- tests/lib/qunit-assert-domequal.js | 8 +++++++- ui/effect.js | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) 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/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 ]; } } -- cgit v1.2.3 From 809f29efa79c3c9aba95e6d7ffef41f567cda3a5 Mon Sep 17 00:00:00 2001 From: Scott González Date: Mon, 8 May 2017 11:52:58 -0400 Subject: All: Remove uses of `jQuery.proxy()` Ref #15160 Closes gh-1813 --- demos/autocomplete/combobox.html | 2 +- ui/widgets/autocomplete.js | 4 ++-- 2 files changed, 3 insertions(+), 3 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/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 ) { -- cgit v1.2.3 From 5708046ea1ba4d6d86f431ec9fd32d28ae7542f6 Mon Sep 17 00:00:00 2001 From: Scott González Date: Thu, 11 May 2017 13:58:08 -0400 Subject: Dialog: Fix shared event handler for modal dialogs The old logic worked when all widgets of the same type used the same event namespace. However, now that each instance has its own namespace, we cannot use `_on()` for shared event handlers. Fixes #15182 Closes gh-1817 --- ui/widgets/dialog.js | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) 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 = $( "
    " ) @@ -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 ); -- cgit v1.2.3 From 6fdd0e34a74789d2da214739ea0f5a8feff71d7e Mon Sep 17 00:00:00 2001 From: Horus68 Date: Wed, 31 May 2017 15:53:30 +0100 Subject: Datepicker: Fix first day of week for pt-PT locale Fixes #15195 Closes gh-1820 --- ui/i18n/datepicker-pt.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/i18n/datepicker-pt.js b/ui/i18n/datepicker-pt.js index b1afd7b3d..5ddd0c636 100644 --- a/ui/i18n/datepicker-pt.js +++ b/ui/i18n/datepicker-pt.js @@ -33,7 +33,7 @@ datepicker.regional.pt = { dayNamesMin: [ "Dom","Seg","Ter","Qua","Qui","Sex","Sáb" ], weekHeader: "Sem", dateFormat: "dd/mm/yy", - firstDay: 0, + firstDay: 1, isRTL: false, showMonthAfterYear: false, yearSuffix: "" }; -- cgit v1.2.3 From 74f8a0ac952f6f45f773312292baef1c26d81300 Mon Sep 17 00:00:00 2001 From: Scott González Date: Wed, 31 May 2017 14:09:05 -0400 Subject: Tests: Load `jquery-1-7` before other modules --- tests/lib/bootstrap.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lib/bootstrap.js b/tests/lib/bootstrap.js index 7f1e12dd0..487b3b807 100644 --- a/tests/lib/bootstrap.js +++ b/tests/lib/bootstrap.js @@ -174,7 +174,7 @@ function migrateUrl() { // Load the jQuery fixes, if necessary if ( parseFloat( parseUrl().jquery ) < 3 ) { - modules.push( "ui/jquery-1-7" ); + modules.unshift( "ui/jquery-1-7" ); } requireTests( modules, noBackCompat ); -- cgit v1.2.3