From 27a88c8094094b1cd52abe707b5b276d6199c3e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Mon, 3 Nov 2014 17:59:56 -0500 Subject: [PATCH 01/79] Build: Update links to AUTHORS.txt and LICENSE.txt in package.json --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index acece984825..25fd51b3aff 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "homepage": "http://jqueryui.com", "author": { "name": "jQuery Foundation and other contributors", - "url": "https://github.com/jquery/jquery-ui/blob/master/AUTHORS.txt" + "url": "https://github.com/jquery/jquery-ui/blob/1-11-stable/AUTHORS.txt" }, "maintainers": [ { @@ -53,7 +53,7 @@ "licenses": [ { "type": "MIT", - "url": "https://github.com/jquery/jquery-ui/blob/master/LICENSE.txt" + "url": "https://github.com/jquery/jquery-ui/blob/1-11-stable/LICENSE.txt" } ], "scripts": { From 47ceff8dbd1f64c081f8fd136d86a5db23fef0ff Mon Sep 17 00:00:00 2001 From: Chen Eshchar Date: Sun, 19 Oct 2014 09:37:21 +0300 Subject: [PATCH 02/79] DatePicker: datepicker_instActive released on instance destroy Fixes #10668 Closes gh-1362 (cherry picked from commit e5e3ca4240fbae9684f689ec6e00882ec0211922) --- ui/datepicker.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/datepicker.js b/ui/datepicker.js index d3fe3dd1fe9..34ffc578edb 100644 --- a/ui/datepicker.js +++ b/ui/datepicker.js @@ -389,6 +389,10 @@ $.extend(Datepicker.prototype, { } else if (nodeName === "div" || nodeName === "span") { $target.removeClass(this.markerClassName).empty(); } + + if ( datepicker_instActive === inst ) { + datepicker_instActive = null; + } }, /* Enable the date picker to a jQuery selection. From c303f7e073e38cfa56591768261607314f16825e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20P=C3=A9rel?= Date: Mon, 20 Oct 2014 14:09:13 +0200 Subject: [PATCH 03/79] Autocomplete: Remove duplicate array key in demo Ref gh-1363 (cherry picked from commit 0fccf94113eb549ba591729f8854d1e289b0479b) --- demos/autocomplete/search.php | 1 - 1 file changed, 1 deletion(-) diff --git a/demos/autocomplete/search.php b/demos/autocomplete/search.php index 835772deea8..04bda422423 100644 --- a/demos/autocomplete/search.php +++ b/demos/autocomplete/search.php @@ -368,7 +368,6 @@ "Glossy Ibis"=>"Plegadis falcinellus", "Spanish Imperial Eagle"=>"Aquila adalberti", "Lesser Kestrel"=>"Falco naumanni", -"Houbara Bustard"=>"Chlamydotis undulata", "Crab-Plover"=>"Dromas ardeola", "Cream-coloured Courser"=>"Cursorius cursor", "Collared Pratincole"=>"Glareola pratincola", From 152c2d1b35c3829585c6955d192b899c8bf8035a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20P=C3=A9rel?= Date: Mon, 20 Oct 2014 14:09:27 +0200 Subject: [PATCH 04/79] Demos: Remove duplicate CSS properties Closes gh-1363 (cherry picked from commit 14c4eae32423682dd291fea633081502077f4df9) --- demos/sortable/empty-lists.html | 2 +- demos/tabs/vertical.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/demos/sortable/empty-lists.html b/demos/sortable/empty-lists.html index 6d8f6565b2d..1925446195a 100644 --- a/demos/sortable/empty-lists.html +++ b/demos/sortable/empty-lists.html @@ -11,7 +11,7 @@ - From c3dcf4eaccbdc35288371ea6295431bf812ee838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Wed, 22 Oct 2014 12:27:37 -0400 Subject: [PATCH 06/79] Selectmenu: Remove broken tabindex code (cherry picked from commit 1fb08790a6cae0ac861df0373a303d72ed0e8d71) --- ui/selectmenu.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ui/selectmenu.js b/ui/selectmenu.js index 26456b0dc1b..14c81efee87 100644 --- a/ui/selectmenu.js +++ b/ui/selectmenu.js @@ -67,8 +67,7 @@ return $.widget( "ui.selectmenu", { }, _drawButton: function() { - var that = this, - tabindex = this.element.attr( "tabindex" ); + var that = this; // Associate existing label with the new button this.label = $( "label[for='" + this.ids.element + "']" ).attr( "for", this.ids.button ); @@ -85,7 +84,7 @@ return $.widget( "ui.selectmenu", { // Create button this.button = $( "", { "class": "ui-selectmenu-button ui-widget ui-state-default ui-corner-all", - tabindex: tabindex || this.options.disabled ? -1 : 0, + tabindex: this.options.disabled ? -1 : 0, id: this.ids.button, role: "combobox", "aria-expanded": "false", From 9afe0f7b8a1fc0c282f0561899e4195f601c8538 Mon Sep 17 00:00:00 2001 From: Mohammed Alshehri Date: Sun, 11 May 2014 23:30:07 +0300 Subject: [PATCH 07/79] Datepicker: Fixed month names and firstDay value in Arabic locale Fixes #10035 Closes gh-1246 (cherry picked from commit 06231cf7622fe112703c38535df71aa7f100ef7d) --- ui/i18n/datepicker-ar.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ui/i18n/datepicker-ar.js b/ui/i18n/datepicker-ar.js index c93fed48dc6..c9ee84a5435 100644 --- a/ui/i18n/datepicker-ar.js +++ b/ui/i18n/datepicker-ar.js @@ -1,6 +1,7 @@ /* Arabic Translation for jQuery UI date picker plugin. */ -/* Khaled Alhourani -- me@khaledalhourani.com */ -/* NOTE: monthNames are the original months names and they are the Arabic names, not the new months name فبراير - يناير and there isn't any Arabic roots for these months */ +/* Used in most of Arab countries, primarily in Bahrain, Kuwait, Oman, Qatar, Saudi Arabia and the United Arab Emirates, Egypt, Sudan and Yemen. */ +/* Written by Mohammed Alshehri -- m@dralshehri.com */ + (function( factory ) { if ( typeof define === "function" && define.amd ) { @@ -18,15 +19,15 @@ datepicker.regional['ar'] = { prevText: '<السابق', nextText: 'التالي>', currentText: 'اليوم', - monthNames: ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'مايو', 'حزيران', - 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'], + monthNames: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', + 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'], monthNamesShort: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'], dayNames: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], - dayNamesShort: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], + dayNamesShort: ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'], dayNamesMin: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], weekHeader: 'أسبوع', dateFormat: 'dd/mm/yy', - firstDay: 6, + firstDay: 0, isRTL: true, showMonthAfterYear: false, yearSuffix: ''}; From 468645874e9d53d8df11114f5fc0d46380003673 Mon Sep 17 00:00:00 2001 From: TJ VanToll Date: Wed, 22 Oct 2014 22:21:58 -0400 Subject: [PATCH 08/79] Tests: Adding missing dependency (cherry picked from commit ae577ae108e6c01be1ef6d318e4065aab3cb0b87) --- tests/visual/compound/datepicker_dialog.html | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/visual/compound/datepicker_dialog.html b/tests/visual/compound/datepicker_dialog.html index e6a25a2e8df..52c91a0835b 100644 --- a/tests/visual/compound/datepicker_dialog.html +++ b/tests/visual/compound/datepicker_dialog.html @@ -12,6 +12,7 @@ + + From fcb26aaded146e63ffdb9fcca46e308f9b877edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=CC=88rn=20Zaefferer?= Date: Mon, 12 Jan 2015 17:12:05 +0100 Subject: [PATCH 23/79] Tests: Fix jQuery version references to match files in external/ (cherry picked from commit a3b43eeb58a290f9447ac4127d145ef121ca255c) --- tests/unit/testsuite.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/testsuite.js b/tests/unit/testsuite.js index 18353c702df..1c0f1785916 100644 --- a/tests/unit/testsuite.js +++ b/tests/unit/testsuite.js @@ -64,7 +64,7 @@ QUnit.config.urlConfig.push({ id: "jquery", label: "jQuery version", value: [ - "1.6", "1.6.1", "1.6.2", "1.6.3", "1.6.4", "1.7", "1.7.1", "1.7.2", + "1.6.0", "1.6.1", "1.6.2", "1.6.3", "1.6.4", "1.7.0", "1.7.1", "1.7.2", "1.8.0", "1.8.1", "1.8.2", "1.8.3", "1.9.0", "1.9.1", "1.10.0", "1.10.1", "1.10.2", "2.0.0", "2.0.1", "2.0.2", "2.0.3", "git" ], From dfa3a9f8c983f5206d49000a170b42581fcc5478 Mon Sep 17 00:00:00 2001 From: Jyoti Deka Date: Fri, 9 Jan 2015 20:06:32 -0500 Subject: [PATCH 24/79] Slider: Fix max calculation, when step is float Fixes #10721 Closes gh-1398 (cherry picked from commit ae1d6d5f90236405023964bb3061eccd6c625e39) --- tests/unit/slider/slider_options.js | 14 +++++++++++++- ui/slider.js | 22 ++++++++++++++++++++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/tests/unit/slider/slider_options.js b/tests/unit/slider/slider_options.js index defb6f3b0fb..2badcc566f9 100644 --- a/tests/unit/slider/slider_options.js +++ b/tests/unit/slider/slider_options.js @@ -40,7 +40,7 @@ test( "disabled", function(){ }); test( "max", function() { - expect( 4 ); + expect( 5 ); element = $( "
" ); options = { @@ -72,6 +72,18 @@ test( "max", function() { ok( element.slider( "value" ) === options.max, "value method will max, step is changed" ); element.slider( "destroy" ); + options = { + max: 60, + min: 50, + orientation: "horizontal", + step: 0.1, + value: 60 + }; + + element.slider( options ); + ok( element.slider( "value" ) === options.max, "value method will max, step is changed and step is float" ); + element.slider( "destroy" ); + }); test( "min", function() { diff --git a/ui/slider.js b/ui/slider.js index c96180dd275..edc8b402729 100644 --- a/ui/slider.js +++ b/ui/slider.js @@ -547,8 +547,26 @@ return $.widget( "ui.slider", $.ui.mouse, { }, _calculateNewMax: function() { - var remainder = ( this.options.max - this._valueMin() ) % this.options.step; - this.max = this.options.max - remainder; + var max = this.options.max, + min = this._valueMin(), + step = this.options.step, + aboveMin = Math.floor( ( max - min ) / step ) * step; + max = aboveMin + min; + this.max = parseFloat( max.toFixed( this._precision() ) ); + }, + + _precision: function() { + var precision = this._precisionOf( this.options.step ); + if ( this.options.min !== null ) { + precision = Math.max( precision, this._precisionOf( this.options.min ) ); + } + return precision; + }, + + _precisionOf: function( num ) { + var str = num.toString(), + decimal = str.indexOf( "." ); + return decimal === -1 ? 0 : str.length - decimal - 1; }, _valueMin: function() { From da67914465e7e82ff620c9bbd51dfa9d0236f3df Mon Sep 17 00:00:00 2001 From: Luke Page Date: Sat, 10 Jan 2015 10:58:40 +0000 Subject: [PATCH 25/79] Docs: Clarify PHP Usage Clarify that PHP is not required for testing, add a link to the CONTRIBUTING page and tidy up. Closes gh-1418 (cherry picked from commit 8cc636dd448afb8df7147640a7fbfb67f7d53623) --- CONTRIBUTING.md | 67 ++++++++++++++++++++++++++++++------------------- README.md | 26 +++++-------------- 2 files changed, 47 insertions(+), 46 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5d694c99cfc..8c1ceb034ae 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,68 +16,83 @@ This is the best way to contribute to jQuery UI. Please read through the full gu Every week (unless otherwise noted) the jQuery UI team has a meeting to discuss the progress of current work and to bring forward possible new blockers for discussion. The meeting is held on [IRC](http://irc.jquery.org) in the #jquery-meeting channel at [Noon EST](http://www.timeanddate.com/worldclock/fixedtime.html?month=1&day=17&year=2011&hour=12&min=0&sec=0&p1=43) on Wednesdays. Meeting notes are posted on http://meetings.jquery.org/category/ui/ after each meeting. -## Tips For Bug Patching +## Tips for Getting Started -### Environment: localhost w/ PHP, Node.js & Grunt +### Environment: Minimum Required -jQuery UI uses Node.js & Grunt to automate the building and validation of source code. +If you are contributing changes you will need a fork of jquery-ui (see [Getting the Source](#environment-getting-the-source)). If you just want the source code you could clone jquery-ui directly: -Some tests depend on PHP running locally, so make sure you have the following installed: - -* A web server with PHP support (any will do, such as [XAMPP](http://www.apachefriends.org/en/xampp.html) or [MAMP](http://www.mamp.info/en/index.html)) -* [Node.js](http://nodejs.org/) (includes NPM, necessary for the next step) -* Grunt (install with: `npm install -g grunt`) +```bash +git clone git://github.com/jquery/jquery-ui.git +cd jquery-ui +``` -### Build a Local Copy of jQuery UI +The tests can run in any local web server. Ideally you should test your patch in appropriate web browsers and if possible run `grunt` to lint the code and run automated tests (this will happen automatically when you create a pull request). See the [Recommended Setup](#environment-recommended-setup) for setting up Node.js so that the grunt command works. -Create a fork of the jQuery UI repo on GitHub at http://github.com/jquery/jquery-ui. +### Environment: Getting the Source -Change directory to your web root directory, whatever that might be: +* Create a fork of the jQuery UI repo on GitHub at http://github.com/jquery/jquery-ui. This will create a fork of jquery-ui in your Github account. +* You may want to clone jquery-ui under the path to your web server. If so, change to the required directory ```bash -$ cd /path/to/your/www/root/ +cd /path/to/your/www/root/ ``` -Clone your jQuery UI fork to work locally. - -*Note: be sure to replace `[USERNAME]` with your GitHub username.* +* Clone your jQuery UI git repo. ```bash -$ git clone git@github.com:[USERNAME]/jquery-ui.git +git clone git://github.com/[USERNAME]/jquery-ui.git +cd jquery-ui ``` -Change to the newly created directory. +*Note: be sure to replace `[USERNAME]` with your GitHub username.* + +* Add the official jQuery repository as a remote. We recommend naming it "upstream". ```bash -$ cd jquery-ui +git remote add upstream git://github.com/jquery/jquery-ui.git ``` -Add the official jQuery repository as a remote. We recommend naming it "upstream". +* Get in the habit of pulling in the "upstream" master to stay up to date as jQuery UI receives new commits. ```bash -$ git remote add upstream git://github.com/jquery/jquery-ui.git +git pull upstream master ``` -Get in the habit of pulling in the "upstream" master to stay up to date as jQuery UI receives new commits. +### Environment: Recommended Setup + +jQuery UI uses Node.js & Grunt to automate the building and validation of source code. Here is how to set that up: + +* Get [Node.js](http://nodejs.org/) (includes NPM, necessary for the next step) +* Install Grunt cli: ```bash -$ git pull upstream master +npm install -g grunt-cli ``` -Install the dependencies. +* Install local Node.js modules ```bash npm install ``` +The tests require a local web server and the samples contain some PHP, so a PHP web server may be useful. + +* Install a web server. Here are some you could use: + * Windows: [WAMP download](http://www.wampserver.com/en/) + * Mac: [MAMP download](http://www.mamp.info/en/index.html) + * Linux: [Setting up LAMP](https://www.linux.com/learn/tutorials/288158-easy-lamp-server-installation) + * [Mongoose (most platforms)](http://code.google.com/p/mongoose/) + * [http-server](https://www.npmjs.com/package/http-server) + +### Running the Tests + To lint the JavaScript, HTML, and CSS, as well as run a smoke test in PhantomJS, run grunt: ```bash -$ grunt +grunt ``` To run the tests for a specific plugin in your browser, open the appropriate file from the `/tests/unit/` directory, for example: `http://localhost/tests/unit/accordion/accordion.html`. The domain will be dependent on your local server configuration; if there is a port, be sure to include it. Ideally you would test in all of our [supported browsers](http://jqueryui.com/browser-support/), but if you don't have all of these browsers available, that's ok. - -Make sure to read our [commits and pull requests documentation](http://dev.contribute.jquery.org/commits-and-pull-requests/) for full details on working with branches and forks, as well as our commit guidelines. diff --git a/README.md b/README.md index edd49ab7baa..998a3f24be1 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ If you are interested in helping develop jQuery UI, you are in the right place. To discuss development with team members and the community, visit the [Developing jQuery UI Forum](http://forum.jquery.com/developing-jquery-ui) or [#jqueryui-dev on irc.freenode.net](http://irc.jquery.org/). -## For contributors +## For Contributors If you want to help and provide a patch for a bugfix or new feature, please take a few minutes and look at [our Getting Involved guide](http://wiki.jqueryui.com/w/page/35263114/Getting-Involved). @@ -21,35 +21,21 @@ In general, fork the project, create a branch for a specific change and send a pull request for that branch. Don't mix unrelated changes. You can use the commit message as the description for the pull request. +For more information, see the [contributing page](CONTRIBUTING.md). ## Running the Unit Tests -Run the unit tests with a local server that supports PHP. No database is required. Pre-configured php local servers are available for Windows and Mac. Here are some options: - -- Windows: [WAMP download](http://www.wampserver.com/en/) -- Mac: [MAMP download](http://www.mamp.info/en/index.html) -- Linux: [Setting up LAMP](https://www.linux.com/learn/tutorials/288158-easy-lamp-server-installation) -- [Mongoose (most platforms)](http://code.google.com/p/mongoose/) +Run the unit tests manually with appropriate browsers and any local web server. See our [environment setup](CONTRIBUTING.md#environment-minimum-required) and [information on running tests](CONTRIBUTING.md#running-the-tests). +You can also run the unit tests inside phantomjs by [setting up your environment](CONTRIBUTING.md#user-content-environment-recommended-setup). ## Building jQuery UI -jQuery UI uses the [Grunt](http://github.com/gruntjs/grunt) build system. +jQuery UI uses the [Grunt](http://gruntjs.com/) build system. -To build jQuery UI, you must have [node.js](http://nodejs.org/) installed and then run the following commands: +To build jQuery UI, [setup your environment]([setting up your environment](CONTRIBUTING.md#environment-minimum-required)) and then run the following commands: ```sh - -# Install the Grunt CLI -npm install -g grunt-cli - -# Clone the jQuery UI git repo -git clone git://github.com/jquery/jquery-ui.git -cd jquery-ui - -# Install the node module dependencies -npm install - # Run the concat task to concatenate files grunt concat From 105f4a5cb0b96efe77ac4380b483c08637e23a26 Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Tue, 27 Jan 2015 22:07:32 -0500 Subject: [PATCH 26/79] Resizable: Whitespace Cleanup (cherry picked from commit 337e4110b0cb60c73bb27be2e2b855a75a0c4b2e) --- tests/unit/resizable/resizable_options.js | 4 ++-- ui/resizable.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit/resizable/resizable_options.js b/tests/unit/resizable/resizable_options.js index c46801bc54d..9b364f5d3ba 100644 --- a/tests/unit/resizable/resizable_options.js +++ b/tests/unit/resizable/resizable_options.js @@ -237,7 +237,7 @@ test( "containment - immediate parent", function() { test("grid", function() { expect(4); - var handle = ".ui-resizable-se", target = $("#resizable1").resizable({ handles: "all", grid: [0, 20] }); + var handle = ".ui-resizable-se", target = $("#resizable1").resizable({ handles: "all", grid: [ 0, 20 ] }); TestHelpers.resizable.drag(handle, 3, 9); equal( target.width(), 103, "compare width"); @@ -265,7 +265,7 @@ test("grid (min/max dimensions)", function() { test("grid (wrapped)", function() { expect(4); - var handle = ".ui-resizable-se", target = $("#resizable2").resizable({ handles: "all", grid: [0, 20] }); + var handle = ".ui-resizable-se", target = $("#resizable2").resizable({ handles: "all", grid: [ 0, 20 ] }); TestHelpers.resizable.drag(handle, 3, 9); equal( target.width(), 103, "compare width"); diff --git a/ui/resizable.js b/ui/resizable.js index 8ec986f4fe5..6cfd9993969 100644 --- a/ui/resizable.js +++ b/ui/resizable.js @@ -943,7 +943,7 @@ $.ui.plugin.add( "resizable", "containment", { } } - if ( !continueResize ){ + if ( !continueResize ) { that.position.left = that.prevPosition.left; that.position.top = that.prevPosition.top; that.size.width = that.prevSize.width; From 0a0db09378fb21ef37fa261958d89f7f1a21ba76 Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Tue, 27 Jan 2015 22:08:05 -0500 Subject: [PATCH 27/79] Resizable: correct width when grid approaches zero Fixes #10590 (cherry picked from commit 9493839f23b6ff71aacb9cb8fe8fde6c8d0ecd61) --- tests/unit/resizable/resizable_options.js | 4 ++-- ui/resizable.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit/resizable/resizable_options.js b/tests/unit/resizable/resizable_options.js index 9b364f5d3ba..2b66fda3e45 100644 --- a/tests/unit/resizable/resizable_options.js +++ b/tests/unit/resizable/resizable_options.js @@ -311,12 +311,12 @@ test( "grid - maintains grid with padding and border when approaching no dimensi height: 80 }).resizable({ handles: "all", - grid: 50 + grid: [ 50, 12 ] }); TestHelpers.resizable.drag( handle, 50, 50 ); equal( target.outerWidth(), 50, "compare width" ); - equal( target.outerHeight(), 50, "compare height" ); + equal( target.outerHeight(), 52, "compare height" ); }); test("ui-resizable-se { handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 100, maxHeight: 100 }", function() { diff --git a/ui/resizable.js b/ui/resizable.js index 6cfd9993969..88b9ee7ea3d 100644 --- a/ui/resizable.js +++ b/ui/resizable.js @@ -1165,7 +1165,7 @@ $.ui.plugin.add("resizable", "grid", { that.size.width = newWidth; that.position.left = op.left - ox; } else { - newWidth = gridY - outerDimensions.height; + newWidth = gridX - outerDimensions.width; that.size.width = newWidth; that.position.left = op.left + os.width - newWidth; } From fa460f36dc8191e4fe23c02bcbcc7d5006b51d7e Mon Sep 17 00:00:00 2001 From: Marcus Warren Date: Mon, 2 Feb 2015 14:59:03 -0500 Subject: [PATCH 28/79] Sortable: Add support for iframes Fixes #9604 Closes gh-1443 (cherry picked from commit 17c7f698a2894211bbb5f2d63750f5b3b84bb0ab) --- ui/sortable.js | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/ui/sortable.js b/ui/sortable.js index 88bdf138b23..13a57e897b4 100644 --- a/ui/sortable.js +++ b/ui/sortable.js @@ -276,7 +276,7 @@ return $.widget("ui.sortable", $.ui.mouse, { } //Prepare scrolling - if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { + if(this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") { this.overflowOffset = this.scrollParent.offset(); } @@ -328,7 +328,7 @@ return $.widget("ui.sortable", $.ui.mouse, { //Do scrolling if(this.options.scroll) { - if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { + 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; @@ -344,16 +344,16 @@ return $.widget("ui.sortable", $.ui.mouse, { } else { - if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { - scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); - } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { - scrolled = $(document).scrollTop($(document).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(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { - scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); - } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { - scrolled = $(document).scrollLeft($(document).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); } } @@ -452,10 +452,10 @@ return $.widget("ui.sortable", $.ui.mouse, { animation = {}; if ( !axis || axis === "x" ) { - animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft); + animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollLeft); } if ( !axis || axis === "y" ) { - animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop); + animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollTop); } this.reverting = true; $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() { @@ -648,7 +648,7 @@ return $.widget("ui.sortable", $.ui.mouse, { if(connectWith && connected) { for (i = connectWith.length - 1; i >= 0; i--){ - cur = $(connectWith[i]); + cur = $(connectWith[i], this.document[0]); for ( j = cur.length - 1; j >= 0; j--){ inst = $.data(cur[j], this.widgetFullName); if(inst && inst !== this && !inst.options.disabled) { @@ -698,7 +698,7 @@ return $.widget("ui.sortable", $.ui.mouse, { if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down for (i = connectWith.length - 1; i >= 0; i--){ - cur = $(connectWith[i]); + cur = $(connectWith[i], this.document[0]); for (j = cur.length - 1; j >= 0; j--){ inst = $.data(cur[j], this.widgetFullName); if(inst && inst !== this && !inst.options.disabled) { @@ -990,14 +990,14 @@ return $.widget("ui.sortable", $.ui.mouse, { // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag - if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { + if(this.cssPosition === "absolute" && this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) { po.left += this.scrollParent.scrollLeft(); po.top += this.scrollParent.scrollTop(); } // This needs to be actually done for all browsers, since pageX/pageY includes this information // with an ugly IE fix - if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { + if( this.offsetParent[0] === this.document[0].body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { po = { top: 0, left: 0 }; } @@ -1047,8 +1047,8 @@ return $.widget("ui.sortable", $.ui.mouse, { this.containment = [ 0 - this.offset.relative.left - this.offset.parent.left, 0 - this.offset.relative.top - this.offset.parent.top, - $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left, - ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top + o.containment === "document" ? this.document.width() : this.window.width() - this.helperProportions.width - this.margins.left, + (o.containment === "document" ? this.document.width() : this.window.height() || this.document[0].body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top ]; } @@ -1073,7 +1073,7 @@ return $.widget("ui.sortable", $.ui.mouse, { pos = this.position; } var mod = d === "absolute" ? 1 : -1, - scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, + scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); return { @@ -1099,13 +1099,13 @@ return $.widget("ui.sortable", $.ui.mouse, { o = this.options, pageX = event.pageX, pageY = event.pageY, - scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); // This is another very weird special case that only happens for relative elements: // 1. If the css position is relative // 2. and the scroll parent is the document or similar to the offset parent // we have to refresh the relative offset during the scroll so there are no jumps - if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) { + if(this.cssPosition === "relative" && !(this.scrollParent[0] !== this.document[0] && this.scrollParent[0] !== this.offsetParent[0])) { this.offset.relative = this._getRelativeOffset(); } From 8dfc67d46865889057164005c827d1193781bc9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Wed, 11 Feb 2015 07:45:11 -0500 Subject: [PATCH 29/79] Build: Update authors list --- AUTHORS.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/AUTHORS.txt b/AUTHORS.txt index 1521874ce45..002b5893c0d 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -282,3 +282,10 @@ Will Holley Uri Gilad Richard Gibson Simen Bekkhus +Chen Eshchar +Bruno Pérel +Mohammed Alshehri +Anne-Gaelle Colom +Adam Foster +Luke Page +Marcus Warren From aec0b62e94e5c46d364218befc6e8f22449c9438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Thu, 12 Feb 2015 13:05:17 -0500 Subject: [PATCH 30/79] Build: Updating the 1-11-stable version to 1.11.4-pre. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 25fd51b3aff..988f9579890 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "jquery-ui", "title": "jQuery UI", "description": "A curated set of user interface interactions, effects, widgets, and themes built on top of the jQuery JavaScript Library.", - "version": "1.11.3-pre", + "version": "1.11.4-pre", "homepage": "http://jqueryui.com", "author": { "name": "jQuery Foundation and other contributors", From 258dbe3ae481b74c056e6445bd1aaaface9d6c48 Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Fri, 20 Feb 2015 04:42:29 +0000 Subject: [PATCH 31/79] Build: Use browserSets from testswarm config It's already in jQuery's Jenkins node-testswarm config (and set to the same value) but not used yet. Reference it to make sure it keeps working in the future. Closes gh-1452 (cherry picked from commit 1e7a1e811f7c9d624b2561ea3e2f34f80773ad0c) --- build/tasks/testswarm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/tasks/testswarm.js b/build/tasks/testswarm.js index aa1c52abc53..a23214e6d7d 100644 --- a/build/tasks/testswarm.js +++ b/build/tasks/testswarm.js @@ -61,7 +61,7 @@ function submit( commit, runs, configFile, extra, done ) { name: "Commit " + commit.substr( 0, 10 ) + "" + extra, runs: runs, runMax: config.runMax, - browserSets: [ "popular-ui" ], + browserSets: config.browserSets, timeout: 1000 * 60 * 30 }, function( error, passed ) { if ( error ) { From 189f1d476c2d6f53c88f9e92bdaffbc64ed9c572 Mon Sep 17 00:00:00 2001 From: TJ VanToll Date: Fri, 31 Oct 2014 09:46:41 -0400 Subject: [PATCH 32/79] Sortable: Redetermine floating flag when recalculating positions This addresses a bug where users initialize empty sortable lists are add items dynamically. In this situation refresh() should recognize the position and orientation of the new items. Fixes #7498 Closes gh-1381 (cherry picked from commit f656aebe3f99356b7eb91ffdafe6689ecc8fb4ae) --- tests/unit/sortable/sortable_methods.js | 35 +++++++++++++++++++++++++ ui/sortable.js | 10 +++---- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/tests/unit/sortable/sortable_methods.js b/tests/unit/sortable/sortable_methods.js index f3fe240e701..9c0a86a359b 100644 --- a/tests/unit/sortable/sortable_methods.js +++ b/tests/unit/sortable/sortable_methods.js @@ -90,4 +90,39 @@ test( "disable", function() { equal( chainable, element, "disable is chainable" ); }); +test( "refresh() should update the positions of initially empty lists (see #7498)", function() { + expect( 1 ); + + var changeCount = 0, + element = $( "#qunit-fixture" ).html( "
    " ).find( "ul" ); + + element + .css({ + "float": "left", + width: "100px" + }) + .sortable({ + change: function() { + changeCount++; + } + }) + .append( "
  • a
  • a
  • " ) + .find( "li" ) + .css({ + "float": "left", + width: "50px", + height: "50px" + }); + + element.sortable( "refresh" ); + + // Switch the order of the two li elements + element.find( "li" ).eq( 0 ).simulate( "drag", { + dx: 55, + moves: 15 + }); + + equal( changeCount, 1 ); +}); + })(jQuery); diff --git a/ui/sortable.js b/ui/sortable.js index 13a57e897b4..4cfb28979a0 100644 --- a/ui/sortable.js +++ b/ui/sortable.js @@ -77,17 +77,12 @@ return $.widget("ui.sortable", $.ui.mouse, { }, _create: function() { - - var o = this.options; this.containerCache = {}; this.element.addClass("ui-sortable"); //Get the items this.refresh(); - //Let's determine if the items are being displayed horizontally - this.floating = this.items.length ? o.axis === "x" || this._isFloating(this.items[0].item) : false; - //Let's determine the parent's offset this.offset = this.element.offset(); @@ -731,6 +726,11 @@ 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(); From b3710631e8d21ef9165ef9f037590e1d250350b4 Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Sat, 8 Nov 2014 20:23:08 -0500 Subject: [PATCH 33/79] Draggable: Ensure parent is correct after dragging through sortable Fixes #10669 (cherry picked from commit d8077dc562bfca60906a160e20186608a10b7a87) --- tests/unit/draggable/draggable_options.js | 23 +++++++++++++++++++++++ ui/draggable.js | 8 ++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index e54ae1df46d..d8bbedc9163 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -405,6 +405,29 @@ test( "connectToSortable, dragging through one sortable to a second", function() element.simulate( "drag", dragParams ); }); +test( "connectToSortable, dragging through a sortable", function() { + expect( 1 ); + + var draggable = $( "#draggableSortable" ).draggable({ + scroll: false, + connectToSortable: "#sortable2" + }), + sortable = $( "#sortable2" ).sortable(), + sortableOffset = sortable.offset(); + + // http://bugs.jqueryui.com/ticket/10669 + // Draggable: Position issue with connectToSortable + draggable.one( "dragstop", function() { + equal( draggable.parent().attr( "id" ), "sortable", "restored draggable to original parent" ); + }); + + draggable.simulate( "drag", { + x: sortableOffset.left + 25, + y: sortableOffset.top + sortable.outerHeight() + 400, + moves: 20 + }); +}); + test( "{ containment: Element }", function() { expect( 1 ); diff --git a/ui/draggable.js b/ui/draggable.js index a9d0279c493..c3821ba8eec 100644 --- a/ui/draggable.js +++ b/ui/draggable.js @@ -800,6 +800,9 @@ $.ui.plugin.add( "draggable", "connectToSortable", { if ( !sortable.isOver ) { sortable.isOver = 1; + // Store draggable's parent in case we need to reappend to it later. + draggable._parent = ui.helper.parent(); + sortable.currentItem = ui.helper .appendTo( sortable.element ) .data( "ui-sortable-item", true ); @@ -876,8 +879,9 @@ $.ui.plugin.add( "draggable", "connectToSortable", { sortable.placeholder.remove(); } - // Recalculate the draggable's offset considering the sortable - // may have modified them in unexpected ways (#8809) + // Restore and recalculate the draggable's offset considering the sortable + // may have modified them in unexpected ways. (#8809, #10669) + ui.helper.appendTo( draggable._parent ); draggable._refreshOffsets( event ); ui.position = draggable._generatePosition( event, true ); From 04ab6e0388f248b2490c2bc663528657ba39051a Mon Sep 17 00:00:00 2001 From: TJ VanToll Date: Wed, 18 Feb 2015 10:45:11 -0500 Subject: [PATCH 34/79] Dialog: Stop tracking instance in destroy() to avoid memory leaks Fixes #11125 Closes gh-1448 (cherry picked from commit ec1f393c39aa5bbac1158acf692271f8ce9518ce) --- ui/dialog.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/dialog.js b/ui/dialog.js index e5c0bfe21f9..d10b836572d 100644 --- a/ui/dialog.js +++ b/ui/dialog.js @@ -150,6 +150,7 @@ return $.widget( "ui.dialog", { var next, originalPosition = this.originalPosition; + this._untrackInstance(); this._destroyOverlay(); this.element From de75b40835ecb82360321dafbd87d66db5404a4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Mon, 2 Mar 2015 18:43:07 -0500 Subject: [PATCH 35/79] Accordion: Handle `box-sizing: border-box` in animations Fixes #9264 Closes gh-1287 Closes gh-1459 (cherry picked from commit 4b017b414f107ed3c1dafc7601b61cbcd76acf61) --- ui/accordion.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ui/accordion.js b/ui/accordion.js index 46f7e8509a8..98c8412cc67 100644 --- a/ui/accordion.js +++ b/ui/accordion.js @@ -516,6 +516,7 @@ return $.widget( "ui.accordion", { var total, easing, duration, that = this, adjust = 0, + boxSizing = toShow.css( "box-sizing" ), down = toShow.length && ( !toHide.length || ( toShow.index() < toHide.index() ) ), animate = this.options.animate || {}, @@ -558,7 +559,9 @@ return $.widget( "ui.accordion", { step: function( now, fx ) { fx.now = Math.round( now ); if ( fx.prop !== "height" ) { - adjust += fx.now; + if ( boxSizing === "content-box" ) { + adjust += fx.now; + } } else if ( that.options.heightStyle !== "content" ) { fx.now = Math.round( total - toHide.outerHeight() - adjust ); adjust = 0; From 65f31c2ead48755ac4cdffb95478a2f6d02801ff Mon Sep 17 00:00:00 2001 From: Patricia Juarez Date: Thu, 14 Nov 2013 13:40:57 +0100 Subject: [PATCH 36/79] Resizable: Modified to allow jquery objects as handles Custom handlers did not work as jquery objects (outside the resizable element) Fixes #9658 Closes gh-1445 (cherry picked from commit 18e301f4e29c2080e9aa9dac87c00dee137cb6c9) --- tests/unit/resizable/resizable.html | 1 + tests/unit/resizable/resizable_options.js | 29 +++++++++++++++++++++++ ui/resizable.js | 17 +++++++------ 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/tests/unit/resizable/resizable.html b/tests/unit/resizable/resizable.html index 5668c909a22..a44346e7cba 100644 --- a/tests/unit/resizable/resizable.html +++ b/tests/unit/resizable/resizable.html @@ -69,6 +69,7 @@
    I'm a resizable.
    +
    diff --git a/tests/unit/resizable/resizable_options.js b/tests/unit/resizable/resizable_options.js index 2b66fda3e45..d6829484528 100644 --- a/tests/unit/resizable/resizable_options.js +++ b/tests/unit/resizable/resizable_options.js @@ -375,6 +375,35 @@ test("ui-resizable-nw { handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 1 equal( target.height(), 100, "compare maxHeight" ); }); + +test( "custom handles { handles: { 's': $('#resizer1'), containment: 'parent' }", function () { + expect( 2 ); + + var handle = "#resizer1", + target = $( "#resizable1" ).resizable({ handles: { "s": $( "#resizer1" ) }, containment: "parent" }); + + TestHelpers.resizable.drag( handle, 0, 70 ); + equal( target.height(), 170, "compare height" ); + + TestHelpers.resizable.drag( handle, 0, -70 ); + equal( target.height(), 100, "compare height" ); +}); + + +test( "custom handles { handles: { 's': $('#resizer1')[0], containment: 'parent' }", function () { + expect( 2 ); + + var handle = "#resizer1", + target = $( "#resizable1" ).resizable({ handles: { "s": $( "#resizer1" )[ 0 ] }, containment: "parent" }); + + TestHelpers.resizable.drag( handle, 0, 70 ); + equal( target.height(), 170, "compare height" ); + + TestHelpers.resizable.drag( handle, 0, -70 ); + equal( target.height(), 100, "compare height" ); +}); + + test("zIndex, applied to all handles", function() { expect(8); diff --git a/ui/resizable.js b/ui/resizable.js index 88b9ee7ea3d..2df2413c7c7 100644 --- a/ui/resizable.js +++ b/ui/resizable.js @@ -160,7 +160,8 @@ $.widget("ui.resizable", $.ui.mouse, { nw: ".ui-resizable-nw" } ); - if (this.handles.constructor === String) { + this._handles = $(); + if ( this.handles.constructor === String ) { if ( this.handles === "all") { this.handles = "n,e,s,w,se,sw,ne,nw"; @@ -198,6 +199,9 @@ $.widget("ui.resizable", $.ui.mouse, { if (this.handles[i].constructor === String) { this.handles[i] = this.element.children( this.handles[ i ] ).first().show(); + } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) { + this.handles[ i ] = $( this.handles[ i ] ); + this._on( this.handles[ i ], { "mousedown": that._mouseDown }); } if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)) { @@ -214,21 +218,17 @@ $.widget("ui.resizable", $.ui.mouse, { target.css(padPos, padWrapper); this._proportionallyResize(); - } - // TODO: What's that good for? There's not anything to be executed left - if (!$(this.handles[i]).length) { - continue; - } + this._handles = this._handles.add( this.handles[ i ] ); } }; // TODO: make renderAxis a prototype function this._renderAxis(this.element); - this._handles = $(".ui-resizable-handle", this.element) - .disableSelection(); + this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) ); + this._handles.disableSelection(); this._handles.mouseover(function() { if (!that.resizing) { @@ -262,7 +262,6 @@ $.widget("ui.resizable", $.ui.mouse, { } this._mouseInit(); - }, _destroy: function() { From 31e7099709a3bccaae8f83d397951096835269a2 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Mon, 25 Aug 2014 14:07:25 -0400 Subject: [PATCH 37/79] Resizable: alsoResize more than one element of a jQuery selection Fixes #4666 Closes gh-1324 Closes gh-1461 (cherry picked from commit 19783fd3e6a6e6e02a2030028e8820076c3b1295) --- tests/unit/resizable/resizable_options.js | 30 ++++++++++ ui/resizable.js | 68 +++++++---------------- 2 files changed, 51 insertions(+), 47 deletions(-) diff --git a/tests/unit/resizable/resizable_options.js b/tests/unit/resizable/resizable_options.js index d6829484528..7fd409cecb2 100644 --- a/tests/unit/resizable/resizable_options.js +++ b/tests/unit/resizable/resizable_options.js @@ -433,4 +433,34 @@ test( "alsoResize + containment", function() { equal( other.height(), 150, "alsoResize constrained height at containment edge" ); }); +test( "alsoResize + multiple selection", function() { + expect( 6 ); + var other1 = $( "
    " ) + .addClass( "other" ) + .css({ + width: 50, + height: 50 + }) + .appendTo( "body" ), + other2 = $( "
    " ) + .addClass( "other" ) + .css({ + width: 50, + height: 50 + }) + .appendTo( "body"), + element = $( "#resizable1" ).resizable({ + alsoResize: other1.add( other2 ), + containment: "#container" + }); + + TestHelpers.resizable.drag( ".ui-resizable-se", 400, 400 ); + equal( element.width(), 300, "resizable constrained width at containment edge" ); + equal( element.height(), 200, "resizable constrained height at containment edge" ); + equal( other1.width(), 250, "alsoResize o1 constrained width at containment edge" ); + equal( other1.height(), 150, "alsoResize o1 constrained height at containment edge" ); + equal( other2.width(), 250, "alsoResize o2 constrained width at containment edge" ); + equal( other2.height(), 150, "alsoResize o2 constrained height at containment edge" ); +}); + })(jQuery); diff --git a/ui/resizable.js b/ui/resizable.js index 2df2413c7c7..6c010783a38 100644 --- a/ui/resizable.js +++ b/ui/resizable.js @@ -983,29 +983,15 @@ $.ui.plugin.add("resizable", "alsoResize", { start: function() { var that = $(this).resizable( "instance" ), - o = that.options, - _store = function(exp) { - $(exp).each(function() { - var el = $(this); - el.data("ui-resizable-alsoresize", { - width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), - left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10) - }); - }); - }; + o = that.options; - if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) { - if (o.alsoResize.length) { - o.alsoResize = o.alsoResize[0]; - _store(o.alsoResize); - } else { - $.each(o.alsoResize, function(exp) { - _store(exp); - }); - } - } else { - _store(o.alsoResize); - } + $(o.alsoResize).each(function() { + var el = $(this); + el.data("ui-resizable-alsoresize", { + width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), + left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10) + }); + }); }, resize: function(event, ui) { @@ -1018,35 +1004,23 @@ $.ui.plugin.add("resizable", "alsoResize", { width: (that.size.width - os.width) || 0, top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0 - }, + }; + + $(o.alsoResize).each(function() { + var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {}, + css = el.parents(ui.originalElement[0]).length ? + [ "width", "height" ] : + [ "width", "height", "top", "left" ]; - _alsoResize = function(exp, c) { - $(exp).each(function() { - var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {}, - css = c && c.length ? - c : - el.parents(ui.originalElement[0]).length ? - [ "width", "height" ] : - [ "width", "height", "top", "left" ]; - - $.each(css, function(i, prop) { - var sum = (start[prop] || 0) + (delta[prop] || 0); - if (sum && sum >= 0) { - style[prop] = sum || null; - } - }); - - el.css(style); + $.each(css, function(i, prop) { + var sum = (start[prop] || 0) + (delta[prop] || 0); + if (sum && sum >= 0) { + style[prop] = sum || null; + } }); - }; - if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) { - $.each(o.alsoResize, function(exp, c) { - _alsoResize(exp, c); + el.css(style); }); - } else { - _alsoResize(o.alsoResize); - } }, stop: function() { From 0f99e9c9693b05199d9f8c1137606c7033e19f38 Mon Sep 17 00:00:00 2001 From: Ablay Keldibek Date: Wed, 4 Mar 2015 18:23:17 +0600 Subject: [PATCH 38/79] Slider: Modified to allow value to reach max value with float step Fixes #11286 Closes gh-1465 (cherry picked from commit 60c00cd4ecdab41f44e125efe2679223e9cd5535) --- tests/unit/slider/slider_methods.js | 12 +++++++++++- ui/slider.js | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/unit/slider/slider_methods.js b/tests/unit/slider/slider_methods.js index c5c7e1254aa..ce26620e221 100644 --- a/tests/unit/slider/slider_methods.js +++ b/tests/unit/slider/slider_methods.js @@ -62,7 +62,7 @@ test( "disable", function() { }); test( "value", function() { - expect( 17 ); + expect( 18 ); $( [ false, "min", "max" ] ).each(function() { var element = $( "
    " ).slider({ range: this, @@ -88,6 +88,16 @@ test( "value", function() { equal( element.slider( "value" ), 1, "value method get respects max" ); equal( element.slider( "value", 2 ), element, "value method is chainable" ); equal( element.slider( "option", "value" ), 1, "value method set respects max" ); + + // set max value with step 0.01 + element.slider( "option", { + min: 2, + value: 2, + max: 2.4, + step: 0.01 + }); + element.slider( "option", "value", 2.4 ); + equal( element.slider( "value" ), 2.4, "value is set to max with 0.01 step" ); }); //test( "values", function() { diff --git a/ui/slider.js b/ui/slider.js index edc8b402729..65204ca9168 100644 --- a/ui/slider.js +++ b/ui/slider.js @@ -550,7 +550,7 @@ return $.widget( "ui.slider", $.ui.mouse, { var max = this.options.max, min = this._valueMin(), step = this.options.step, - aboveMin = Math.floor( ( max - min ) / step ) * step; + aboveMin = Math.floor( ( +( max - min ).toFixed( this._precision() ) ) / step ) * step; max = aboveMin + min; this.max = parseFloat( max.toFixed( this._precision() ) ); }, From d6997254f01c953d4f6d60b37057ca84f7f98856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Mon, 23 Feb 2015 16:33:18 -0500 Subject: [PATCH 39/79] Dialog: Fix typo Closes gh-1447 Thanks Spencer Davis (cherry picked from commit d95c23ae6c44e7d82289bb0a82eb1a7840a7a5f2) --- ui/dialog.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/dialog.js b/ui/dialog.js index d10b836572d..d33f72c1e92 100644 --- a/ui/dialog.js +++ b/ui/dialog.js @@ -229,10 +229,10 @@ return $.widget( "ui.dialog", { _moveToTop: function( event, silent ) { var moved = false, - zIndicies = this.uiDialog.siblings( ".ui-front:visible" ).map(function() { + zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map(function() { return +$( this ).css( "z-index" ); }).get(), - zIndexMax = Math.max.apply( null, zIndicies ); + zIndexMax = Math.max.apply( null, zIndices ); if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) { this.uiDialog.css( "z-index", zIndexMax + 1 ); From ddc1b32a45746db7cc8e96de92818936464b323b Mon Sep 17 00:00:00 2001 From: Nils Heuermann Date: Fri, 31 Oct 2014 14:24:29 +0100 Subject: [PATCH 40/79] Sortable: Append a tr with td to the placeholder of tbody elements When sorting tbody elements of a table the placeholder needs to have a tr with td elements to be visible. The appended elements are created in the same way as for the placeholder of a tr element; the first row of the sorted tbody is used for that. Fixes #10682 Closes gh-1380 (cherry picked from commit 962e05dc1d0a51a7458bc44725417aa3462cd89a) --- tests/unit/sortable/sortable.html | 52 +++++++++++++++++++++---- tests/unit/sortable/sortable_options.js | 36 +++++++++++++++++ ui/sortable.js | 23 ++++++++--- 3 files changed, 97 insertions(+), 14 deletions(-) diff --git a/tests/unit/sortable/sortable.html b/tests/unit/sortable/sortable.html index 3edc999b76e..f13b895b8db 100644 --- a/tests/unit/sortable/sortable.html +++ b/tests/unit/sortable/sortable.html @@ -74,20 +74,56 @@ - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    121.11.2
    341.31.4
    561.51.6
    781.71.8
    2.12.2
    2.32.4
    2.52.6
    2.72.8
    3.13.2
    3.33.4
    3.53.6
    3.73.8
    diff --git a/tests/unit/sortable/sortable_options.js b/tests/unit/sortable/sortable_options.js index f2beb4dbcd6..90cf765a2b5 100644 --- a/tests/unit/sortable/sortable_options.js +++ b/tests/unit/sortable/sortable_options.js @@ -388,6 +388,42 @@ test( "{ placholder: String } tr", function() { }); }); +test( "{ placholder: String } tbody", function() { + expect( 6 ); + + var originalWidths, + element = $( "#sortable-table" ).sortable({ + placeholder: "test", + start: function( event, ui ) { + var currentWidths = otherBody.children().map(function() { + return $( this ).width(); + }).get(); + ok( ui.placeholder.hasClass( "test" ), "placeholder has class" ); + deepEqual( currentWidths, originalWidths, "table cells maintain size" ); + equal( ui.placeholder.children().length, 1, + "placeholder has one child" ); + equal( ui.placeholder.children( "tr" ).length, 1, + "placeholder's child is tr" ); + equal( ui.placeholder.find( "> tr" ).children().length, + dragBody.find( "> tr:first" ).children().length, + "placeholder's tr has correct number of cells" ); + equal( ui.placeholder.find( "> tr" ).children().html(), + $( " " ).html(), + "placeholder td has content for forced dimensions" ); + } + }), + bodies = element.children( "tbody" ), + dragBody = bodies.eq( 0 ), + otherBody = bodies.eq( 1 ); + + originalWidths = otherBody.children().map(function() { + return $( this ).width(); + }).get(); + dragBody.simulate( "drag", { + dy: 1 + }); +}); + /* test("{ revert: false }, default", function() { ok(false, "missing test - untested code is broken code."); diff --git a/ui/sortable.js b/ui/sortable.js index 4cfb28979a0..a2dd034ce7b 100644 --- a/ui/sortable.js +++ b/ui/sortable.js @@ -788,12 +788,13 @@ return $.widget("ui.sortable", $.ui.mouse, { .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder") .removeClass("ui-sortable-helper"); - if ( nodeName === "tr" ) { - that.currentItem.children().each(function() { - $( " ", that.document[0] ) - .attr( "colspan", $( this ).attr( "colspan" ) || 1 ) - .appendTo( element ); - }); + if ( nodeName === "tbody" ) { + that._createTrPlaceholder( + that.currentItem.find( "tr" ).eq( 0 ), + $( "", that.document[ 0 ] ).appendTo( element ) + ); + } else if ( nodeName === "tr" ) { + that._createTrPlaceholder( that.currentItem, element ); } else if ( nodeName === "img" ) { element.attr( "src", that.currentItem.attr( "src" ) ); } @@ -830,6 +831,16 @@ return $.widget("ui.sortable", $.ui.mouse, { }, + _createTrPlaceholder: function( sourceTr, targetTr ) { + var that = this; + + sourceTr.children().each(function() { + $( " ", that.document[ 0 ] ) + .attr( "colspan", $( this ).attr( "colspan" ) || 1 ) + .appendTo( targetTr ); + }); + }, + _contactContainers: function(event) { var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, floating, axis, innermostContainer = null, From 1c92d68c042a493303edb48c11b3e35d62d6aff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Mon, 23 Feb 2015 14:55:25 -0500 Subject: [PATCH 41/79] Tabs: Use standard promise methods for jqXHR The old success(), error() and complete() methods have been deprecated for a while and have been removed in upstream master. Closes gh-1455 (cherry picked from commit c1dfb98d4576901aacf35f99d2506e8f652c2690) --- demos/tabs/ajax.html | 2 +- ui/tabs.js | 29 +++++++++++++++++------------ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/demos/tabs/ajax.html b/demos/tabs/ajax.html index ba766dd298d..7a486fc9635 100644 --- a/demos/tabs/ajax.html +++ b/demos/tabs/ajax.html @@ -13,7 +13,7 @@ $(function() { $( "#tabs" ).tabs({ beforeLoad: function( event, ui ) { - ui.jqXHR.error(function() { + ui.jqXHR.fail(function() { ui.panel.html( "Couldn't load this tab. We'll try to fix this as soon as possible. " + "If this wouldn't be a demo." ); diff --git a/ui/tabs.js b/ui/tabs.js index 3cdcae6fcba..db4c9726a41 100644 --- a/ui/tabs.js +++ b/ui/tabs.js @@ -817,6 +817,18 @@ return $.widget( "ui.tabs", { eventData = { tab: tab, panel: panel + }, + complete = function( jqXHR, status ) { + if ( status === "abort" ) { + that.panels.stop( false, true ); + } + + tab.removeClass( "ui-tabs-loading" ); + panel.removeAttr( "aria-busy" ); + + if ( jqXHR === that.xhr ) { + delete that.xhr; + } }; // not remote @@ -834,28 +846,21 @@ return $.widget( "ui.tabs", { panel.attr( "aria-busy", "true" ); this.xhr - .success(function( response ) { + .done(function( response, status, jqXHR ) { // support: jQuery <1.8 // http://bugs.jquery.com/ticket/11778 setTimeout(function() { panel.html( response ); that._trigger( "load", event, eventData ); + + complete( jqXHR, status ); }, 1 ); }) - .complete(function( jqXHR, status ) { + .fail(function( jqXHR, status ) { // support: jQuery <1.8 // http://bugs.jquery.com/ticket/11778 setTimeout(function() { - if ( status === "abort" ) { - that.panels.stop( false, true ); - } - - tab.removeClass( "ui-tabs-loading" ); - panel.removeAttr( "aria-busy" ); - - if ( jqXHR === that.xhr ) { - delete that.xhr; - } + complete( jqXHR, status ); }, 1 ); }); } From 88291ffc4d6a5f4762ae65e42de607f5588101dd Mon Sep 17 00:00:00 2001 From: Marco Ziech Date: Mon, 23 Feb 2015 19:33:01 -0500 Subject: [PATCH 42/79] Tooltip: Register event handlers before content is loaded Fixes #8740 Closes gh-1053 Closes gh-1456 (cherry picked from commit c4e367bb31c21d7c8b2701c626a92a2f13be5af4) --- tests/unit/tooltip/tooltip_options.js | 22 ++++++++++++++++++++++ ui/tooltip.js | 26 +++++++++++++++++++------- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/tests/unit/tooltip/tooltip_options.js b/tests/unit/tooltip/tooltip_options.js index 17f0a423775..a07f65199ab 100644 --- a/tests/unit/tooltip/tooltip_options.js +++ b/tests/unit/tooltip/tooltip_options.js @@ -71,6 +71,28 @@ asyncTest( "content: sync + async callback", function() { }).tooltip( "open" ); }); +// http://bugs.jqueryui.com/ticket/8740 +asyncTest( "content: async callback loses focus before load", function() { + expect( 1 ); + + var element = $( "#tooltipped1" ).tooltip({ + content: function( response ) { + setTimeout(function() { + element.trigger( "mouseleave" ); + setTimeout(function() { + response( "sometext" ); + setTimeout(function() { + ok( !$( "#" + element.data( "ui-tooltip-id" ) ).is( ":visible" ), + "Tooltip should not display" ); + start(); + }); + }); + }); + } + }); + element.trigger( "mouseover" ); +}); + test( "content: change while open", function() { expect( 2 ) ; var element = $( "#tooltipped1" ).tooltip({ diff --git a/ui/tooltip.js b/ui/tooltip.js index 73844c0eae3..8408f6781fb 100644 --- a/ui/tooltip.js +++ b/ui/tooltip.js @@ -194,6 +194,7 @@ return $.widget( "ui.tooltip", { }); } + this._registerCloseHandlers( event, target ); this._updateContent( target, event ); }, @@ -208,13 +209,16 @@ return $.widget( "ui.tooltip", { } content = contentOption.call( target[0], function( response ) { - // ignore async response if tooltip was closed already - if ( !target.data( "ui-tooltip-open" ) ) { - return; - } + // IE may instantly serve a cached response for ajax requests // delay this call to _open so the other call to _open runs first that._delay(function() { + + // Ignore async response if tooltip was closed already + if ( !target.data( "ui-tooltip-open" ) ) { + return; + } + // jQuery creates a special event for focusin when it doesn't // exist natively. To improve performance, the native event // object is reused and the type is changed. Therefore, we can't @@ -232,7 +236,7 @@ return $.widget( "ui.tooltip", { }, _open: function( event, target, content ) { - var tooltipData, tooltip, events, delayedShow, a11yContent, + var tooltipData, tooltip, delayedShow, a11yContent, positionOption = $.extend( {}, this.options.position ); if ( !content ) { @@ -314,8 +318,10 @@ return $.widget( "ui.tooltip", { } this._trigger( "open", event, { tooltip: tooltip } ); + }, - events = { + _registerCloseHandlers: function( event, target ) { + var events = { keyup: function( event ) { if ( event.keyCode === $.ui.keyCode.ESCAPE ) { var fakeEvent = $.Event(event); @@ -329,7 +335,7 @@ return $.widget( "ui.tooltip", { // tooltips will handle this in destroy. if ( target[ 0 ] !== this.element[ 0 ] ) { events.remove = function() { - this._removeTooltip( tooltip ); + this._removeTooltip( this._find( target ).tooltip ); }; } @@ -350,6 +356,12 @@ return $.widget( "ui.tooltip", { // The tooltip may already be closed if ( !tooltipData ) { + + // We set ui-tooltip-open immediately upon open (in open()), but only set the + // additional data once there's actually content to show (in _open()). So even if the + // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in + // the period between open() and _open(). + target.removeData( "ui-tooltip-open" ); return; } From 40cdb5f57ac178521bf6d5f702c2df60731f4401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Tue, 10 Mar 2015 12:47:51 -0400 Subject: [PATCH 43/79] Build: Update authors list --- AUTHORS.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/AUTHORS.txt b/AUTHORS.txt index 002b5893c0d..bf1554481da 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -289,3 +289,8 @@ Anne-Gaelle Colom Adam Foster Luke Page Marcus Warren +Patricia Juarez +Ben Mosher +Ablay Keldibek +Nils Heuermann +Marco Ziech From b93df29e4db20521b1db39e5cfa87d6da28d37ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Wed, 11 Mar 2015 09:03:14 -0400 Subject: [PATCH 44/79] Build: Updating the 1-11-stable version to 1.11.5-pre. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 988f9579890..9ee9214d679 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "jquery-ui", "title": "jQuery UI", "description": "A curated set of user interface interactions, effects, widgets, and themes built on top of the jQuery JavaScript Library.", - "version": "1.11.4-pre", + "version": "1.11.5-pre", "homepage": "http://jqueryui.com", "author": { "name": "jQuery Foundation and other contributors", From 82d4e6045952569e2f37981a33c8a2fa442e104f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Tue, 10 Mar 2015 15:16:27 -0400 Subject: [PATCH 45/79] Dialog: Fix focus tests in IE8 with jQuery 1.7 Ref gh-1481 (cherry picked from commit a6a18d1ed82ca68cf1a8551be706ea8b03841242) --- tests/unit/dialog/dialog_core.js | 88 +++++++++++++++++--------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/tests/unit/dialog/dialog_core.js b/tests/unit/dialog/dialog_core.js index d72fef7b5bf..56f1e3da8e7 100644 --- a/tests/unit/dialog/dialog_core.js +++ b/tests/unit/dialog/dialog_core.js @@ -59,90 +59,94 @@ asyncTest( "focus tabbable", function() { element = $( markup ).dialog( options ); setTimeout(function() { - testFn(); - element.remove(); - setTimeout( next ); + testFn(function done() { + element.remove(); + setTimeout( next ); + }); }); } function step1() { - element = $( "
    " ).dialog( options ); - setTimeout(function() { + checkFocus( "
    ", options, function( done ) { var input = element.find( "input:last" ).focus().blur(); element.dialog( "instance" )._focusTabbable(); setTimeout(function() { equal( document.activeElement, input[ 0 ], "1. an element that was focused previously." ); - element.remove(); - setTimeout( step2 ); + done(); }); - }); + }, step2 ); } function step2() { - checkFocus( "
    ", options, function() { + checkFocus( "
    ", options, function( done ) { equal( document.activeElement, element.find( "input" )[ 1 ], "2. first element inside the dialog matching [autofocus]" ); + done(); }, step3 ); } function step3() { - checkFocus( "
    ", options, function() { + checkFocus( "
    ", options, function( done ) { equal( document.activeElement, element.find( "input" )[ 0 ], "3. tabbable element inside the content element" ); + done(); }, step4 ); } function step4() { - checkFocus( "
    text
    ", options, function() { + checkFocus( "
    text
    ", options, function( done ) { equal( document.activeElement, element.dialog( "widget" ).find( ".ui-dialog-buttonpane button" )[ 0 ], "4. tabbable element inside the buttonpane" ); + done(); }, step5 ); } function step5() { - checkFocus( "
    text
    ", {}, function() { + checkFocus( "
    text
    ", {}, function( done ) { equal( document.activeElement, element.dialog( "widget" ).find( ".ui-dialog-titlebar .ui-dialog-titlebar-close" )[ 0 ], "5. the close button" ); + done(); }, step6 ); } function step6() { - element = $( "
    text
    " ).dialog({ - autoOpen: false - }); - element.dialog( "widget" ).find( ".ui-dialog-titlebar-close" ).hide(); - element.dialog( "open" ); - setTimeout(function() { - equal( document.activeElement, element.parent()[ 0 ], "6. the dialog itself" ); - element.remove(); - setTimeout( step7 ); - }); + checkFocus( "
    text
    ", { autoOpen: false }, function( done ) { + element.dialog( "widget" ).find( ".ui-dialog-titlebar-close" ).hide(); + element.dialog( "open" ); + setTimeout(function() { + equal( document.activeElement, element.parent()[ 0 ], "6. the dialog itself" ); + done(); + }); + }, step7 ); } function step7() { - element = $( "
    " ).dialog({ - open: function() { - var inputs = $( this ).find( "input" ); - inputs.last().keydown(function( event ) { - event.preventDefault(); - inputs.first().focus(); - }); - } - }); - setTimeout(function() { - var inputs = element.find( "input" ); - equal( document.activeElement, inputs[ 1 ], "Focus starts on second input" ); - inputs.last().simulate( "keydown", { keyCode: $.ui.keyCode.TAB }); - setTimeout(function() { - equal( document.activeElement, inputs[ 0 ], - "Honor preventDefault, allowing custom focus management" ); - element.remove(); - start(); - }, 50 ); - }); + checkFocus( + "
    ", + { + open: function() { + var inputs = $( this ).find( "input" ); + inputs.last().keydown(function( event ) { + event.preventDefault(); + inputs.first().focus(); + }); + } + }, + function( done ) { + var inputs = element.find( "input" ); + equal( document.activeElement, inputs[ 1 ], "Focus starts on second input" ); + inputs.last().simulate( "keydown", { keyCode: $.ui.keyCode.TAB }); + setTimeout(function() { + equal( document.activeElement, inputs[ 0 ], + "Honor preventDefault, allowing custom focus management" ); + done(); + }, 50 ); + }, + start + ); } step1(); From b2aa641c04fb00901c7de9acf1bdc59f65bbed25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Tue, 10 Mar 2015 16:10:43 -0400 Subject: [PATCH 46/79] Accordion: Fix tests in IE 11 with jQuery 1.7-1.8 Closes gh-1482 (cherry picked from commit 8ea36f5e0cc389752fdecdd17f0a82a2d560d4bb) --- tests/unit/accordion/accordion_core.js | 67 +++++++++++++++++++++----- 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/tests/unit/accordion/accordion_core.js b/tests/unit/accordion/accordion_core.js index dc0649b3bc8..721d1548751 100644 --- a/tests/unit/accordion/accordion_core.js +++ b/tests/unit/accordion/accordion_core.js @@ -110,38 +110,81 @@ asyncTest( "keyboard support", function() { keyCode = $.ui.keyCode; equal( headers.filter( ".ui-state-focus" ).length, 0, "no headers focused on init" ); headers.eq( 0 ).simulate( "focus" ); - setTimeout(function() { + setTimeout( step1 ); + + function step1() { ok( headers.eq( 0 ).is( ".ui-state-focus" ), "first header has focus" ); headers.eq( 0 ).simulate( "keydown", { keyCode: keyCode.DOWN } ); + setTimeout( step2 ); + } + + // Support: IE 11 with jQuery 1.7 - 1.8 only + // All of the setTimeouts() from keydowns aren't necessary with newer jQuery. + // Only the explicit focus simulations require them. + function step2() { ok( headers.eq( 1 ).is( ".ui-state-focus" ), "DOWN moves focus to next header" ); headers.eq( 1 ).simulate( "keydown", { keyCode: keyCode.RIGHT } ); + setTimeout( step3 ); + } + + function step3() { ok( headers.eq( 2 ).is( ".ui-state-focus" ), "RIGHT moves focus to next header" ); headers.eq( 2 ).simulate( "keydown", { keyCode: keyCode.DOWN } ); - ok( headers.eq( 0 ).is( ".ui-state-focus" ), "DOWN wraps focus to first header" ); + setTimeout( step4 ); + } + function step4() { + ok( headers.eq( 0 ).is( ".ui-state-focus" ), "DOWN wraps focus to first header" ); headers.eq( 0 ).simulate( "keydown", { keyCode: keyCode.UP } ); + setTimeout( step5 ); + } + + function step5() { ok( headers.eq( 2 ).is( ".ui-state-focus" ), "UP wraps focus to last header" ); headers.eq( 2 ).simulate( "keydown", { keyCode: keyCode.LEFT } ); - ok( headers.eq( 1 ).is( ".ui-state-focus" ), "LEFT moves focus to previous header" ); + setTimeout( step6 ); + } + function step6() { + ok( headers.eq( 1 ).is( ".ui-state-focus" ), "LEFT moves focus to previous header" ); headers.eq( 1 ).simulate( "keydown", { keyCode: keyCode.HOME } ); + setTimeout( step7 ); + } + + function step7() { ok( headers.eq( 0 ).is( ".ui-state-focus" ), "HOME moves focus to first header" ); headers.eq( 0 ).simulate( "keydown", { keyCode: keyCode.END } ); - ok( headers.eq( 2 ).is( ".ui-state-focus" ), "END moves focus to last header" ); + setTimeout( step8 ); + } + function step8() { + ok( headers.eq( 2 ).is( ".ui-state-focus" ), "END moves focus to last header" ); headers.eq( 2 ).simulate( "keydown", { keyCode: keyCode.ENTER } ); + setTimeout( step9 ); + } + + function step9() { equal( element.accordion( "option", "active" ) , 2, "ENTER activates panel" ); headers.eq( 1 ).simulate( "keydown", { keyCode: keyCode.SPACE } ); - equal( element.accordion( "option", "active" ), 1, "SPACE activates panel" ); + setTimeout( step10 ); + } + function step10() { + equal( element.accordion( "option", "active" ), 1, "SPACE activates panel" ); anchor.simulate( "focus" ); - setTimeout(function() { - ok( !headers.eq( 1 ).is( ".ui-state-focus" ), "header loses focus when focusing inside the panel" ); - anchor.simulate( "keydown", { keyCode: keyCode.UP, ctrlKey: true } ); - ok( headers.eq( 1 ).is( ".ui-state-focus" ), "CTRL+UP moves focus to header" ); - start(); - }, 1 ); - }, 1 ); + setTimeout( step11 ); + } + + function step11() { + ok( !headers.eq( 1 ).is( ".ui-state-focus" ), "header loses focus when focusing inside the panel" ); + anchor.simulate( "keydown", { keyCode: keyCode.UP, ctrlKey: true } ); + setTimeout( step12 ); + } + + function step12() { + ok( headers.eq( 1 ).is( ".ui-state-focus" ), "CTRL+UP moves focus to header" ); + start(); + } }); }( jQuery ) ); From d86df4b697b73c0e5ba971a912ae6d0b0385d512 Mon Sep 17 00:00:00 2001 From: Ablay Keldibek Date: Thu, 12 Mar 2015 13:26:24 +0600 Subject: [PATCH 47/79] Slider: Verify value constraint with a max that is a step mismatch Ref #10078 Closes gh-1485 (cherry picked from commit 21831f5036bd695cc2734ec3f44e97549d2f7660) --- tests/unit/slider/slider_methods.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/unit/slider/slider_methods.js b/tests/unit/slider/slider_methods.js index ce26620e221..1a82e6edfbf 100644 --- a/tests/unit/slider/slider_methods.js +++ b/tests/unit/slider/slider_methods.js @@ -62,7 +62,7 @@ test( "disable", function() { }); test( "value", function() { - expect( 18 ); + expect( 19 ); $( [ false, "min", "max" ] ).each(function() { var element = $( "
    " ).slider({ range: this, @@ -98,6 +98,16 @@ test( "value", function() { }); element.slider( "option", "value", 2.4 ); equal( element.slider( "value" ), 2.4, "value is set to max with 0.01 step" ); + + element = $( "
    " ).slider({ + value: 100, + min: 10, + max: 500, + step: 50 + }); + + element.slider( "option", "value", 510 ); + equal( element.slider( "value" ), 460, "value is restricted to maximum valid step" ); }); //test( "values", function() { From 2256eeda45c0f52df87ee2241a88b3d70e83711e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Mon, 9 Mar 2015 16:03:22 -0400 Subject: [PATCH 48/79] Core: Add methods to work around IE active element bugs Closes gh-1478 (cherry picked from commit f33027840cdac5152599da66635981bbe68c6bda) --- ui/autocomplete.js | 2 +- ui/core.js | 25 +++++++++++++++++++++++++ ui/dialog.js | 26 +++++++------------------- ui/draggable.js | 15 ++------------- ui/menu.js | 4 ++-- ui/spinner.js | 4 ++-- ui/tabs.js | 2 +- 7 files changed, 40 insertions(+), 38 deletions(-) diff --git a/ui/autocomplete.js b/ui/autocomplete.js index dc970b5c704..6e477bb41aa 100644 --- a/ui/autocomplete.js +++ b/ui/autocomplete.js @@ -278,7 +278,7 @@ $.widget( "ui.autocomplete", { previous = this.previous; // only trigger when focus was lost (click on menu) - if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) { + if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) { this.element.focus(); this.previous = previous; // #6109 - IE triggers two focus events and the second diff --git a/ui/core.js b/ui/core.js index 0b2e039509c..40703d73dd2 100644 --- a/ui/core.js +++ b/ui/core.js @@ -43,6 +43,31 @@ $.extend( $.ui, { SPACE: 32, TAB: 9, UP: 38 + }, + + // Internal use only + safeActiveElement: function( document ) { + var activeElement; + + // Support: IE 9 only + // IE9 throws an "Unspecified error" accessing document.activeElement from an