From 432191b799d9e7eaf8b98e77ca08dbed24651cee Mon Sep 17 00:00:00 2001 From: Matthew O'Riordan Date: Tue, 4 Mar 2014 14:13:17 +0000 Subject: [PATCH 01/69] Include instructions for installation via Bower --- README.md | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d2442a5e..31b2905c 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Requirements If you don't use HTML5, adding "data" attributes to your HTML4 or XHTML pages might make them fail [W3C markup validation][validator]. However, this shouldn't create any issues for web browsers or other user agents. -Installation +Installation using the jQuery-Rails Gem ------------ For automated installation in Rails, use the "jquery-rails" gem. Place this in your Gemfile: @@ -52,6 +52,29 @@ Choose to overwrite jquery_ujs.js if prompted.* c. For Rails 2.x and for manual installation follow [this wiki](https://github.com/rails/jquery-ujs/wiki/Manual-installing-and-Rails-2) . +Installation using Bower +------------ + +Modify your bower.json file and add jQuery-UJS as a dependency as follows: + +```javascript +{ + "dependencies": { + /* include jQuery-UJS as below */ + "jquery-ujs": "git@github.com:rails/jquery-ujs.git" + } +} +``` + +Then run `bower install jquery-ujs` to install the jQuery-UJS package. + +For Rails 3.1 and above, add these lines to the top of your app/assets/javascripts/application.js file: + +```javascript +//= require jquery +//= require jquery-ujs/src/rails +``` + How to run tests ------------ From d10970ac1cc7c836fd43da8d56a16dee802e573c Mon Sep 17 00:00:00 2001 From: Lucas Mazza Date: Wed, 6 Aug 2014 22:57:05 -0300 Subject: [PATCH 02/69] Update dependencies --- Gemfile.lock | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index aa541a84..966496e1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,20 +1,23 @@ GEM remote: https://rubygems.org/ specs: - daemons (1.1.0) - eventmachine (0.12.10) - rack (1.2.1) - rake (10.1.1) - shotgun (0.8) + daemons (1.1.9) + eventmachine (1.0.3) + rack (1.5.2) + rack-protection (1.5.3) + rack + rake (10.3.2) + shotgun (0.9) rack (>= 1.0) - sinatra (1.1.2) - rack (~> 1.1) - tilt (~> 1.2) - thin (1.2.7) + sinatra (1.4.5) + rack (~> 1.4) + rack-protection (~> 1.4) + tilt (~> 1.3, >= 1.3.4) + thin (1.6.2) daemons (>= 1.0.9) - eventmachine (>= 0.12.6) + eventmachine (>= 1.0.0) rack (>= 1.0.0) - tilt (1.2.1) + tilt (1.4.1) PLATFORMS ruby From b2787d457f2680b67103f611fa91f95fe8509eb2 Mon Sep 17 00:00:00 2001 From: Gabriel Sobrinho Date: Thu, 7 Aug 2014 01:34:09 -0300 Subject: [PATCH 03/69] Re-enables buttons and links after going back Firefox has a weird behavior where when you hit the back button it keeps the submit buttons and links on disabled state which even reloading the page do not re-enables them. Using the pageshow event, which is triggered every time a page loads, we can keep the rails-ujs behavior consistent with all other browsers. See https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching [Fixes #357] --- src/rails.js | 23 ++++++++++++++++++++ test/public/test/data-disable-with.js | 30 +++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/rails.js b/src/rails.js index a26f48c6..ae4355c0 100644 --- a/src/rails.js +++ b/src/rails.js @@ -322,6 +322,29 @@ $.ajaxPrefilter(function(options, originalOptions, xhr){ if ( !options.crossDomain ) { rails.CSRFProtection(xhr); }}); + // This event works the same as the load event, except that it fires every + // time the page is loaded. + // + // See https://github.com/rails/jquery-ujs/issues/357 + // See https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching + $(window).on("pageshow.rails", function () { + $($.rails.enableSelector).each(function () { + var element = $(this); + + if (element.data("ujs:enable-with")) { + $.rails.enableFormElement(element); + } + }); + + $($.rails.linkDisableSelector).each(function () { + var element = $(this); + + if (element.data("ujs:enable-with")) { + $.rails.enableElement(element); + } + }); + }); + $document.delegate(rails.linkDisableSelector, 'ajax:complete', function() { rails.enableElement($(this)); }); diff --git a/test/public/test/data-disable-with.js b/test/public/test/data-disable-with.js index f0903b1f..5e2a67da 100644 --- a/test/public/test/data-disable-with.js +++ b/test/public/test/data-disable-with.js @@ -99,6 +99,24 @@ asyncTest('form input[type=submit][data-disable-with] disables', 6, function(){ }, 30); }); +test('form input[type=submit][data-disable-with] re-enables when `pageshow` event is triggered', function(){ + var form = $('form:not([data-remote])'), input = form.find('input[type=submit]'); + + App.checkEnabledState(input, 'Submit'); + + // Emulate the disabled state without submitting the form at all, what is the + // state after going back on firefox after submitting a form. + // + // See https://github.com/rails/jquery-ujs/issues/357 + $.rails.disableFormElements(form); + + App.checkDisabledState(input, 'submitting ...'); + + $(window).trigger('pageshow'); + + App.checkEnabledState(input, 'Submit'); +}); + asyncTest('form[data-remote] input[type=submit][data-disable-with] is replaced in ajax callback', 2, function(){ var form = $('form:not([data-remote])').attr('data-remote', 'true'), origFormContents = form.html(); @@ -173,6 +191,18 @@ asyncTest('a[data-disable-with] disables', 4, function() { start(); }); +test('a[data-disable-with] re-enables when `pageshow` event is triggered', function() { + var link = $('a[data-disable-with]'); + + App.checkEnabledState(link, 'Click me'); + + link.trigger('click'); + App.checkDisabledState(link, 'clicking...'); + + $(window).trigger('pageshow'); + App.checkEnabledState(link, 'Click me'); +}); + asyncTest('a[data-remote][data-disable-with] disables and re-enables', 6, function() { var link = $('a[data-disable-with]').attr('data-remote', true); From 60aadb18582fcf8efbe5611e85ac84cdf2ca3728 Mon Sep 17 00:00:00 2001 From: Lucas Mazza Date: Wed, 27 Aug 2014 16:43:04 -0300 Subject: [PATCH 04/69] Release 1.0.1 --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index ea9b1ab4..3e7634bf 100644 --- a/bower.json +++ b/bower.json @@ -5,7 +5,7 @@ "description": "Ruby on Rails unobtrusive scripting adapter for jQuery", "main": "src/rails.js", "license": "MIT", - "version": "1.0.0", + "version": "1.0.1", "dependencies": { "jquery": ">1.8.*" }, From 52cdbe26667b988a485f1bfd2c48c2645d635b38 Mon Sep 17 00:00:00 2001 From: Lucas Mazza Date: Mon, 8 Sep 2014 13:35:04 -0300 Subject: [PATCH 05/69] Rewrite the CHANGELOG to display the changes between each tagged release. --- CHANGELOG.md | 64 ++++++++++++++++------------------------------------ 1 file changed, 19 insertions(+), 45 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe03033a..fb61e14a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,45 +1,19 @@ -CHANGELOG -========= - -Here is a non-exhaustive list of notable changes to jquery-ujs (oldest -to newest): - -- [`085d910a5ec07b69`](https://github.com/rails/jquery-ujs/commit/085d910a5ec07b69f31beabce286141aa26f3005) last version before callback names updated -- [`72d875a8d57c6bb4`](https://github.com/rails/jquery-ujs/commit/72d875a8d57c6bb466170980a5142c66ac74e8f0) callback name updates completed -- [`e076121248913143`](https://github.com/rails/jquery-ujs/commit/e0761212489131437402a92fa8f548a78f685ae2) dropped support for jQuery 1.4, 1.4.1, 1.4.2 (separate [v1.4 branch](https://github.com/rails/jquery-ujs/commits/v1.4) created) -- [`498b35e24cdb14f2`](https://github.com/rails/jquery-ujs/commit/498b35e24cdb14f2d94486e8a1f4a1f661091426) last version before `.callRemote()` removed -- [`ec96408a746d3b06`](https://github.com/rails/jquery-ujs/commit/ec96408a746d3b0692da9249f218a3943fbffc28) `ACCEPTS` header data-type default changed to prefer `:js` but not require it -- [`fc639928d1e15c88`](https://github.com/rails/jquery-ujs/commit/fc639928d1e15c885b85de5b517346db7f963f44) default form method changed from `POST` to `GET` -- [`e9311550fdb3afeb`](https://github.com/rails/jquery-ujs/commit/e9311550fdb3afeb2917bcb1fef39767bf715003) added CSRF Protection to remote requests -- [`a284dd706e7d76e8`](https://github.com/rails/jquery-ujs/commit/a284dd706e7d76e85471ef39ab3efdf07feef374) CSRF fixed - changed to only add if token is present -- [`f9b21b3a3c7c4684`](https://github.com/rails/jquery-ujs/commit/f9b21b3a3c7c46840fed8127a90def26911fad3d) `ajax:before` added back -- [`7f2acc1811f62877`](https://github.com/rails/jquery-ujs/commit/7f2acc1811f62877611e16451530728b5e13dbe7) last version before file-upload aborting behavior added -- [`ca575e184e93b3ef`](https://github.com/rails/jquery-ujs/commit/ca575e184e93b3efe1a858cf598f8a37f0a760cc) added `ajax:aborted:required` and `ajax:aborted:file` event hooks -- [`d2abd6f9df4e4a42`](https://github.com/rails/jquery-ujs/commit/d2abd6f9df4e4a426c17c218b7d5e05004c768d0) fixed submit and bubbling behavior for IE -- [`d59144177d867908`](https://github.com/rails/jquery-ujs/commit/d59144177d86790891fdb99b0e3437312e04fda2) created external api via `$.rails` object -- [`cd357e492de14747`](https://github.com/rails/jquery-ujs/commit/cd357e492de147472a8a2524575acce5d923e640) added support for jQuery 1.6 and dropped support for jQuery 1.4.3 -- [`50c06dcc02c1b08c`](https://github.com/rails/jquery-ujs/commit/50c06dcc02c1b08cb7a9b4b8eced54ed685c1c93) added `confirm:complete` event hook which is passed result from confirm dialog -- [`8063d1d47ea6a08e`](https://github.com/rails/jquery-ujs/commit/8063d1d47ea6a08e545e9a6ba3e84af584200e41) made $.rails.confirm and $.rails.ajax functions available in $.rails object -- [`a96c4e9b074998c6`](https://github.com/rails/jquery-ujs/commit/a96c4e9b074998c6b6d102e4573b81c8a76f07a7) added support for jQuery 1.6.1 -- [`dad6982dc5926866`](https://github.com/rails/jquery-ujs/commit/dad6982dc592686677e6845e681233c40d2ead27) added support for `data-params` attribute on remote links -- [`5433841d01622345`](https://github.com/rails/jquery-ujs/commit/5433841d01622345f734f22f82394ac035c2f783) removed support for jQuery 1.4.4 and 1.5.x, and added support for jQuery 1.6.2 -- [`cd619df9f0daad33`](https://github.com/rails/jquery-ujs/commit/cd619df9f0daad3303aacd4f992fff19158b1e5d) added support for html5 `novalidate` attribute, so required fields validation is not enforced -- [`840ab6ac76b2d5ab`](https://github.com/rails/jquery-ujs/commit/840ab6ac76b2d5ab931841bc3d8567e5b57f183e) added support for jQuery 1.6.3 -- [`ba5808e73111fb65`](https://github.com/rails/jquery-ujs/commit/ba5808e73111fb65e91610b078577bb014d9b6d8) added `data-remote` support for checkboxes -- [`6e9a06d45eaf2da1`](https://github.com/rails/jquery-ujs/commit/6e9a06d45eaf2da1036d4c2ead25ff57d0127d03) added `data-disable-with` support for links -- [`89396108ce574080`](https://github.com/rails/jquery-ujs/commit/89396108ce574080f9b877cad74573c5d1ae9aa2) added `data-remote` support for all input types -- [`c01215c3d48ebb9f`](https://github.com/rails/jquery-ujs/commit/c01215c3d48ebb9f9f1059f26efa0c0c9092da2b) added support for jQuery 1.6.4 -- [`17f4004310b6ece3`](https://github.com/rails/jquery-ujs/commit/17f4004310b6ece3cb240914932b4d6d46032c24) added support for jQuery 1.7 -- [`cb54ae287f5c7320`](https://github.com/rails/jquery-ujs/commit/cb54ae287f5c73207aef2891cdf22212aea5fb86) added support for jQuery 1.7.1 -- [`dbb1b5f72a62e59f`](https://github.com/rails/jquery-ujs/commit/dbb1b5f72a62e59f34f6b5be4bee291ee7f3318f) added support for jQuery 1.7.2 -- [`8100cf3b2462f144`](https://github.com/rails/jquery-ujs/commit/8100cf3b2462f144e6a0bcef7cb78d05be41755d) created `rails:attachBindings` to allow for customization of - $.rails object settings -- [`e4ca2045b202cd7a`](https://github.com/rails/jquery-ujs/commit/e4ca2045b202cd7ade97d78c20caa2822c5c28da) created `ajax:send` event to provide access to jqXHR object from - ajax requests -- [`4382f580766fcdd1`](https://github.com/rails/jquery-ujs/commit/4382f580766fcdd14201c204f43ca5aeb0928501) added support for `data-with-credentials` -- [`12da9fc2f175c8e4`](https://github.com/rails/jquery-ujs/commit/12da9fc2f175c8e445413b15cf6b685deb271d6e) added support for jQuery 1.8.0, removed support for jquery 1.6.x -- [`faeb0ad734ff6867`](https://github.com/rails/jquery-ujs/commit/faeb0ad734ff6867149b8522f9a29081734442e6) added support for jQuery 1.8.1 -- [`b6dae4ef4a2d031a`](https://github.com/rails/jquery-ujs/commit/b6dae4ef4a2d031a222627c7f6a4284602f99160) added support for jQuery 1.8.2 -- [`6927b82cadf3146c`](https://github.com/rails/jquery-ujs/commit/6927b82cadf3146c2b9ae3028e9b197af64011ca) added support for jQuery 1.8.3 -- [`cc356656cc3edf15`](https://github.com/rails/jquery-ujs/commit/cc356656cc3edf1596fd685265187d2f75d1bc7c) added support for jQuery 1.9.0 -- [`2f8ccdf26eac199a`](https://github.com/rails/jquery-ujs/commit/2f8ccdf26eac199a11aa1a893a8909bb4650d0fb) added support for jQuery 1.9.1 +## Unreleased + +* Re-enables buttons and links after going back through the `pageshow` event. + + *Gabriel Sobrinho* + +## v1.0.1 + +* `confirm` is no longer called twice for `button` elements inside a `form`. + + *Lucas Mazza* + +* `button` or submit inputs using the `form` attribute are properly bound. + + *Marnen Laibow-Koser* + +## v1.0.0 + +* First tagged release. From 7cbd1278563b533da192d8e629c30b789ebc7456 Mon Sep 17 00:00:00 2001 From: Lucas Mazza Date: Mon, 8 Sep 2014 13:36:16 -0300 Subject: [PATCH 06/69] Remove version constraint from `jquery-rails` installation example. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8df8340d..ee5e5c23 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Installation For automated installation in Rails, use the "jquery-rails" gem. Place this in your Gemfile: ```ruby -gem 'jquery-rails', '~> 2.1' +gem 'jquery-rails' ``` And run: From 97c28b141db84c6e034b7a983e7c7566a69248b0 Mon Sep 17 00:00:00 2001 From: Lucas Mazza Date: Mon, 8 Sep 2014 13:39:51 -0300 Subject: [PATCH 07/69] Simplify bower installation steps --- README.md | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 868ade22..ac1129e2 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Requirements If you don't use HTML5, adding "data" attributes to your HTML4 or XHTML pages might make them fail [W3C markup validation][validator]. However, this shouldn't create any issues for web browsers or other user agents. -Installation using the jQuery-Rails Gem +Installation using the jquery-rails gem ------------ For automated installation in Rails, use the "jquery-rails" gem. Place this in your Gemfile: @@ -55,24 +55,13 @@ c. For Rails 2.x and for manual installation follow [this wiki](https://github.c Installation using Bower ------------ -Modify your bower.json file and add jQuery-UJS as a dependency as follows: - -```javascript -{ - "dependencies": { - /* include jQuery-UJS as below */ - "jquery-ujs": "git@github.com:rails/jquery-ujs.git" - } -} -``` - -Then run `bower install jquery-ujs` to install the jQuery-UJS package. +Run `bower install jquery-ujs --save` to install the jquery-ujs package. For Rails 3.1 and above, add these lines to the top of your app/assets/javascripts/application.js file: ```javascript //= require jquery -//= require jquery-ujs/src/rails +//= require jquery-ujs ``` How to run tests From 2f22624a923c783343577a6fe88186f70776d5c2 Mon Sep 17 00:00:00 2001 From: Lucas Mazza Date: Mon, 8 Sep 2014 13:45:33 -0300 Subject: [PATCH 08/69] Extract the redudant setup steps and remove instructions for older versions of rails/jquery-rails. --- README.md | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index ac1129e2..53894c89 100644 --- a/README.md +++ b/README.md @@ -31,33 +31,19 @@ gem 'jquery-rails' And run: - $ bundle install - -This next step depends on your version of Rails. - -a. For Rails 3.1, add these lines to the top of your app/assets/javascripts/application.js file: - -```javascript -//= require jquery -//= require jquery_ujs +```shell +$ bundle install ``` -b. For Rails 3.0, run this command: - -*Be sure to get rid of the rails.js file if it exists, and instead use -the new jquery_ujs.js file that gets copied to the public directory. -Choose to overwrite jquery_ujs.js if prompted.* - - $ rails generate jquery:install - -c. For Rails 2.x and for manual installation follow [this wiki](https://github.com/rails/jquery-ujs/wiki/Manual-installing-and-Rails-2) . - Installation using Bower ------------ Run `bower install jquery-ujs --save` to install the jquery-ujs package. -For Rails 3.1 and above, add these lines to the top of your app/assets/javascripts/application.js file: +Usage +------------ + +Require both `jquery` and `jquery-ujs` into your application.js manifest. ```javascript //= require jquery From c1fcef5baa2e854d5c47267f4be57a6c1ce86822 Mon Sep 17 00:00:00 2001 From: Lucas Mazza Date: Tue, 9 Sep 2014 21:49:30 -0300 Subject: [PATCH 09/69] jquery-rails ships with 'jquery_ujs', not 'jquery-ujs'. Closes #390. --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 53894c89..29ea432d 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,13 @@ And run: $ bundle install ``` +Require both `jquery` and `jquery_ujs` into your application.js manifest. + +```javascript +//= require jquery +//= require jquery_ujs +``` + Installation using Bower ------------ From 57f4848652584f33018e46414605a873194a97d7 Mon Sep 17 00:00:00 2001 From: Dmitry Karpunin Date: Wed, 15 Oct 2014 11:13:05 +0400 Subject: [PATCH 10/69] Small optimization `method` extracted from `data` at 357 does not change over function --- src/rails.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rails.js b/src/rails.js index ae4355c0..c0f45238 100644 --- a/src/rails.js +++ b/src/rails.js @@ -371,7 +371,7 @@ } return false; - } else if (link.data('method')) { + } else if (method) { rails.handleMethod(link); return false; } From 9a4602f04bf40cf11dcab1a42e9997feb8258197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 25 Nov 2014 21:58:02 -0200 Subject: [PATCH 11/69] Release 1.0.2 --- CHANGELOG.md | 2 +- bower.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb61e14a..3005c6c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## Unreleased +## v1.0.2 * Re-enables buttons and links after going back through the `pageshow` event. diff --git a/bower.json b/bower.json index 3e7634bf..cfee5da0 100644 --- a/bower.json +++ b/bower.json @@ -5,7 +5,7 @@ "description": "Ruby on Rails unobtrusive scripting adapter for jQuery", "main": "src/rails.js", "license": "MIT", - "version": "1.0.1", + "version": "1.0.2", "dependencies": { "jquery": ">1.8.*" }, From 8fc44057482460793052d8ff2e0ccb74448dd702 Mon Sep 17 00:00:00 2001 From: Krzysztof Kotlarski Date: Fri, 5 Dec 2014 14:29:53 +0100 Subject: [PATCH 12/69] Add support form HTML5 "formaction" and "formmethod" attributes in remote forms --- src/rails.js | 11 ++++++++--- test/public/test/call-remote.js | 26 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/rails.js b/src/rails.js index c0f45238..3bec1074 100644 --- a/src/rails.js +++ b/src/rails.js @@ -100,8 +100,8 @@ dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType); if (element.is('form')) { - method = element.attr('method'); - url = element.attr('action'); + method = element.data('ujs:submit-button-formmethod') || element.attr('method'); + url = element.data('ujs:submit-button-formaction') || element.attr('action'); data = element.serializeArray(); // memoized value from clicked submit button var button = element.data('ujs:submit-button'); @@ -109,6 +109,8 @@ data.push(button); element.data('ujs:submit-button', null); } + element.data('ujs:submit-button-formmethod', null) + element.data('ujs:submit-button-formaction', null) } else if (element.is(rails.inputChangeSelector)) { method = element.data('method'); url = element.data('url'); @@ -450,7 +452,10 @@ var name = button.attr('name'), data = name ? {name:name, value:button.val()} : null; - button.closest('form').data('ujs:submit-button', data); + button.closest('form') + .data('ujs:submit-button', data) + .data('ujs:submit-button-formaction', button.attr('formaction')) + .data('ujs:submit-button-formmethod', button.attr('formmethod')); }); $document.delegate(rails.formSubmitSelector, 'ajax:send.rails', function(event) { diff --git a/test/public/test/call-remote.js b/test/public/test/call-remote.js index d78ce565..8bd09bc2 100644 --- a/test/public/test/call-remote.js +++ b/test/public/test/call-remote.js @@ -32,6 +32,19 @@ asyncTest('form method is not read from "data-method" attribute in case of missi }); }); +asyncTest('form method is read from submit button "formmethod" if submit is triggered by that button', 1, function() { + var submitButton = $('') + buildForm({ method: 'post' }); + + $('#qunit-fixture').find('form').append(submitButton) + .bind('ajax:success', function(e, data, status, xhr) { + App.assertGetRequest(data); + }) + .bind('ajax:complete', function() { start() }); + + submitButton.trigger('click'); +}); + asyncTest('form default method is GET', 1, function() { buildForm(); @@ -56,6 +69,19 @@ asyncTest('form url is read from "action" not "href"', 1, function() { }); }); +asyncTest('form url is read from submit button "formaction" if submit is triggered by that button', 1, function() { + var submitButton = $('') + buildForm({ method: 'post', href: '/echo2' }); + + $('#qunit-fixture').find('form').append(submitButton) + .bind('ajax:success', function(e, data, status, xhr) { + App.assertRequestPath(data, '/echo'); + }) + .bind('ajax:complete', function() { start() }); + + submitButton.trigger('click'); +}); + asyncTest('prefer JS, but accept any format', 1, function() { buildForm({ method: 'post' }); From 04653649da71f6405a7387a7a7412ac3ed88db35 Mon Sep 17 00:00:00 2001 From: Ryunosuke SATO Date: Sat, 20 Dec 2014 17:32:09 +0900 Subject: [PATCH 13/69] Add jQuery 1.11.x and 2.1.x to .travis.yml matrics They are current stable versions. --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 8b7d9259..985c8a05 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,5 +11,10 @@ env: - JQUERY_VERSION: 1.10.1 - JQUERY_VERSION: 1.10.2 - JQUERY_VERSION: 1.11.0 + - JQUERY_VERSION: 1.11.1 + - JQUERY_VERSION: 1.11.2 - JQUERY_VERSION: 2.0.0 - JQUERY_VERSION: 2.1.0 + - JQUERY_VERSION: 2.1.1 + - JQUERY_VERSION: 2.1.2 + - JQUERY_VERSION: 2.1.3 From 9664dac7ea1fca6c3ee3df61ad179582666edbf9 Mon Sep 17 00:00:00 2001 From: Carlos Antonio da Silva Date: Mon, 29 Dec 2014 17:27:17 -0200 Subject: [PATCH 14/69] Bundle update --- Gemfile.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 966496e1..8ced3297 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,21 +2,21 @@ GEM remote: https://rubygems.org/ specs: daemons (1.1.9) - eventmachine (1.0.3) - rack (1.5.2) + eventmachine (1.0.4) + rack (1.6.0) rack-protection (1.5.3) rack - rake (10.3.2) + rake (10.4.2) shotgun (0.9) rack (>= 1.0) sinatra (1.4.5) rack (~> 1.4) rack-protection (~> 1.4) tilt (~> 1.3, >= 1.3.4) - thin (1.6.2) - daemons (>= 1.0.9) - eventmachine (>= 1.0.0) - rack (>= 1.0.0) + thin (1.6.3) + daemons (~> 1.0, >= 1.0.9) + eventmachine (~> 1.0) + rack (~> 1.0) tilt (1.4.1) PLATFORMS From 5a5952880ff6ce7e0c46f37cdf9d17eb70608bee Mon Sep 17 00:00:00 2001 From: Carlos Antonio da Silva Date: Mon, 29 Dec 2014 17:27:30 -0200 Subject: [PATCH 15/69] Replace deprecated deferred.error() with fail() Ported from rails/jquery-rails#184. --- src/rails.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rails.js b/src/rails.js index c0f45238..a4fb0bed 100644 --- a/src/rails.js +++ b/src/rails.js @@ -367,7 +367,7 @@ if (handleRemote === false) { rails.enableElement(link); } else { - handleRemote.error( function() { rails.enableElement(link); } ); + handleRemote.fail( function() { rails.enableElement(link); } ); } return false; @@ -389,7 +389,7 @@ if (handleRemote === false) { rails.enableFormElement(button); } else { - handleRemote.error( function() { rails.enableFormElement(button); } ); + handleRemote.fail( function() { rails.enableFormElement(button); } ); } return false; }); From 519aad962496497870621e5b6afe2a727a28839d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 29 Dec 2014 18:10:13 -0300 Subject: [PATCH 16/69] Release 1.0.3 --- CHANGELOG.md | 5 +++++ bower.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3005c6c4..8e4116fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## v1.0.3 + +* Replace deprecated `deferred.error()` with `fail()`. + + *Carlos Antonio da Silva* ## v1.0.2 * Re-enables buttons and links after going back through the `pageshow` event. diff --git a/bower.json b/bower.json index cfee5da0..9b5d5df6 100644 --- a/bower.json +++ b/bower.json @@ -5,7 +5,7 @@ "description": "Ruby on Rails unobtrusive scripting adapter for jQuery", "main": "src/rails.js", "license": "MIT", - "version": "1.0.2", + "version": "1.0.3", "dependencies": { "jquery": ">1.8.*" }, From 96f4474065df7a9afbebd36151aa66ee9e57ac25 Mon Sep 17 00:00:00 2001 From: Julien Vanier Date: Thu, 12 Mar 2015 14:21:53 -0400 Subject: [PATCH 17/69] Extract csrfToken and csrfParam to allow external use --- src/rails.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/rails.js b/src/rails.js index a4fb0bed..211c7226 100644 --- a/src/rails.js +++ b/src/rails.js @@ -54,17 +54,25 @@ // Button onClick disable selector with possible reenable after remote submission buttonDisableSelector: 'button[data-remote][data-disable-with], button[data-remote][data-disable]', + // Up-to-date Cross-Site Request Forgery token + csrfToken: function() { + return $('meta[name=csrf-token]').attr('content'); + }, + + // URL param that must contain the CSRF token + csrfParam: function() { + return $('meta[name=csrf-param]').attr('content'); + }, + // Make sure that every Ajax request sends the CSRF token CSRFProtection: function(xhr) { - var token = $('meta[name="csrf-token"]').attr('content'); + var token = rails.csrfToken(); if (token) xhr.setRequestHeader('X-CSRF-Token', token); }, // making sure that all forms have actual up-to-date token(cached forms contain old one) refreshCSRFTokens: function(){ - var csrfToken = $('meta[name=csrf-token]').attr('content'); - var csrfParam = $('meta[name=csrf-param]').attr('content'); - $('form input[name="' + csrfParam + '"]').val(csrfToken); + $('form input[name="' + rails.csrfParam() + '"]').val(rails.csrfToken()); }, // Triggers an event on an element and returns false if the event result is false From 9e6c2a4becbb072bf83f3ba059b766c231ae287b Mon Sep 17 00:00:00 2001 From: Julien Vanier Date: Thu, 12 Mar 2015 14:45:22 -0400 Subject: [PATCH 18/69] Added tests --- test/public/test/csrf-token.js | 27 +++++++++++++++++++++++++++ test/views/index.erb | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 test/public/test/csrf-token.js diff --git a/test/public/test/csrf-token.js b/test/public/test/csrf-token.js new file mode 100644 index 00000000..dfed3781 --- /dev/null +++ b/test/public/test/csrf-token.js @@ -0,0 +1,27 @@ +(function(){ + +module('csrf-token', {}); + +asyncTest('find csrf token', 1, function() { + var correctToken = "cf50faa3fe97702ca1ae"; + + $('#qunit-fixture').append(''); + + currentToken = $.rails.csrfToken(); + + start(); + equal(currentToken, correctToken); +}); + +asyncTest('find csrf param', 1, function() { + var correctParam = "authenticity_token"; + + $('#qunit-fixture').append(''); + + currentParam = $.rails.csrfParam(); + + start(); + equal(currentParam, correctParam); +}); + +})(); diff --git a/test/views/index.erb b/test/views/index.erb index f153cd12..776a4bab 100644 --- a/test/views/index.erb +++ b/test/views/index.erb @@ -1,6 +1,6 @@ <% @title = "jquery-ujs test" %> -<%= test 'data-confirm', 'data-remote', 'data-disable', 'data-disable-with', 'call-remote', 'call-remote-callbacks', 'data-method', 'override', 'csrf-refresh' %> +<%= test 'data-confirm', 'data-remote', 'data-disable', 'data-disable-with', 'call-remote', 'call-remote-callbacks', 'data-method', 'override', 'csrf-refresh', 'csrf-token' %>

<%= @title %>

From 96561a2ac0fab58e3e248458e19003e09f106ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Wed, 25 Mar 2015 17:23:33 -0300 Subject: [PATCH 19/69] Properly check if the request is cross domain Fix CVE-2015-1840 --- src/rails.js | 31 +++++++++++++++++----- test/public/test/call-remote-callbacks.js | 14 ---------- test/public/test/call-remote.js | 32 ----------------------- test/public/test/data-method.js | 26 ++++++++++++++++++ test/public/test/override.js | 2 +- 5 files changed, 52 insertions(+), 53 deletions(-) diff --git a/src/rails.js b/src/rails.js index a4fb0bed..1ee8859e 100644 --- a/src/rails.js +++ b/src/rails.js @@ -86,16 +86,14 @@ // Default way to get an element's href. May be overridden at $.rails.href. href: function(element) { - return element.attr('href'); + return element[0].href; }, // Submits "remote" forms and links with ajax handleRemote: function(element) { - var method, url, data, elCrossDomain, crossDomain, withCredentials, dataType, options; + var method, url, data, withCredentials, dataType, options; if (rails.fire(element, 'ajax:before')) { - elCrossDomain = element.data('cross-domain'); - crossDomain = elCrossDomain === undefined ? null : elCrossDomain; withCredentials = element.data('with-credentials') || null; dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType); @@ -147,7 +145,7 @@ error: function(xhr, status, error) { element.trigger('ajax:error', [xhr, status, error]); }, - crossDomain: crossDomain + crossDomain: rails.isCrossDomain(url) }; // There is no withCredentials for IE6-8 when @@ -167,6 +165,27 @@ } }, + // Determines if the request is a cross domain request. + isCrossDomain: function(url) { + var originAnchor = document.createElement("a"); + originAnchor.href = location.href; + var urlAnchor = document.createElement("a"); + + try { + urlAnchor.href = url; + // This is a workaround to a IE bug. + urlAnchor.href = urlAnchor.href; + + // Make sure that the browser parses the URL and that the protocols and hosts match. + return !urlAnchor.protocol || !urlAnchor.host || + (originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host); + } catch (e) { + // If there is an error parsing the URL, assume it is crossDomain. + return true; + } + }, + // Handles "data-method" on links such as: // Delete handleMethod: function(link) { @@ -178,7 +197,7 @@ form = $('
'), metadataInput = ''; - if (csrfParam !== undefined && csrfToken !== undefined) { + if (csrfParam !== undefined && csrfToken !== undefined && !rails.isCrossDomain(href)) { metadataInput += ''; } diff --git a/test/public/test/call-remote-callbacks.js b/test/public/test/call-remote-callbacks.js index c1791f6b..ad306a3e 100644 --- a/test/public/test/call-remote-callbacks.js +++ b/test/public/test/call-remote-callbacks.js @@ -64,20 +64,6 @@ asyncTest('modifying data("type") with "ajax:before" requests new dataType in re }); }); -asyncTest('setting data("cross-domain",true) with "ajax:before" uses new setting in request', 2, function(){ - $('form[data-remote]').data('cross-domain',false) - .bind('ajax:before', function() { - var form = $(this); - form.data('cross-domain',true); - }); - - submit(function(form) { - form.bind('ajax:beforeSend', function(e, xhr, settings) { - equal(settings.crossDomain, true, 'setting modified in ajax:before should have forced cross-domain request'); - }); - }); -}); - asyncTest('setting data("with-credentials",true) with "ajax:before" uses new setting in request', 2, function(){ $('form[data-remote]').data('with-credentials',false) .bind('ajax:before', function() { diff --git a/test/public/test/call-remote.js b/test/public/test/call-remote.js index d78ce565..94316e88 100644 --- a/test/public/test/call-remote.js +++ b/test/public/test/call-remote.js @@ -122,22 +122,6 @@ asyncTest('sends CSRF token in custom header', 1, function() { }); }); -asyncTest('does not send CSRF token in custom header if crossDomain', 1, function() { - buildForm({ 'data-cross-domain': 'true' }); - $('#qunit-fixture').append(''); - - // Manually set request header to be XHR, since setting crossDomain: true in .ajax() - // causes jQuery to skip setting the request header, to prevent our test/server.rb from - // raising an an error (when request.xhr? is false). - $('#qunit-fixture').find('form').bind('ajax:beforeSend', function(e, xhr) { - xhr.setRequestHeader('X-Requested-With', "XMLHttpRequest"); - }); - - submit(function(e, data, status, xhr) { - equal(data.HTTP_X_CSRF_TOKEN, undefined, 'X-CSRF-Token header should NOT be sent'); - }); -}); - asyncTest('intelligently guesses crossDomain behavior when target URL is a different domain', 1, function(e, xhr) { // Don't set data-cross-domain here, just set action to be a different domain than localhost @@ -156,20 +140,4 @@ asyncTest('intelligently guesses crossDomain behavior when target URL is a diffe setTimeout(function() { start(); }, 13); }); - -asyncTest('does not set crossDomain if explicitly set to false on element', 1, function() { - buildForm({ action: 'http://www.alfajango.com', 'data-cross-domain': false }); - $('#qunit-fixture').append(''); - - $('#qunit-fixture').find('form') - .bind('ajax:beforeSend', function(e, xhr, settings) { - equal(settings.crossDomain, false, 'crossDomain should be set to false'); - // prevent request from actually getting sent off-domain - return false; - }) - .trigger('submit'); - - setTimeout(function() { start(); }, 13); -}); - })(); diff --git a/test/public/test/data-method.js b/test/public/test/data-method.js index c4426624..57528377 100644 --- a/test/public/test/data-method.js +++ b/test/public/test/data-method.js @@ -46,4 +46,30 @@ asyncTest('link "target" should be carried over to generated form', 1, function( }); }); +asyncTest('link with "data-method" and cross origin', 1, function() { + var data = {}; + + $('#qunit-fixture') + .append('') + .append(''); + + $(document).on('submit', 'form', function(e) { + $(e.currentTarget).serializeArray().map(function(item) { + data[item.name] = item.value; + }); + + return false; + }); + + var link = $('#qunit-fixture').find('a'); + + link.attr('href', 'http://www.alfajango.com'); + + link.trigger('click'); + + start(); + + notEqual(data.authenticity_token, 'cf50faa3fe97702ca1ae'); +}); + })(); diff --git a/test/public/test/override.js b/test/public/test/override.js index ba84b6dc..0dca60cc 100644 --- a/test/public/test/override.js +++ b/test/public/test/override.js @@ -32,7 +32,7 @@ asyncTest("the getter for an element's href is overridable", 1, function() { asyncTest("the getter for an element's href works normally if not overridden", 1, function() { $.rails.ajax = function(options) { - equal('/real/href', options.url); + equal(location.protocol + '//' + location.host + '/real/href', options.url); } $.rails.handleRemote($('#qunit-fixture').find('a')); start(); From c50b05ab46a655a32c0ee348576d2465e183f9de Mon Sep 17 00:00:00 2001 From: "M. Saiqul Haq" Date: Fri, 3 Apr 2015 23:43:49 +0700 Subject: [PATCH 20/69] Refactor handleMethod method Replacing old code with new method (csrfToken, and csrfParam) --- src/rails.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rails.js b/src/rails.js index 211c7226..39cf9158 100644 --- a/src/rails.js +++ b/src/rails.js @@ -181,8 +181,8 @@ var href = rails.href(link), method = link.data('method'), target = link.attr('target'), - csrfToken = $('meta[name=csrf-token]').attr('content'), - csrfParam = $('meta[name=csrf-param]').attr('content'), + csrfToken = rails.csrfToken(), + csrfParam = rails.csrfParam(), form = $('
'), metadataInput = ''; From f042bf886efc59c36fb9cdb7b878bdb6fb285600 Mon Sep 17 00:00:00 2001 From: Pier-Olivier Thibault Date: Fri, 17 Apr 2015 11:39:15 -0400 Subject: [PATCH 21/69] Links with [disabled] attribute set will not trigger AJAX --- src/rails.js | 2 +- test/public/test/data-remote.js | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/rails.js b/src/rails.js index 39cf9158..94fda15e 100644 --- a/src/rails.js +++ b/src/rails.js @@ -22,7 +22,7 @@ $.rails = rails = { // Link elements bound by jquery-ujs - linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote], a[data-disable-with], a[data-disable]', + linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote]:not([disabled]), a[data-disable-with], a[data-disable]', // Button elements bound by jquery-ujs buttonClickSelector: 'button[data-remote]:not(form button), button[data-confirm]:not(form button)', diff --git a/test/public/test/data-remote.js b/test/public/test/data-remote.js index f8c6b2a8..f678f0bb 100644 --- a/test/public/test/data-remote.js +++ b/test/public/test/data-remote.js @@ -18,6 +18,12 @@ module('data-remote', { 'data-remote': 'true', method: 'post' })) + .append($('', { + href: '/echo', + 'data-remote': 'true', + disabled: 'disabled', + text: 'Disabed link' + })) .find('form').append($('')); } @@ -84,6 +90,19 @@ asyncTest('clicking on a link with data-remote attribute', 5, function() { .trigger('click'); }); +asyncTest('clicking on a link with disabled attribute', 0, function() { + $('a[disabled]') + .bind("ajax:before", function(e, data, status, xhr) { + App.assertCallbackNotInvoked('ajax:success') + }) + .bind('ajax:complete', function() { start() }) + .trigger('click') + + setTimeout(function() { + start(); + }, 13); +}); + asyncTest('clicking on a button with data-remote attribute', 5, function() { $('button[data-remote]') .bind('ajax:success', function(e, data, status, xhr) { From 9aa01e157af0efa1b49ccc2b8f8bd350d8e629a8 Mon Sep 17 00:00:00 2001 From: Can Edremitoglu Date: Sun, 3 May 2015 04:08:15 +0200 Subject: [PATCH 22/69] change wrong filename --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 29ea432d..41d050f5 100644 --- a/README.md +++ b/README.md @@ -50,11 +50,11 @@ Run `bower install jquery-ujs --save` to install the jquery-ujs package. Usage ------------ -Require both `jquery` and `jquery-ujs` into your application.js manifest. +Require both `jquery` and `jquery_ujs` into your application.js manifest. ```javascript //= require jquery -//= require jquery-ujs +//= require jquery_ujs ``` How to run tests From 77567e773fed2ebd33f875b531589b2babe0dc37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Sun, 3 May 2015 20:28:42 -0300 Subject: [PATCH 23/69] Revert "Merge pull request #415 from cantonic/patch-1" This reverts commit ef734cc4e9fdbbdb3bb7800b327834fb02fe65bc, reversing changes made to 75f7094dc6827585e0ab19d8777b9133b69895af. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 41d050f5..29ea432d 100644 --- a/README.md +++ b/README.md @@ -50,11 +50,11 @@ Run `bower install jquery-ujs --save` to install the jquery-ujs package. Usage ------------ -Require both `jquery` and `jquery_ujs` into your application.js manifest. +Require both `jquery` and `jquery-ujs` into your application.js manifest. ```javascript //= require jquery -//= require jquery_ujs +//= require jquery-ujs ``` How to run tests From 14b5763e73eb96f3068e004c87d5579c0b89f565 Mon Sep 17 00:00:00 2001 From: Alex Ianus Date: Mon, 4 May 2015 17:09:28 -0400 Subject: [PATCH 24/69] Add test for when $.rails.confirm throws --- test/public/test/data-confirm.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/public/test/data-confirm.js b/test/public/test/data-confirm.js index da040b9a..8add713c 100644 --- a/test/public/test/data-confirm.js +++ b/test/public/test/data-confirm.js @@ -117,6 +117,27 @@ asyncTest('clicking on a button with data-confirm attribute. Confirm No.', 3, fu }, 50); }); +asyncTest('clicking on a button with data-confirm attribute. Confirm error.', 3, function() { + var message; + // auto-decline: + window.confirm = function(msg) { message = msg; throw "some random error"; }; + + $('button[data-confirm]') + .bind('confirm:complete', function(e, data) { + App.assertCallbackInvoked('confirm:complete'); + ok(data == false, 'confirm:complete passes in confirm answer (false)'); + }) + .bind('ajax:beforeSend', function(e, data, status, xhr) { + App.assertCallbackNotInvoked('ajax:beforeSend'); + }) + .trigger('click'); + + setTimeout(function() { + equal(message, 'Are you absolutely sure?'); + start(); + }, 50); +}); + asyncTest('clicking on a submit button with form and data-confirm attributes. Confirm No.', 3, function() { var message; // auto-decline: From ad97eac726cc80272324420d4ae8829e445dfd5e Mon Sep 17 00:00:00 2001 From: Alex Ianus Date: Mon, 4 May 2015 16:56:38 -0400 Subject: [PATCH 25/69] Treat exception in $.rails.confirm as a false answer --- src/rails.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/rails.js b/src/rails.js index 39cf9158..67a55003 100644 --- a/src/rails.js +++ b/src/rails.js @@ -260,7 +260,11 @@ if (!message) { return true; } if (rails.fire(element, 'confirm')) { - answer = rails.confirm(message); + try { + answer = rails.confirm(message); + } catch (e) { + (console.error || console.log).call(console, e.stack || e); + } callback = rails.fire(element, 'confirm:complete', [answer]); } return answer && callback; From 0b195730213c54c363546a309ae41d9d80d621a3 Mon Sep 17 00:00:00 2001 From: Kevin Kirsche Date: Thu, 11 Jun 2015 20:56:49 -0400 Subject: [PATCH 26/69] Remove moot `version` property from bower.json Per bower/bower.json-spec@a325da3 Also their maintainer says they probably won't ever use it: http://stackoverflow.com/questions/24844901/bowers-bower-json-file-version-property --- bower.json | 1 - 1 file changed, 1 deletion(-) diff --git a/bower.json b/bower.json index 9b5d5df6..14f93cf3 100644 --- a/bower.json +++ b/bower.json @@ -5,7 +5,6 @@ "description": "Ruby on Rails unobtrusive scripting adapter for jQuery", "main": "src/rails.js", "license": "MIT", - "version": "1.0.3", "dependencies": { "jquery": ">1.8.*" }, From 7146dc96a71fda9b713f1f60fb414c699db0b3a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 16 Jun 2015 12:58:24 -0300 Subject: [PATCH 27/69] Release 1.0.4 --- CHANGELOG.md | 8 ++++++++ bower.json | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e4116fb..2a90470c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## v1.0.4 + +* Fix CSP bypass vulnerability. + + CVE-2015-1840. + + *Rafael Mendonça França* + ## v1.0.3 * Replace deprecated `deferred.error()` with `fail()`. diff --git a/bower.json b/bower.json index 9b5d5df6..14f93cf3 100644 --- a/bower.json +++ b/bower.json @@ -5,7 +5,6 @@ "description": "Ruby on Rails unobtrusive scripting adapter for jQuery", "main": "src/rails.js", "license": "MIT", - "version": "1.0.3", "dependencies": { "jquery": ">1.8.*" }, From 86625cf5a4873330d6ced6f40befea64d76ff0f7 Mon Sep 17 00:00:00 2001 From: Alexander Kaupanin Date: Fri, 20 Sep 2013 16:11:56 +0400 Subject: [PATCH 28/69] Don't fire ajaxyness if "data-remote"="false", because `jQuery("#my_id").data("remote") === false` if input's data-remote is set to string "false" (``) --- src/rails.js | 13 +++-- test/public/test/data-remote.js | 93 +++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 4 deletions(-) diff --git a/src/rails.js b/src/rails.js index 152391bf..b8636b96 100644 --- a/src/rails.js +++ b/src/rails.js @@ -97,6 +97,11 @@ return element[0].href; }, + // Checks "data-remote" if true to handle the request through a XHR request. + isRemote: function(element) { + return element.data('remote') !== undefined && element.data('remote') !== false; + }, + // Submits "remote" forms and links with ajax handleRemote: function(element) { var method, url, data, withCredentials, dataType, options; @@ -390,7 +395,7 @@ if (!metaClick && link.is(rails.linkDisableSelector)) rails.disableElement(link); - if (link.data('remote') !== undefined) { + if (rails.isRemote(link)) { if (metaClick && (!method || method === 'GET') && !data) { return true; } var handleRemote = rails.handleRemote(link); @@ -411,7 +416,7 @@ $document.delegate(rails.buttonClickSelector, 'click.rails', function(e) { var button = $(this); - if (!rails.allowAction(button)) return rails.stopEverything(e); + if (!rails.allowAction(button) || !rails.isRemote(button)) return rails.stopEverything(e); if (button.is(rails.buttonDisableSelector)) rails.disableFormElement(button); @@ -427,7 +432,7 @@ $document.delegate(rails.inputChangeSelector, 'change.rails', function(e) { var link = $(this); - if (!rails.allowAction(link)) return rails.stopEverything(e); + if (!rails.allowAction(link) || !rails.isRemote(link)) return rails.stopEverything(e); rails.handleRemote(link); return false; @@ -435,7 +440,7 @@ $document.delegate(rails.formSubmitSelector, 'submit.rails', function(e) { var form = $(this), - remote = form.data('remote') !== undefined, + remote = rails.isRemote(form), blankRequiredInputs, nonBlankFileInputs; diff --git a/test/public/test/data-remote.js b/test/public/test/data-remote.js index f8c6b2a8..c0b47586 100644 --- a/test/public/test/data-remote.js +++ b/test/public/test/data-remote.js @@ -186,3 +186,96 @@ asyncTest('returning false in form\'s submit bindings in non-submit-bubbling bro setTimeout(function(){ start(); }, 13); }); + +asyncTest('clicking on a link with falsy "data-remote" attribute does not fire ajaxyness', 0, function() { + $('a[data-remote]') + .attr('data-remote', 'false') + .bind('ajax:beforeSend', function() { + ok(false, 'ajax should not be triggered'); + }) + .bind('click', function() { + return false; + }) + .trigger('click'); + + setTimeout(function(){ start(); }, 20); +}); + +asyncTest('ctrl-clicking on a link with falsy "data-remote" attribute does not fire ajaxyness even if "data-params" present', 0, function() { + var link = $('a[data-remote]'), e; + e = $.Event('click'); + e.metaKey = true; + + link + .removeAttr('data-params') + .attr('data-remote', 'false') + .attr('data-method', 'POST') + .bind('ajax:beforeSend', function() { + ok(false, 'ajax should not be triggered'); + }) + .bind('click', function() { + return false; + }) + .trigger(e); + + e = $.Event('click'); + e.metaKey = true; + + link + .removeAttr('data-method') + .attr('data-params', 'name=steve') + .trigger(e); + + setTimeout(function(){ start(); }, 20); +}); + +asyncTest('clicking on a button with falsy "data-remote" attribute', 0, function() { + $('button[data-remote]:first') + .attr('data-remote', 'false') + .bind('ajax:beforeSend', function() { + ok(false, 'ajax should not be triggered'); + }) + .bind('click', function() { + return false; + }) + .trigger('click'); + + setTimeout(function(){ start(); }, 20); +}); + +asyncTest('submitting a form with falsy "data-remote" attribute', 0, function() { + $('form[data-remote]:first') + .attr('data-remote', 'false') + .bind('ajax:beforeSend', function() { + ok(false, 'ajax should not be triggered'); + }) + .bind('submit', function() { + return false; + }) + .trigger('submit'); + + setTimeout(function(){ start(); }, 20); +}); + +asyncTest('changing a select option with falsy "data-remote" attribute', 0, function() { + $('form') + .append( + $('')); @@ -135,6 +136,51 @@ asyncTest('submitting form with data-remote attribute', 4, function() { .trigger('submit'); }); +asyncTest('submitting form with data-remote attribute submits input with matching [form] attribute', 5, function() { + $('#qunit-fixture') + .append($('')); + + $('form[data-remote]') + .bind('ajax:success', function(e, data, status, xhr) { + App.assertCallbackInvoked('ajax:success'); + App.assertRequestPath(data, '/echo'); + equal(data.params.user_name, 'john', 'ajax arguments should have key user_name with right value'); + equal(data.params.user_data, 'value1', 'ajax arguments should have key user_data with right value'); + App.assertPostRequest(data); + }) + .bind('ajax:complete', function() { start() }) + .trigger('submit'); +}); + +asyncTest('submitting form with data-remote attribute by clicking button with matching [form] attribute', 5, function() { + $('form[data-remote]') + .bind('ajax:success', function(e, data, status, xhr) { + App.assertCallbackInvoked('ajax:success'); + App.assertRequestPath(data, '/echo'); + equal(data.params.user_name, 'john', 'ajax arguments should have key user_name with right value'); + equal(data.params.user_data, 'value2', 'ajax arguments should have key user_data with right value'); + App.assertPostRequest(data); + }) + .bind('ajax:complete', function() { start() }); + + $(''); form.append(button); @@ -66,6 +66,7 @@ asyncTest('form button with "data-disable" attribute', 6, function() { form.trigger('submit'); App.checkDisabledState(button, 'Submit'); + equal(button.data('ujs:enable-with'), undefined); }); asyncTest('form input[type=submit][data-disable] disables', 6, function(){ @@ -132,13 +133,14 @@ asyncTest('form[data-remote] textarea[data-disable] attribute', 3, function() { App.checkDisabledState(textarea, 'born, lived, died.'); }); -asyncTest('a[data-disable] disables', 4, function() { +asyncTest('a[data-disable] disables', 5, function() { var link = $('a[data-disable]'); App.checkEnabledState(link, 'Click me'); link.trigger('click'); App.checkDisabledState(link, 'Click me'); + equal(link.data('ujs:enable-with'), undefined); start(); }); diff --git a/test/public/test/settings.js b/test/public/test/settings.js index 85a33ac1..6fbbdab3 100644 --- a/test/public/test/settings.js +++ b/test/public/test/settings.js @@ -25,7 +25,7 @@ App.getVal = function(el) { }; App.disabled = function(el) { - return el.is('input,textarea,select,button') ? el.is(':disabled') : el.data('ujs:enable-with'); + return el.is('input,textarea,select,button') ? (el.is(':disabled') && el.data('ujs:disabled')) : el.data('ujs:disabled'); }; App.checkEnabledState = function(el, text) { From 709b59b7001ef8a5d311a1c99606c5125323d0a2 Mon Sep 17 00:00:00 2001 From: "Harry V. Kiselev" Date: Mon, 7 Dec 2015 01:59:17 +0300 Subject: [PATCH 48/69] Update rails.js Add space into requiredInputSelector selector. --- src/rails.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rails.js b/src/rails.js index e9ac784e..59f35e86 100644 --- a/src/rails.js +++ b/src/rails.js @@ -45,7 +45,7 @@ enableSelector: 'input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled', // Form required input elements - requiredInputSelector: 'input[name][required]:not([disabled]),textarea[name][required]:not([disabled])', + requiredInputSelector: 'input[name][required]:not([disabled]), textarea[name][required]:not([disabled])', // Form file input elements fileInputSelector: 'input[type=file]:not([disabled])', From b9bb7f56b00043a566c43255cc98ff5791f2d5ec Mon Sep 17 00:00:00 2001 From: Jeroen Visser Date: Fri, 1 Jan 2016 02:16:15 +0100 Subject: [PATCH 49/69] Update copyright year Happy new year! --- MIT-LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MIT-LICENSE b/MIT-LICENSE index ed4c3901..9c7e3c0b 100644 --- a/MIT-LICENSE +++ b/MIT-LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2007-2015 Contributors at http://github.com/rails/jquery-ujs/contributors +Copyright (c) 2007-2016 Contributors at http://github.com/rails/jquery-ujs/contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the From 4297a15d263e6cfabe9b0fbc998c441c069db7b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 12 Jan 2016 21:07:42 -0200 Subject: [PATCH 50/69] Fix jshint warnings --- src/rails.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rails.js b/src/rails.js index d7386608..012d5092 100644 --- a/src/rails.js +++ b/src/rails.js @@ -122,8 +122,8 @@ data.push(button); element.data('ujs:submit-button', null); } - element.data('ujs:submit-button-formmethod', null) - element.data('ujs:submit-button-formaction', null) + element.data('ujs:submit-button-formmethod', null); + element.data('ujs:submit-button-formaction', null); } else if (element.is(rails.inputChangeSelector)) { method = element.data('method'); url = element.data('url'); @@ -514,7 +514,7 @@ // Save attributes from button form.data('ujs:formnovalidate-button', button.attr('formnovalidate')); - form.data('ujs:submit-button-formaction', button.attr('formaction')) + form.data('ujs:submit-button-formaction', button.attr('formaction')); form.data('ujs:submit-button-formmethod', button.attr('formmethod')); }); From b3d633fadfe4abad10e0e8a0c9454c4f30bd7dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 12 Jan 2016 21:07:51 -0200 Subject: [PATCH 51/69] Test with jQuery 1.12.0 and 2.2.0 --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 21eb4736..98158148 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,8 +15,10 @@ env: - JQUERY_VERSION: 1.11.0 - JQUERY_VERSION: 1.11.1 - JQUERY_VERSION: 1.11.2 + - JQUERY_VERSION: 1.12.0 - JQUERY_VERSION: 2.0.0 - JQUERY_VERSION: 2.1.0 - JQUERY_VERSION: 2.1.1 - JQUERY_VERSION: 2.1.2 - JQUERY_VERSION: 2.1.3 + - JQUERY_VERSION: 2.2.0 From 20fde22d4960c2aea11711f4f8ca4209b2685ccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 12 Jan 2016 21:14:05 -0200 Subject: [PATCH 52/69] Use new build infrastructure --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 98158148..5d25a09a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,7 @@ language: ruby +sudo: false +cache: + - bundler script: ./script/cibuild before_install: - "npm install jshint -g" From 15515b20722b955224db00caffaa8f28ac845875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 12 Jan 2016 21:16:53 -0200 Subject: [PATCH 53/69] Add npm to the travis cache --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 5d25a09a..7e6cb080 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,8 @@ language: ruby sudo: false cache: - bundler + - directories: + - $HOME/.npm script: ./script/cibuild before_install: - "npm install jshint -g" From 6f6c1e73e441c1fa6a10da7363acbfe7704aa4f1 Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sun, 14 Feb 2016 23:11:55 -0800 Subject: [PATCH 54/69] Update CONTRIBUTING.md --- CONTRIBUTING.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 64e6864d..6827438d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,12 +27,11 @@ git checkout -b my-feature-branch #### Bundle Install and Test -Ensure that you can build the project and run tests. Run rake test first, and then run the web tests. Visit [[http://localhost:4567]] in your browser. Click the version links at the top right of the page to run the test suite with the different supported versions of jQuery. +Ensure that you can build the project and run tests. Run `rake test:server` first, and then run the web tests by visiting [[http://localhost:4567]] in your browser. Click the version links at the top right of the page to run the test suite with the different supported versions of jQuery. ``` bundle install -rake test -ruby test/server.rb +rake test:server ``` #### Write Tests From e1a87651b8c1fcfefd0a347e47ee8742d7f45533 Mon Sep 17 00:00:00 2001 From: Achilleas Buisman Date: Mon, 22 Feb 2016 12:14:00 +0100 Subject: [PATCH 55/69] Prevent fieldsets from resulting in double data entries --- src/rails.js | 2 +- test/public/test/data-remote.js | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/rails.js b/src/rails.js index 012d5092..b51db23e 100644 --- a/src/rails.js +++ b/src/rails.js @@ -115,7 +115,7 @@ if (element.is('form')) { method = element.data('ujs:submit-button-formmethod') || element.attr('method'); url = element.data('ujs:submit-button-formaction') || element.attr('action'); - data = $(element[0].elements).serializeArray(); + data = $(element[0]).serializeArray(); // memoized value from clicked submit button var button = element.data('ujs:submit-button'); if (button) { diff --git a/test/public/test/data-remote.js b/test/public/test/data-remote.js index d4dc0955..e751c8e0 100644 --- a/test/public/test/data-remote.js +++ b/test/public/test/data-remote.js @@ -155,6 +155,21 @@ asyncTest('submitting form with data-remote attribute', 4, function() { .trigger('submit'); }); +asyncTest('submitting form with data-remote attribute should include inputs in a fieldset only once', 3, function() { + $('form[data-remote]') + .append('
') + .bind('ajax:success', function(e, data, status, xhr) { + App.assertCallbackInvoked('ajax:success'); + equal(data.params.items.length, 1, 'ajax arguments should only have the item once') + App.assertPostRequest(data); + }) + .bind('ajax:complete', function() { + $('form[data-remote], fieldset').remove() + start() + }) + .trigger('submit'); +}); + asyncTest('submitting form with data-remote attribute submits input with matching [form] attribute', 5, function() { $('#qunit-fixture') .append($('')); From 0fa8410cbf6b78c0bcb0652c4cffc74a44a7a4fd Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Wed, 10 Feb 2016 23:15:36 -0800 Subject: [PATCH 56/69] Bug where one radio button in group required The HTML spec does not seemd to clearly state what "required" does when only some of a radio button set are required. This answer on StackOverflow states that only one of the set is required: http://stackoverflow.com/a/8287947/1009332 Per the comments added in the fix: We cannot just compare allInputs for radio buttons, as the spec for required radio buttons states that only one of a radio button set needs to be required. If you have 2 radio buttons, and one is checked, but it's not required, then we get the other required radio button and see that there are no other radio buttons checked for the "required" ones. Thus, if the input control is a radio button, then filter for all radio buttons with the same name on the form. This will get all radio buttons of a given name that are checked and see that at least one is checked. Don't count unchecked required radio if other radio with same name is checked. But do count checked non-required radio of the same name. Note, each radio button name that is required is checked only once. --- src/rails.js | 47 ++++++++++++++++------- test/public/test/call-remote-callbacks.js | 29 +++++++++++++- 2 files changed, 61 insertions(+), 15 deletions(-) diff --git a/src/rails.js b/src/rails.js index 012d5092..86cfee1e 100644 --- a/src/rails.js +++ b/src/rails.js @@ -309,24 +309,45 @@ // Helper function which checks for blank inputs in a form that match the specified CSS selector blankInputs: function(form, specifiedSelector, nonBlank) { - var inputs = $(), input, valueToCheck, - selector = specifiedSelector || 'input,textarea', - allInputs = form.find(selector); - - allInputs.each(function() { + var foundInputs = $(), + input, + valueToCheck, + radiosForNameWithNoneSelected, + radioName, + selector = specifiedSelector || 'input,textarea', + requiredInputs = form.find(selector), + checkedRadioButtonNames = {}; + + requiredInputs.each(function() { input = $(this); - valueToCheck = input.is('input[type=checkbox],input[type=radio]') ? input.is(':checked') : !!input.val(); - if (valueToCheck === nonBlank) { + if (input.is('input[type=radio]')) { - // Don't count unchecked required radio if other radio with same name is checked - if (input.is('input[type=radio]') && allInputs.filter('input[type=radio]:checked[name="' + input.attr('name') + '"]').length) { - return true; // Skip to next input - } + // Don't count unchecked required radio as blank if other radio with same name is checked, + // regardless of whether same-name radio input has required attribute or not. The spec + // states https://www.w3.org/TR/html5/forms.html#the-required-attribute + radioName = input.attr('name'); + + // Skip if we've already seen the radio with this name. + if (!checkedRadioButtonNames[radioName]) { + + // If none checked + if (form.find('input[type=radio]:checked[name="' + radioName + '"]').length === 0) { + radiosForNameWithNoneSelected = form.find( + 'input[type=radio][name="' + radioName + '"]'); + foundInputs = foundInputs.add(radiosForNameWithNoneSelected); + } - inputs = inputs.add(input); + // We only need to check each name once. + checkedRadioButtonNames[radioName] = radioName; + } + } else { + valueToCheck = input.is('input[type=checkbox],input[type=radio]') ? input.is(':checked') : !!input.val(); + if (valueToCheck === nonBlank) { + foundInputs = foundInputs.add(input); + } } }); - return inputs.length ? inputs : false; + return foundInputs.length ? foundInputs : false; }, // Helper function which checks for non-blank inputs in a form that match the specified CSS selector diff --git a/test/public/test/call-remote-callbacks.js b/test/public/test/call-remote-callbacks.js index beee0a0c..11acaf18 100644 --- a/test/public/test/call-remote-callbacks.js +++ b/test/public/test/call-remote-callbacks.js @@ -241,8 +241,8 @@ asyncTest('unchecked required checkbox should abort form submission', 1, functio asyncTest('unchecked required radio should abort form submission', 1, function() { var form = $('form[data-remote]') - .append($('')) - .append($('')) + .append($('')) + .append($('')) .removeAttr('data-remote') .bind('ujs:everythingStopped', function() { ok(true, 'ujs:everythingStopped should run'); @@ -275,6 +275,31 @@ asyncTest('required radio should only require one to be checked', 1, function() }, 13); }); +asyncTest('required radio should only require one to be checked if not all radios are required', 1, function() { + $(document).bind('iframe:loading', function() { + ok(true, 'form should get submitted'); + }); + + var form = $('form[data-remote]') + // Check the radio that is not required + .append($('')) + // Check the radio that is not required + .append($('')) + // Only one needs to be required + .append($('')) + .removeAttr('data-remote') + .bind('ujs:everythingStopped', function() { + ok(false, 'ujs:everythingStopped should not run'); + }) + .find('#checkme').prop('checked', true) + .end() + .trigger('submit'); + + setTimeout(function() { + start(); + }, 13); +}); + function skipIt() { // This test cannot work due to the security feature in browsers which makes the value // attribute of file input fields readonly, so it cannot be set with default value. From 627913fc067399c26e5663fbd0a1719fc196af6b Mon Sep 17 00:00:00 2001 From: Mason Hale Date: Sun, 6 Mar 2016 10:32:37 -0600 Subject: [PATCH 57/69] Ignore file input fields without name attribute.\nThis is important to provide compatibility with the refile file upload ruby gem.\nSee: https://github.com/refile/refile/issues/58 --- src/rails.js | 2 +- test/public/test/call-remote-callbacks.js | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/rails.js b/src/rails.js index bc9fceb3..9e192a2e 100644 --- a/src/rails.js +++ b/src/rails.js @@ -48,7 +48,7 @@ requiredInputSelector: 'input[name][required]:not([disabled]), textarea[name][required]:not([disabled])', // Form file input elements - fileInputSelector: 'input[type=file]:not([disabled])', + fileInputSelector: 'input[name][type=file]:not([disabled])', // Link onClick disable selector with possible reenable after remote submission linkDisableSelector: 'a[data-disable-with], a[data-disable]', diff --git a/test/public/test/call-remote-callbacks.js b/test/public/test/call-remote-callbacks.js index 11acaf18..e7ee0dab 100644 --- a/test/public/test/call-remote-callbacks.js +++ b/test/public/test/call-remote-callbacks.js @@ -327,6 +327,27 @@ function skipIt() { }, 13); }); + asyncTest('file form input field should not abort remote request if file form input does not have a name attribute', 5, function() { + var form = $('form[data-remote]') + .append($('')) + .bind('ajax:beforeSend', function() { + ok(true, 'ajax:beforeSend should run'); + }) + .bind('iframe:loading', function() { + ok(true, 'form should get submitted'); + }) + .bind('ajax:aborted:file', function(e,data) { + ok(false, 'ajax:aborted:file should not run'); + }) + .trigger('submit'); + + setTimeout(function() { + form.find('input[type="file"]').val(''); + form.unbind('ajax:beforeSend'); + submit(); + }, 13); + }); + asyncTest('blank file input field should abort request entirely if handler bound to "ajax:aborted:file" event that returns false', 1, function() { var form = $('form[data-remote]') .append($('')) From f6471b2d8117de8939b656c0b5e5222d448fbfef Mon Sep 17 00:00:00 2001 From: Evgeniy Sukhanov Date: Wed, 15 Jun 2016 20:49:40 +0500 Subject: [PATCH 58/69] ready for jQuery 3 --- src/rails.js | 18 +++++++++--------- test/server.rb | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/rails.js b/src/rails.js index 9e192a2e..1370a65c 100644 --- a/src/rails.js +++ b/src/rails.js @@ -416,15 +416,15 @@ }); }); - $document.delegate(rails.linkDisableSelector, 'ajax:complete', function() { + $document.on('ajax:complete', rails.linkDisableSelector, function() { rails.enableElement($(this)); }); - $document.delegate(rails.buttonDisableSelector, 'ajax:complete', function() { + $document.on('ajax:complete', rails.buttonDisableSelector, function() { rails.enableFormElement($(this)); }); - $document.delegate(rails.linkClickSelector, 'click.rails', function(e) { + $document.on('click.rails', rails.linkClickSelector, function(e) { var link = $(this), method = link.data('method'), data = link.data('params'), metaClick = e.metaKey || e.ctrlKey; if (!rails.allowAction(link)) return rails.stopEverything(e); @@ -448,7 +448,7 @@ } }); - $document.delegate(rails.buttonClickSelector, 'click.rails', function(e) { + $document.on('click.rails', rails.buttonClickSelector, function(e) { var button = $(this); if (!rails.allowAction(button) || !rails.isRemote(button)) return rails.stopEverything(e); @@ -465,7 +465,7 @@ return false; }); - $document.delegate(rails.inputChangeSelector, 'change.rails', function(e) { + $document.on('change.rails', rails.inputChangeSelector, function(e) { var link = $(this); if (!rails.allowAction(link) || !rails.isRemote(link)) return rails.stopEverything(e); @@ -473,7 +473,7 @@ return false; }); - $document.delegate(rails.formSubmitSelector, 'submit.rails', function(e) { + $document.on('submit.rails', rails.formSubmitSelector, function(e) { var form = $(this), remote = rails.isRemote(form), blankRequiredInputs, @@ -518,7 +518,7 @@ } }); - $document.delegate(rails.formInputClickSelector, 'click.rails', function(event) { + $document.on('click.rails', rails.formInputClickSelector, function(event) { var button = $(this); if (!rails.allowAction(button)) return rails.stopEverything(event); @@ -539,11 +539,11 @@ form.data('ujs:submit-button-formmethod', button.attr('formmethod')); }); - $document.delegate(rails.formSubmitSelector, 'ajax:send.rails', function(event) { + $document.on('ajax:send.rails', rails.formSubmitSelector, function(event) { if (this === event.target) rails.disableFormElements($(this)); }); - $document.delegate(rails.formSubmitSelector, 'ajax:complete.rails', function(event) { + $document.on('ajax:complete.rails', rails.formSubmitSelector, function(event) { if (this === event.target) rails.enableFormElements($(this)); }); diff --git a/test/server.rb b/test/server.rb index 85f11db2..db94368a 100644 --- a/test/server.rb +++ b/test/server.rb @@ -1,7 +1,7 @@ require 'sinatra' require 'json' -JQUERY_VERSIONS = %w[ 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 1.11.0 2.0.0 2.1.0].freeze +JQUERY_VERSIONS = %w[ 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 1.11.0 2.0.0 2.1.0 3.0.0].freeze use Rack::Static, :urls => ["/src"], :root => File.expand_path('..', settings.root) From baccefdb5674d0d8964f3c93f5265a7d2db3a601 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Wed, 3 Aug 2016 04:59:25 -0300 Subject: [PATCH 59/69] Add package.json to release jquery-ujs in npm. --- package.json | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 00000000..fcebfa56 --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "jquery-ujs", + "version": "1.2.1", + "description": "Unobtrusive scripting adapter for jQuery", + "main": "src/rails.js", + "directories": { + "test": "test" + }, + "scripts": { + "test": "echo \"See the wiki: https://github.com/rails/jquery-ujs/wiki/Running-Tests-and-Contributing\" && exit 1", + "postversion": "git push && git push --tags && npm publish" + }, + "repository": { + "type": "git", + "url": "https://github.com/rails/jquery-ujs.git" + }, + "author": [ + "Stephen St. Martin", + "Steve Schwartz" + ], + "license": "MIT", + "bugs": { + "url": "https://github.com/rails/jquery-ujs/issues" + }, + "homepage": "https://github.com/rails/jquery-ujs#readme", + "dependencies": { + "jquery": ">=1.8.0" + } +} From 26c9c77fb6f769fbfd7d321319c5780be2f90872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Wed, 3 Aug 2016 05:23:39 -0300 Subject: [PATCH 60/69] Add instructions about npm --- README.md | 5 +++++ RELEASE.md | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 RELEASE.md diff --git a/README.md b/README.md index a9fd2ab4..df6aee68 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,11 @@ Require both `jquery` and `jquery_ujs` into your application.js manifest. //= require jquery_ujs ``` +Installation using npm. +------------ + +Run `npm install --save jquery-ujs` to install the jquery-ujs package. + Installation using Bower ------------ diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 00000000..59316f77 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,23 @@ +## Releasing jquery-ujs + +### Releasing to npm + +Make sure npm's configuration `sign-git-tag` is set to true. + +``` +npm config set sign-git-tag true +``` + +Release it to npm using the [npm version command](https://docs.npmjs.com/cli/version). Like: + +``` +npm version patch +``` + +This will: + +* Bump a patch version +* Commit the change +* Generate the tag +* Push the commit and the tag to the repository +* Publish the package in https://www.npmjs.com From 33ba167d25f4e3ff696d7fec39fea24935811b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Fri, 19 Aug 2016 13:20:32 -0300 Subject: [PATCH 61/69] Ignore Ruby files in the npm generated package --- .npmignore | 4 ++++ package.json | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 .npmignore diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..3af83847 --- /dev/null +++ b/.npmignore @@ -0,0 +1,4 @@ +script/ +test/ +Rakefile +Gemfile* diff --git a/package.json b/package.json index fcebfa56..67ca7a12 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,6 @@ "version": "1.2.1", "description": "Unobtrusive scripting adapter for jQuery", "main": "src/rails.js", - "directories": { - "test": "test" - }, "scripts": { "test": "echo \"See the wiki: https://github.com/rails/jquery-ujs/wiki/Running-Tests-and-Contributing\" && exit 1", "postversion": "git push && git push --tags && npm publish" From a4da3b4909b2ca081de3c6f99064403623bfe1fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Fri, 19 Aug 2016 13:26:52 -0300 Subject: [PATCH 62/69] 1.2.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 67ca7a12..08a5a245 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jquery-ujs", - "version": "1.2.1", + "version": "1.2.2", "description": "Unobtrusive scripting adapter for jQuery", "main": "src/rails.js", "scripts": { From 267b70d8a15514b084627aac6facd5bbdca8dd20 Mon Sep 17 00:00:00 2001 From: Sergey Date: Fri, 30 Dec 2016 14:08:12 +0800 Subject: [PATCH 63/69] Allow to init Jquery UJS manually --- src/rails.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/rails.js b/src/rails.js index 1370a65c..e5f581fd 100644 --- a/src/rails.js +++ b/src/rails.js @@ -1,4 +1,4 @@ -(function($, undefined) { +/* jshint node: true */ /** * Unobtrusive scripting adapter for jQuery @@ -10,10 +10,13 @@ * */ - // Cut down on the number of issues from people inadvertently including jquery_ujs twice - // by detecting and raising an error when it happens. +(function() { 'use strict'; + var jqueryUjsInit = function($, undefined) { + + // Cut down on the number of issues from people inadvertently including jquery_ujs twice + // by detecting and raising an error when it happens. if ( $.rails !== undefined ) { $.error('jquery-ujs has already been loaded!'); } @@ -552,4 +555,11 @@ }); } -})( jQuery ); + }; + + if (window.jQuery) { + jqueryUjsInit(jQuery); + } else if (typeof exports === 'object' && typeof module === 'object') { + module.exports = jqueryUjsInit; + } +})(); From 3bff9e049afcb38191c6eb470062b9e51f46e535 Mon Sep 17 00:00:00 2001 From: aki Date: Fri, 14 Apr 2017 15:19:59 +0900 Subject: [PATCH 64/69] Use jQuery.fn.on instead of jQuery.fn.bind --- src/rails.js | 4 +- test/public/test/call-remote-callbacks.js | 114 +++++++++++----------- test/public/test/call-remote.js | 18 ++-- test/public/test/data-confirm.js | 40 ++++---- test/public/test/data-disable-with.js | 44 ++++----- test/public/test/data-disable.js | 38 ++++---- test/public/test/data-method.js | 4 +- test/public/test/data-remote.js | 64 ++++++------ test/public/test/settings.js | 2 +- test/views/layout.erb | 2 +- 10 files changed, 165 insertions(+), 165 deletions(-) diff --git a/src/rails.js b/src/rails.js index 1370a65c..7eee3906 100644 --- a/src/rails.js +++ b/src/rails.js @@ -372,7 +372,7 @@ element.html(replacement); } - element.bind('click.railsDisable', function(e) { // prevent further clicking + element.on('click.railsDisable', function(e) { // prevent further clicking return rails.stopEverything(e); }); element.data('ujs:disabled', true); @@ -384,7 +384,7 @@ element.html(element.data('ujs:enable-with')); // set to old enabled state element.removeData('ujs:enable-with'); // clean up cache } - element.unbind('click.railsDisable'); // enable element + element.off('click.railsDisable'); // enable element element.removeData('ujs:disabled'); } }; diff --git a/test/public/test/call-remote-callbacks.js b/test/public/test/call-remote-callbacks.js index e7ee0dab..35926202 100644 --- a/test/public/test/call-remote-callbacks.js +++ b/test/public/test/call-remote-callbacks.js @@ -12,13 +12,13 @@ module('call-remote-callbacks', { $(document).undelegate('form[data-remote]', 'ajax:send'); $(document).undelegate('form[data-remote]', 'ajax:complete'); $(document).undelegate('form[data-remote]', 'ajax:success'); - $(document).unbind('ajaxStop'); - $(document).unbind('iframe:loading'); + $(document).off('ajaxStop'); + $(document).off('iframe:loading'); } }); function start_after_submit(form) { - form.bind('ajax:complete', function() { + form.on('ajax:complete', function() { ok(true, 'ajax:complete'); start(); }); @@ -43,7 +43,7 @@ asyncTest('modifying form fields with "ajax:before" sends modified data in reque $('form[data-remote]') .append($('')) .append($('')) - .bind('ajax:before', function() { + .on('ajax:before', function() { var form = $(this); form .append($('',{name: 'other_user_name',value: 'jonathan'})) @@ -53,7 +53,7 @@ asyncTest('modifying form fields with "ajax:before" sends modified data in reque }); submit(function(form) { - form.bind('ajax:success', function(e, data, status, xhr) { + form.on('ajax:success', function(e, data, status, xhr) { equal(data.params.user_name, 'steve', 'modified field value should have been submitted'); equal(data.params.other_user_name, 'jonathan', 'added field value should have been submitted'); equal(data.params.removed_user_name, undefined, 'removed field value should be undefined'); @@ -63,13 +63,13 @@ asyncTest('modifying form fields with "ajax:before" sends modified data in reque asyncTest('modifying data("type") with "ajax:before" requests new dataType in request', 2, function(){ $('form[data-remote]').data('type','html') - .bind('ajax:before', function() { + .on('ajax:before', function() { var form = $(this); form.data('type','xml'); }); submit(function(form) { - form.bind('ajax:beforeSend', function(e, xhr, settings) { + form.on('ajax:beforeSend', function(e, xhr, settings) { equal(settings.dataType, 'xml', 'modified dataType should have been requested'); }); }); @@ -77,13 +77,13 @@ asyncTest('modifying data("type") with "ajax:before" requests new dataType in re asyncTest('setting data("with-credentials",true) with "ajax:before" uses new setting in request', 2, function(){ $('form[data-remote]').data('with-credentials',false) - .bind('ajax:before', function() { + .on('ajax:before', function() { var form = $(this); form.data('with-credentials',true); }); submit(function(form) { - form.bind('ajax:beforeSend', function(e, xhr, settings) { + form.on('ajax:beforeSend', function(e, xhr, settings) { equal(settings.xhrFields && settings.xhrFields.withCredentials, true, 'setting modified in ajax:before should have forced withCredentials request'); }); }); @@ -91,37 +91,37 @@ asyncTest('setting data("with-credentials",true) with "ajax:before" uses new set asyncTest('stopping the "ajax:beforeSend" event aborts the request', 1, function() { submit(function(form) { - form.bind('ajax:beforeSend', function() { + form.on('ajax:beforeSend', function() { ok(true, 'aborting request in ajax:beforeSend'); return false; }); - form.unbind('ajax:send').bind('ajax:send', function() { + form.off('ajax:send').on('ajax:send', function() { ok(false, 'ajax:send should not run'); }); - form.unbind('ajax:complete').bind('ajax:complete', function() { + form.off('ajax:complete').on('ajax:complete', function() { ok(false, 'ajax:complete should not run'); }); - form.bind('ajax:error', function(e, xhr, status, error) { + form.on('ajax:error', function(e, xhr, status, error) { ok(false, 'ajax:error should not run'); }); - $(document).bind('ajaxStop', function() { + $(document).on('ajaxStop', function() { start(); }); }); }); asyncTest('blank required form input field should abort request and trigger "ajax:aborted:required" event', 5, function() { - $(document).bind('iframe:loading', function() { + $(document).on('iframe:loading', function() { ok(false, 'form should not get submitted'); }); var form = $('form[data-remote]') .append($('')) .append($('')) - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { ok(false, 'ajax:beforeSend should not run'); }) - .bind('ajax:aborted:required', function(e,data){ + .on('ajax:aborted:required', function(e,data){ ok(data.length == 2, 'ajax:aborted:required event is passed all blank required inputs (jQuery objects)'); ok(data.first().is('input[name="user_name"]') , 'ajax:aborted:required adds blank required input to data'); ok(data.last().is('textarea[name="user_bio"]'), 'ajax:aborted:required adds blank required textarea to data'); @@ -131,7 +131,7 @@ asyncTest('blank required form input field should abort request and trigger "aja setTimeout(function() { form.find('input[required],textarea[required]').val('Tyler'); - form.unbind('ajax:beforeSend'); + form.off('ajax:beforeSend'); submit(); }, 13); }); @@ -140,7 +140,7 @@ asyncTest('blank required form input for non-remote form should abort normal sub var form = $('form[data-remote]') .append($('')) .removeAttr('data-remote') - .bind('ujs:everythingStopped', function() { + .on('ujs:everythingStopped', function() { ok(true, 'ujs:everythingStopped should run'); }) .trigger('submit'); @@ -153,10 +153,10 @@ asyncTest('blank required form input for non-remote form should abort normal sub asyncTest('form should be submitted with blank required fields if handler is bound to "ajax:aborted:required" event that returns false', 1, function(){ var form = $('form[data-remote]') .append($('')) - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { ok(true, 'ajax:beforeSend should run'); }) - .bind('ajax:aborted:required', function() { + .on('ajax:aborted:required', function() { return false; }) .trigger('submit'); @@ -170,10 +170,10 @@ asyncTest('disabled fields should not be included in blank required check', 2, f var form = $('form[data-remote]') .append($('')) .append($('')) - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { ok(true, 'ajax:beforeSend should run'); }) - .bind('ajax:aborted:required', function() { + .on('ajax:aborted:required', function() { ok(false, 'ajax:aborted:required should not run'); }); @@ -184,10 +184,10 @@ asyncTest('form should be submitted with blank required fields if it has the "no var form = $('form[data-remote]') .append($('')) .attr("novalidate", "novalidate") - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { ok(true, 'ajax:beforeSend should run'); }) - .bind('ajax:aborted:required', function() { + .on('ajax:aborted:required', function() { ok(false, 'ajax:aborted:required should not run'); }); @@ -199,10 +199,10 @@ asyncTest('form should be submitted with blank required fields if the button has var form = $('form[data-remote]') .append($('')) .append(submit_button) - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { ok(true, 'ajax:beforeSend should run'); }) - .bind('ajax:aborted:required', function() { + .on('ajax:aborted:required', function() { ok(false, 'ajax:aborted:required should not run'); }); @@ -210,7 +210,7 @@ asyncTest('form should be submitted with blank required fields if the button has }); asyncTest('blank required form input for non-remote form with "novalidate" attribute should not abort normal submission', 1, function() { - $(document).bind('iframe:loading', function() { + $(document).on('iframe:loading', function() { ok(true, 'form should get submitted'); }); @@ -229,7 +229,7 @@ asyncTest('unchecked required checkbox should abort form submission', 1, functio var form = $('form[data-remote]') .append($('')) .removeAttr('data-remote') - .bind('ujs:everythingStopped', function() { + .on('ujs:everythingStopped', function() { ok(true, 'ujs:everythingStopped should run'); }) .trigger('submit'); @@ -244,7 +244,7 @@ asyncTest('unchecked required radio should abort form submission', 1, function() .append($('')) .append($('')) .removeAttr('data-remote') - .bind('ujs:everythingStopped', function() { + .on('ujs:everythingStopped', function() { ok(true, 'ujs:everythingStopped should run'); }) .trigger('submit'); @@ -255,7 +255,7 @@ asyncTest('unchecked required radio should abort form submission', 1, function() }); asyncTest('required radio should only require one to be checked', 1, function() { - $(document).bind('iframe:loading', function() { + $(document).on('iframe:loading', function() { ok(true, 'form should get submitted'); }); @@ -263,7 +263,7 @@ asyncTest('required radio should only require one to be checked', 1, function() .append($('')) .append($('')) .removeAttr('data-remote') - .bind('ujs:everythingStopped', function() { + .on('ujs:everythingStopped', function() { ok(false, 'ujs:everythingStopped should not run'); }) .find('#checkme').prop('checked', true) @@ -276,7 +276,7 @@ asyncTest('required radio should only require one to be checked', 1, function() }); asyncTest('required radio should only require one to be checked if not all radios are required', 1, function() { - $(document).bind('iframe:loading', function() { + $(document).on('iframe:loading', function() { ok(true, 'form should get submitted'); }); @@ -288,7 +288,7 @@ asyncTest('required radio should only require one to be checked if not all radio // Only one needs to be required .append($('')) .removeAttr('data-remote') - .bind('ujs:everythingStopped', function() { + .on('ujs:everythingStopped', function() { ok(false, 'ujs:everythingStopped should not run'); }) .find('#checkme').prop('checked', true) @@ -307,13 +307,13 @@ function skipIt() { asyncTest('non-blank file form input field should abort remote request, but submit normally', 5, function() { var form = $('form[data-remote]') .append($('')) - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { ok(false, 'ajax:beforeSend should not run'); }) - .bind('iframe:loading', function() { + .on('iframe:loading', function() { ok(true, 'form should get submitted'); }) - .bind('ajax:aborted:file', function(e,data) { + .on('ajax:aborted:file', function(e,data) { ok(data.length == 1, 'ajax:aborted:file event is passed all non-blank file inputs (jQuery objects)'); ok(data.first().is('input[name="attachment"]') , 'ajax:aborted:file adds non-blank file input to data'); ok(true, 'ajax:aborted:file event should run'); @@ -322,7 +322,7 @@ function skipIt() { setTimeout(function() { form.find('input[type="file"]').val(''); - form.unbind('ajax:beforeSend'); + form.off('ajax:beforeSend'); submit(); }, 13); }); @@ -330,20 +330,20 @@ function skipIt() { asyncTest('file form input field should not abort remote request if file form input does not have a name attribute', 5, function() { var form = $('form[data-remote]') .append($('')) - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { ok(true, 'ajax:beforeSend should run'); }) - .bind('iframe:loading', function() { + .on('iframe:loading', function() { ok(true, 'form should get submitted'); }) - .bind('ajax:aborted:file', function(e,data) { + .on('ajax:aborted:file', function(e,data) { ok(false, 'ajax:aborted:file should not run'); }) .trigger('submit'); setTimeout(function() { form.find('input[type="file"]').val(''); - form.unbind('ajax:beforeSend'); + form.off('ajax:beforeSend'); submit(); }, 13); }); @@ -351,20 +351,20 @@ function skipIt() { asyncTest('blank file input field should abort request entirely if handler bound to "ajax:aborted:file" event that returns false', 1, function() { var form = $('form[data-remote]') .append($('')) - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { ok(false, 'ajax:beforeSend should not run'); }) - .bind('iframe:loading', function() { + .on('iframe:loading', function() { ok(false, 'form should not get submitted'); }) - .bind('ajax:aborted:file', function() { + .on('ajax:aborted:file', function() { return false; }) .trigger('submit'); setTimeout(function() { form.find('input[type="file"]').val(''); - form.unbind('ajax:beforeSend'); + form.off('ajax:beforeSend'); submit(); }, 13); }); @@ -377,13 +377,13 @@ asyncTest('"ajax:beforeSend" can be observed and stopped with event delegation', }); submit(function(form) { - form.unbind('ajax:send').bind('ajax:send', function() { + form.off('ajax:send').on('ajax:send', function() { ok(false, 'ajax:send should not run'); }); - form.unbind('ajax:complete').bind('ajax:complete', function() { + form.off('ajax:complete').on('ajax:complete', function() { ok(false, 'ajax:complete should not run'); }); - $(document).bind('ajaxStop', function() { + $(document).on('ajaxStop', function() { start(); }); }); @@ -391,19 +391,19 @@ asyncTest('"ajax:beforeSend" can be observed and stopped with event delegation', asyncTest('"ajax:beforeSend", "ajax:send", "ajax:success" and "ajax:complete" are triggered', 9, function() { submit(function(form) { - form.bind('ajax:beforeSend', function(e, xhr, settings) { + form.on('ajax:beforeSend', function(e, xhr, settings) { ok(xhr.setRequestHeader, 'first argument to "ajax:beforeSend" should be an XHR object'); equal(settings.url, '/echo', 'second argument to "ajax:beforeSend" should be a settings object'); }); - form.bind('ajax:send', function(e, xhr) { + form.on('ajax:send', function(e, xhr) { ok(xhr.abort, 'first argument to "ajax:send" should be an XHR object'); }); - form.bind('ajax:success', function(e, data, status, xhr) { + form.on('ajax:success', function(e, data, status, xhr) { ok(data.REQUEST_METHOD, 'first argument to ajax:success should be a data object'); equal(status, 'success', 'second argument to ajax:success should be a status string'); ok(xhr.getResponseHeader, 'third argument to "ajax:success" should be an XHR object'); }); - form.bind('ajax:complete', function(e, xhr, status) { + form.on('ajax:complete', function(e, xhr, status) { ok(xhr.getResponseHeader, 'first argument to "ajax:complete" should be an XHR object'); equal(status, 'success', 'second argument to ajax:complete should be a status string'); }); @@ -414,9 +414,9 @@ if(window.phantom !== undefined) { asyncTest('"ajax:beforeSend", "ajax:send", "ajax:error" and "ajax:complete" are triggered on error', 7, function() { submit(function(form) { form.attr('action', '/error'); - form.bind('ajax:beforeSend', function(arg) { ok(true, 'ajax:beforeSend') }); - form.bind('ajax:send', function(arg) { ok(true, 'ajax:send') }); - form.bind('ajax:error', function(e, xhr, status, error) { + form.on('ajax:beforeSend', function(arg) { ok(true, 'ajax:beforeSend') }); + form.on('ajax:send', function(arg) { ok(true, 'ajax:send') }); + form.on('ajax:error', function(e, xhr, status, error) { ok(xhr.getResponseHeader, 'first argument to "ajax:error" should be an XHR object'); equal(status, 'error', 'second argument to ajax:error should be a status string'); // Firefox 8 returns "Forbidden " with trailing space @@ -452,7 +452,7 @@ asyncTest('binding to ajax callbacks via .delegate() triggers handlers properly' asyncTest('binding to ajax:send event to call jquery methods on ajax object', 2, function() { $('form[data-remote]') - .bind('ajax:send', function(e, xhr) { + .on('ajax:send', function(e, xhr) { ok(true, 'event should fire'); equal(typeof(xhr.abort), 'function', 'event should pass jqXHR object'); xhr.abort(); diff --git a/test/public/test/call-remote.js b/test/public/test/call-remote.js index 2a6e3a61..0d9214a0 100644 --- a/test/public/test/call-remote.js +++ b/test/public/test/call-remote.js @@ -11,8 +11,8 @@ module('call-remote'); function submit(fn) { $('form') - .bind('ajax:success', fn) - .bind('ajax:complete', function() { start() }) + .on('ajax:success', fn) + .on('ajax:complete', function() { start() }) .trigger('submit'); } @@ -37,10 +37,10 @@ asyncTest('form method is read from submit button "formmethod" if submit is trig buildForm({ method: 'post' }); $('#qunit-fixture').find('form').append(submitButton) - .bind('ajax:success', function(e, data, status, xhr) { + .on('ajax:success', function(e, data, status, xhr) { App.assertGetRequest(data); }) - .bind('ajax:complete', function() { start() }); + .on('ajax:complete', function() { start() }); submitButton.trigger('click'); }); @@ -74,10 +74,10 @@ asyncTest('form url is read from submit button "formaction" if submit is trigger buildForm({ method: 'post', href: '/echo2' }); $('#qunit-fixture').find('form').append(submitButton) - .bind('ajax:success', function(e, data, status, xhr) { + .on('ajax:success', function(e, data, status, xhr) { App.assertRequestPath(data, '/echo'); }) - .bind('ajax:complete', function() { start() }); + .on('ajax:complete', function() { start() }); submitButton.trigger('click'); }); @@ -113,7 +113,7 @@ asyncTest('allow empty form "action"', 1, function() { buildForm({ action: '' }); $('#qunit-fixture').find('form') - .bind('ajax:beforeSend', function(e, xhr, settings) { + .on('ajax:beforeSend', function(e, xhr, settings) { // Get current location (the same way jQuery does) try { currentLocation = location.href; @@ -155,7 +155,7 @@ asyncTest('intelligently guesses crossDomain behavior when target URL has a diff $('#qunit-fixture').append(''); $('#qunit-fixture').find('form') - .bind('ajax:beforeSend', function(e, xhr, settings) { + .on('ajax:beforeSend', function(e, xhr, settings) { equal(settings.crossDomain, true, 'crossDomain should be set to true'); @@ -174,7 +174,7 @@ asyncTest('intelligently guesses crossDomain behavior when target URL consists o $('#qunit-fixture').append(''); $('#qunit-fixture').find('form') - .bind('ajax:beforeSend', function(e, xhr, settings) { + .on('ajax:beforeSend', function(e, xhr, settings) { equal(settings.crossDomain, false, 'crossDomain should be set to false'); diff --git a/test/public/test/data-confirm.js b/test/public/test/data-confirm.js index 8add713c..2e905d42 100644 --- a/test/public/test/data-confirm.js +++ b/test/public/test/data-confirm.js @@ -39,11 +39,11 @@ asyncTest('clicking on a link with data-confirm attribute. Confirm yes.', 6, fun window.confirm = function(msg) { message = msg; return true }; $('a[data-confirm]') - .bind('confirm:complete', function(e, data) { + .on('confirm:complete', function(e, data) { App.assertCallbackInvoked('confirm:complete'); ok(data == true, 'confirm:complete passes in confirm answer (true)'); }) - .bind('ajax:success', function(e, data, status, xhr) { + .on('ajax:success', function(e, data, status, xhr) { App.assertCallbackInvoked('ajax:success'); App.assertRequestPath(data, '/echo'); App.assertGetRequest(data); @@ -60,11 +60,11 @@ asyncTest('clicking on a button with data-confirm attribute. Confirm yes.', 6, f window.confirm = function(msg) { message = msg; return true }; $('button[data-confirm]') - .bind('confirm:complete', function(e, data) { + .on('confirm:complete', function(e, data) { App.assertCallbackInvoked('confirm:complete'); ok(data == true, 'confirm:complete passes in confirm answer (true)'); }) - .bind('ajax:success', function(e, data, status, xhr) { + .on('ajax:success', function(e, data, status, xhr) { App.assertCallbackInvoked('ajax:success'); App.assertRequestPath(data, '/echo'); App.assertGetRequest(data); @@ -81,11 +81,11 @@ asyncTest('clicking on a link with data-confirm attribute. Confirm No.', 3, func window.confirm = function(msg) { message = msg; return false }; $('a[data-confirm]') - .bind('confirm:complete', function(e, data) { + .on('confirm:complete', function(e, data) { App.assertCallbackInvoked('confirm:complete'); ok(data == false, 'confirm:complete passes in confirm answer (false)'); }) - .bind('ajax:beforeSend', function(e, data, status, xhr) { + .on('ajax:beforeSend', function(e, data, status, xhr) { App.assertCallbackNotInvoked('ajax:beforeSend'); }) .trigger('click'); @@ -102,11 +102,11 @@ asyncTest('clicking on a button with data-confirm attribute. Confirm No.', 3, fu window.confirm = function(msg) { message = msg; return false }; $('button[data-confirm]') - .bind('confirm:complete', function(e, data) { + .on('confirm:complete', function(e, data) { App.assertCallbackInvoked('confirm:complete'); ok(data == false, 'confirm:complete passes in confirm answer (false)'); }) - .bind('ajax:beforeSend', function(e, data, status, xhr) { + .on('ajax:beforeSend', function(e, data, status, xhr) { App.assertCallbackNotInvoked('ajax:beforeSend'); }) .trigger('click'); @@ -123,11 +123,11 @@ asyncTest('clicking on a button with data-confirm attribute. Confirm error.', 3, window.confirm = function(msg) { message = msg; throw "some random error"; }; $('button[data-confirm]') - .bind('confirm:complete', function(e, data) { + .on('confirm:complete', function(e, data) { App.assertCallbackInvoked('confirm:complete'); ok(data == false, 'confirm:complete passes in confirm answer (false)'); }) - .bind('ajax:beforeSend', function(e, data, status, xhr) { + .on('ajax:beforeSend', function(e, data, status, xhr) { App.assertCallbackNotInvoked('ajax:beforeSend'); }) .trigger('click'); @@ -144,11 +144,11 @@ asyncTest('clicking on a submit button with form and data-confirm attributes. Co window.confirm = function(msg) { message = msg; return false }; $('input[type=submit][form]') - .bind('confirm:complete', function(e, data) { + .on('confirm:complete', function(e, data) { App.assertCallbackInvoked('confirm:complete'); ok(data == false, 'confirm:complete passes in confirm answer (false)'); }) - .bind('ajax:beforeSend', function(e, data, status, xhr) { + .on('ajax:beforeSend', function(e, data, status, xhr) { App.assertCallbackNotInvoked('ajax:beforeSend'); }) .trigger('click'); @@ -166,11 +166,11 @@ asyncTest('binding to confirm event of a link and returning false', 1, function( }; $('a[data-confirm]') - .bind('confirm', function() { + .on('confirm', function() { App.assertCallbackInvoked('confirm'); return false; }) - .bind('confirm:complete', function() { + .on('confirm:complete', function() { App.assertCallbackNotInvoked('confirm:complete'); }) .trigger('click'); @@ -187,11 +187,11 @@ asyncTest('binding to confirm event of a button and returning false', 1, functio }; $('button[data-confirm]') - .bind('confirm', function() { + .on('confirm', function() { App.assertCallbackInvoked('confirm'); return false; }) - .bind('confirm:complete', function() { + .on('confirm:complete', function() { App.assertCallbackNotInvoked('confirm:complete'); }) .trigger('click'); @@ -209,11 +209,11 @@ asyncTest('binding to confirm:complete event of a link and returning false', 2, }; $('a[data-confirm]') - .bind('confirm:complete', function() { + .on('confirm:complete', function() { App.assertCallbackInvoked('confirm:complete'); return false; }) - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { App.assertCallbackNotInvoked('ajax:beforeSend'); }) .trigger('click'); @@ -231,11 +231,11 @@ asyncTest('binding to confirm:complete event of a button and returning false', 2 }; $('button[data-confirm]') - .bind('confirm:complete', function() { + .on('confirm:complete', function() { App.assertCallbackInvoked('confirm:complete'); return false; }) - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { App.assertCallbackNotInvoked('ajax:beforeSend'); }) .trigger('click'); diff --git a/test/public/test/data-disable-with.js b/test/public/test/data-disable-with.js index 0366f81e..1bb67426 100644 --- a/test/public/test/data-disable-with.js +++ b/test/public/test/data-disable-with.js @@ -40,7 +40,7 @@ module('data-disable-with', { })); }, teardown: function() { - $(document).unbind('iframe:loaded'); + $(document).off('iframe:loaded'); } }); @@ -49,7 +49,7 @@ asyncTest('form input field with "data-disable-with" attribute', 7, function() { App.checkEnabledState(input, 'john'); - form.bind('ajax:success', function(e, data) { + form.on('ajax:success', function(e, data) { setTimeout(function() { App.checkEnabledState(input, 'john'); equal(data.params.user_name, 'john'); @@ -67,7 +67,7 @@ asyncTest('blank form input field with "data-disable-with" attribute', 7, functi input.val(''); App.checkEnabledState(input, ''); - form.bind('ajax:success', function(e, data) { + form.on('ajax:success', function(e, data) { setTimeout(function() { App.checkEnabledState(input, ''); equal(data.params.user_name, ''); @@ -85,7 +85,7 @@ asyncTest('form button with "data-disable-with" attribute', 6, function() { App.checkEnabledState(button, 'Submit'); - form.bind('ajax:success', function(e, data) { + form.on('ajax:success', function(e, data) { setTimeout(function() { App.checkEnabledState(button, 'Submit'); start(); @@ -102,9 +102,9 @@ asyncTest('form input[type=submit][data-disable-with] disables', 6, function(){ App.checkEnabledState(input, 'Submit'); // WEEIRDD: attaching this handler makes the test work in IE7 - $(document).bind('iframe:loading', function(e, form) {}); + $(document).on('iframe:loading', function(e, form) {}); - $(document).bind('iframe:loaded', function(e, data) { + $(document).on('iframe:loaded', function(e, data) { setTimeout(function() { App.checkDisabledState(input, 'submitting ...'); start(); @@ -138,7 +138,7 @@ test('form input[type=submit][data-disable-with] re-enables when `pageshow` even asyncTest('form[data-remote] input[type=submit][data-disable-with] is replaced in ajax callback', 2, function(){ var form = $('form:not([data-remote])').attr('data-remote', 'true'), origFormContents = form.html(); - form.bind('ajax:success', function(){ + form.on('ajax:success', function(){ form.html(origFormContents); setTimeout(function(){ @@ -153,7 +153,7 @@ asyncTest('form[data-remote] input[data-disable-with] is replaced with disabled var form = $('form:not([data-remote])').attr('data-remote', 'true'), input = form.find('input[type=submit]'), newDisabledInput = input.clone().attr('disabled', 'disabled'); - form.bind('ajax:success', function(){ + form.on('ajax:success', function(){ input.replaceWith(newDisabledInput); setTimeout(function(){ @@ -168,9 +168,9 @@ asyncTest('form input[type=submit][data-disable-with] using "form" attribute dis App.checkEnabledState(input, 'Form Attr Submit'); // WEEIRDD: attaching this handler makes the test work in IE7 - $(document).bind('iframe:loading', function(e, form) {}); + $(document).on('iframe:loading', function(e, form) {}); - $(document).bind('iframe:loaded', function(e, data) { + $(document).on('iframe:loaded', function(e, data) { setTimeout(function() { App.checkDisabledState(input, 'form attr submitting'); start(); @@ -188,7 +188,7 @@ asyncTest('form[data-remote] textarea[data-disable-with] attribute', 3, function var form = $('form[data-remote]'), textarea = $('').appendTo(form); - form.bind('ajax:success', function(e, data) { + form.on('ajax:success', function(e, data) { setTimeout(function() { equal(data.params.user_bio, 'born, lived, died.'); start(); @@ -227,10 +227,10 @@ asyncTest('a[data-remote][data-disable-with] disables and re-enables', 6, functi App.checkEnabledState(link, 'Click me'); link - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { App.checkDisabledState(link, 'clicking...'); }) - .bind('ajax:complete', function() { + .on('ajax:complete', function() { setTimeout( function() { App.checkEnabledState(link, 'Click me'); start(); @@ -245,7 +245,7 @@ asyncTest('a[data-remote][data-disable-with] re-enables when `ajax:before` event App.checkEnabledState(link, 'Click me'); link - .bind('ajax:before', function() { + .on('ajax:before', function() { App.checkDisabledState(link, 'clicking...'); return false; }) @@ -263,7 +263,7 @@ asyncTest('a[data-remote][data-disable-with] re-enables when `ajax:beforeSend` e App.checkEnabledState(link, 'Click me'); link - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { App.checkDisabledState(link, 'clicking...'); return false; }) @@ -281,7 +281,7 @@ asyncTest('a[data-remote][data-disable-with] re-enables when `ajax:error` event App.checkEnabledState(link, 'Click me'); link - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { App.checkDisabledState(link, 'clicking...'); }) .trigger('click'); @@ -300,7 +300,7 @@ asyncTest('form[data-remote] input|button|textarea[data-disable-with] does not d submit = $('').appendTo(form); form - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { return false; }) .trigger('submit'); @@ -337,10 +337,10 @@ asyncTest('button[data-remote][data-disable-with] disables and re-enables', 6, f App.checkEnabledState(button, 'Click me'); button - .bind('ajax:send', function() { + .on('ajax:send', function() { App.checkDisabledState(button, 'clicking...'); }) - .bind('ajax:complete', function() { + .on('ajax:complete', function() { setTimeout( function() { App.checkEnabledState(button, 'Click me'); start(); @@ -355,7 +355,7 @@ asyncTest('button[data-remote][data-disable-with] re-enables when `ajax:before` App.checkEnabledState(button, 'Click me'); button - .bind('ajax:before', function() { + .on('ajax:before', function() { App.checkDisabledState(button, 'clicking...'); return false; }) @@ -373,7 +373,7 @@ asyncTest('button[data-remote][data-disable-with] re-enables when `ajax:beforeSe App.checkEnabledState(button, 'Click me'); button - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { App.checkDisabledState(button, 'clicking...'); return false; }) @@ -391,7 +391,7 @@ asyncTest('button[data-remote][data-disable-with] re-enables when `ajax:error` e App.checkEnabledState(button, 'Click me'); button - .bind('ajax:send', function() { + .on('ajax:send', function() { App.checkDisabledState(button, 'clicking...'); }) .trigger('click'); diff --git a/test/public/test/data-disable.js b/test/public/test/data-disable.js index 3df1bb9c..ed30b0ec 100644 --- a/test/public/test/data-disable.js +++ b/test/public/test/data-disable.js @@ -30,7 +30,7 @@ module('data-disable', { })); }, teardown: function() { - $(document).unbind('iframe:loaded'); + $(document).off('iframe:loaded'); } }); @@ -39,7 +39,7 @@ asyncTest('form input field with "data-disable" attribute', 7, function() { App.checkEnabledState(input, 'john'); - form.bind('ajax:success', function(e, data) { + form.on('ajax:success', function(e, data) { setTimeout(function() { App.checkEnabledState(input, 'john'); equal(data.params.user_name, 'john'); @@ -57,7 +57,7 @@ asyncTest('form button with "data-disable" attribute', 7, function() { App.checkEnabledState(button, 'Submit'); - form.bind('ajax:success', function(e, data) { + form.on('ajax:success', function(e, data) { setTimeout(function() { App.checkEnabledState(button, 'Submit'); start(); @@ -75,9 +75,9 @@ asyncTest('form input[type=submit][data-disable] disables', 6, function(){ App.checkEnabledState(input, 'Submit'); // WEEIRDD: attaching this handler makes the test work in IE7 - $(document).bind('iframe:loading', function(e, form) {}); + $(document).on('iframe:loading', function(e, form) {}); - $(document).bind('iframe:loaded', function(e, data) { + $(document).on('iframe:loaded', function(e, data) { setTimeout(function() { App.checkDisabledState(input, 'Submit'); start(); @@ -93,7 +93,7 @@ asyncTest('form input[type=submit][data-disable] disables', 6, function(){ asyncTest('form[data-remote] input[type=submit][data-disable] is replaced in ajax callback', 2, function(){ var form = $('form:not([data-remote])').attr('data-remote', 'true'), origFormContents = form.html(); - form.bind('ajax:success', function(){ + form.on('ajax:success', function(){ form.html(origFormContents); setTimeout(function(){ @@ -108,7 +108,7 @@ asyncTest('form[data-remote] input[data-disable] is replaced with disabled field var form = $('form:not([data-remote])').attr('data-remote', 'true'), input = form.find('input[type=submit]'), newDisabledInput = input.clone().attr('disabled', 'disabled'); - form.bind('ajax:success', function(){ + form.on('ajax:success', function(){ input.replaceWith(newDisabledInput); setTimeout(function(){ @@ -122,7 +122,7 @@ asyncTest('form[data-remote] textarea[data-disable] attribute', 3, function() { var form = $('form[data-remote]'), textarea = $('').appendTo(form); - form.bind('ajax:success', function(e, data) { + form.on('ajax:success', function(e, data) { setTimeout(function() { equal(data.params.user_bio, 'born, lived, died.'); start(); @@ -150,10 +150,10 @@ asyncTest('a[data-remote][data-disable] disables and re-enables', 6, function() App.checkEnabledState(link, 'Click me'); link - .bind('ajax:send', function() { + .on('ajax:send', function() { App.checkDisabledState(link, 'Click me'); }) - .bind('ajax:complete', function() { + .on('ajax:complete', function() { setTimeout( function() { App.checkEnabledState(link, 'Click me'); start(); @@ -168,7 +168,7 @@ asyncTest('a[data-remote][data-disable] re-enables when `ajax:before` event is c App.checkEnabledState(link, 'Click me'); link - .bind('ajax:before', function() { + .on('ajax:before', function() { App.checkDisabledState(link, 'Click me'); return false; }) @@ -186,7 +186,7 @@ asyncTest('a[data-remote][data-disable] re-enables when `ajax:beforeSend` event App.checkEnabledState(link, 'Click me'); link - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { App.checkDisabledState(link, 'Click me'); return false; }) @@ -204,7 +204,7 @@ asyncTest('a[data-remote][data-disable] re-enables when `ajax:error` event is tr App.checkEnabledState(link, 'Click me'); link - .bind('ajax:send', function() { + .on('ajax:send', function() { App.checkDisabledState(link, 'Click me'); }) .trigger('click'); @@ -223,7 +223,7 @@ asyncTest('form[data-remote] input|button|textarea[data-disable] does not disabl submit = $('').appendTo(form); form - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { return false; }) .trigger('submit'); @@ -260,10 +260,10 @@ asyncTest('button[data-remote][data-disable] disables and re-enables', 6, functi App.checkEnabledState(button, 'Click me'); button - .bind('ajax:send', function() { + .on('ajax:send', function() { App.checkDisabledState(button, 'Click me'); }) - .bind('ajax:complete', function() { + .on('ajax:complete', function() { setTimeout( function() { App.checkEnabledState(button, 'Click me'); start(); @@ -278,7 +278,7 @@ asyncTest('button[data-remote][data-disable] re-enables when `ajax:before` event App.checkEnabledState(button, 'Click me'); button - .bind('ajax:before', function() { + .on('ajax:before', function() { App.checkDisabledState(button, 'Click me'); return false; }) @@ -296,7 +296,7 @@ asyncTest('button[data-remote][data-disable] re-enables when `ajax:beforeSend` e App.checkEnabledState(button, 'Click me'); button - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { App.checkDisabledState(button, 'Click me'); return false; }) @@ -314,7 +314,7 @@ asyncTest('button[data-remote][data-disable] re-enables when `ajax:error` event App.checkEnabledState(button, 'Click me'); button - .bind('ajax:send', function() { + .on('ajax:send', function() { App.checkDisabledState(button, 'Click me'); }) .trigger('click'); diff --git a/test/public/test/data-method.js b/test/public/test/data-method.js index 57528377..32b90d70 100644 --- a/test/public/test/data-method.js +++ b/test/public/test/data-method.js @@ -7,12 +7,12 @@ module('data-method', { })); }, teardown: function() { - $(document).unbind('iframe:loaded'); + $(document).off('iframe:loaded'); } }); function submit(fn, options) { - $(document).bind('iframe:loaded', function(e, data) { + $(document).on('iframe:loaded', function(e, data) { fn(data); start(); }); diff --git a/test/public/test/data-remote.js b/test/public/test/data-remote.js index e751c8e0..215d8217 100644 --- a/test/public/test/data-remote.js +++ b/test/public/test/data-remote.js @@ -39,7 +39,7 @@ asyncTest('ctrl-clicking on a link does not fire ajaxyness', 0, function() { // follow links using `trigger('click')`, it only fires bindings. link .removeAttr('data-params') - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { ok(false, 'ajax should not be triggered'); }); @@ -62,7 +62,7 @@ asyncTest('ctrl-clicking on a link still fires ajax for non-GET links and for li link .removeAttr('data-params') .attr('data-method', 'POST') - .bind('ajax:beforeSend', function() { + .on('ajax:beforeSend', function() { ok(true, 'ajax should be triggered'); }) .trigger(e); @@ -80,23 +80,23 @@ asyncTest('ctrl-clicking on a link still fires ajax for non-GET links and for li asyncTest('clicking on a link with data-remote attribute', 5, function() { $('a[data-remote]') - .bind('ajax:success', function(e, data, status, xhr) { + .on('ajax:success', function(e, data, status, xhr) { App.assertCallbackInvoked('ajax:success'); App.assertRequestPath(data, '/echo'); equal(data.params.data1, 'value1', 'ajax arguments should have key data1 with right value'); equal(data.params.data2, 'value2', 'ajax arguments should have key data2 with right value'); App.assertGetRequest(data); }) - .bind('ajax:complete', function() { start() }) + .on('ajax:complete', function() { start() }) .trigger('click'); }); asyncTest('clicking on a link with disabled attribute', 0, function() { $('a[disabled]') - .bind("ajax:before", function(e, data, status, xhr) { + .on("ajax:before", function(e, data, status, xhr) { App.assertCallbackNotInvoked('ajax:success') }) - .bind('ajax:complete', function() { start() }) + .on('ajax:complete', function() { start() }) .trigger('click') setTimeout(function() { @@ -106,14 +106,14 @@ asyncTest('clicking on a link with disabled attribute', 0, function() { asyncTest('clicking on a button with data-remote attribute', 5, function() { $('button[data-remote]') - .bind('ajax:success', function(e, data, status, xhr) { + .on('ajax:success', function(e, data, status, xhr) { App.assertCallbackInvoked('ajax:success'); App.assertRequestPath(data, '/echo'); equal(data.params.data1, 'value1', 'ajax arguments should have key data1 with right value'); equal(data.params.data2, 'value2', 'ajax arguments should have key data2 with right value'); App.assertGetRequest(data); }) - .bind('ajax:complete', function() { start() }) + .on('ajax:complete', function() { start() }) .trigger('click'); }); @@ -131,39 +131,39 @@ asyncTest('changing a select option with data-remote attribute', 5, function() { ); $('select[data-remote]') - .bind('ajax:success', function(e, data, status, xhr) { + .on('ajax:success', function(e, data, status, xhr) { App.assertCallbackInvoked('ajax:success'); App.assertRequestPath(data, '/echo'); equal(data.params.user_data, 'optionValue2', 'ajax arguments should have key term with right value'); equal(data.params.data1, 'value1', 'ajax arguments should have key data1 with right value'); App.assertGetRequest(data); }) - .bind('ajax:complete', function() { start() }) + .on('ajax:complete', function() { start() }) .val('optionValue2') .trigger('change'); }); asyncTest('submitting form with data-remote attribute', 4, function() { $('form[data-remote]') - .bind('ajax:success', function(e, data, status, xhr) { + .on('ajax:success', function(e, data, status, xhr) { App.assertCallbackInvoked('ajax:success'); App.assertRequestPath(data, '/echo'); equal(data.params.user_name, 'john', 'ajax arguments should have key user_name with right value'); App.assertPostRequest(data); }) - .bind('ajax:complete', function() { start() }) + .on('ajax:complete', function() { start() }) .trigger('submit'); }); asyncTest('submitting form with data-remote attribute should include inputs in a fieldset only once', 3, function() { $('form[data-remote]') .append('
') - .bind('ajax:success', function(e, data, status, xhr) { + .on('ajax:success', function(e, data, status, xhr) { App.assertCallbackInvoked('ajax:success'); equal(data.params.items.length, 1, 'ajax arguments should only have the item once') App.assertPostRequest(data); }) - .bind('ajax:complete', function() { + .on('ajax:complete', function() { $('form[data-remote], fieldset').remove() start() }) @@ -175,27 +175,27 @@ asyncTest('submitting form with data-remote attribute submits input with matchin .append($('')); $('form[data-remote]') - .bind('ajax:success', function(e, data, status, xhr) { + .on('ajax:success', function(e, data, status, xhr) { App.assertCallbackInvoked('ajax:success'); App.assertRequestPath(data, '/echo'); equal(data.params.user_name, 'john', 'ajax arguments should have key user_name with right value'); equal(data.params.user_data, 'value1', 'ajax arguments should have key user_data with right value'); App.assertPostRequest(data); }) - .bind('ajax:complete', function() { start() }) + .on('ajax:complete', function() { start() }) .trigger('submit'); }); asyncTest('submitting form with data-remote attribute by clicking button with matching [form] attribute', 5, function() { $('form[data-remote]') - .bind('ajax:success', function(e, data, status, xhr) { + .on('ajax:success', function(e, data, status, xhr) { App.assertCallbackInvoked('ajax:success'); App.assertRequestPath(data, '/echo'); equal(data.params.user_name, 'john', 'ajax arguments should have key user_name with right value'); equal(data.params.user_data, 'value2', 'ajax arguments should have key user_data with right value'); App.assertPostRequest(data); }) - .bind('ajax:complete', function() { start() }); + .on('ajax:complete', function() { start() }); $('