From 8fc44057482460793052d8ff2e0ccb74448dd702 Mon Sep 17 00:00:00 2001 From: Krzysztof Kotlarski Date: Fri, 5 Dec 2014 14:29:53 +0100 Subject: [PATCH 01/37] 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 f042bf886efc59c36fb9cdb7b878bdb6fb285600 Mon Sep 17 00:00:00 2001 From: Pier-Olivier Thibault Date: Fri, 17 Apr 2015 11:39:15 -0400 Subject: [PATCH 02/37] 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 5c1fe589dc1fff9f45c70a001e4bbdfea47baf60 Mon Sep 17 00:00:00 2001 From: Leif Gustafson Date: Mon, 29 Jun 2015 18:22:09 -0800 Subject: [PATCH 03/37] Fix for #426 along with tests --- src/rails.js | 11 +++++++---- test/public/test/call-remote.js | 23 +++++++++++++++++++++-- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/rails.js b/src/rails.js index b8636b96..65f8add0 100644 --- a/src/rails.js +++ b/src/rails.js @@ -189,10 +189,13 @@ // 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); + // If URL protocol *and* host are false, assume it is not a + // cross-domain request (should only be the case for IE7 and IE + // compatibility mode). Otherwise, evaluate protocol and host of the + // URL against the origin protocol and host + 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; diff --git a/test/public/test/call-remote.js b/test/public/test/call-remote.js index 94316e88..a93bfc4b 100644 --- a/test/public/test/call-remote.js +++ b/test/public/test/call-remote.js @@ -122,10 +122,10 @@ asyncTest('sends CSRF token in custom header', 1, function() { }); }); -asyncTest('intelligently guesses crossDomain behavior when target URL is a different domain', 1, function(e, xhr) { +asyncTest('intelligently guesses crossDomain behavior when target URL has a protocol and hostname', 1, function(e, xhr) { // Don't set data-cross-domain here, just set action to be a different domain than localhost - buildForm({ action: 'http://www.alfajango.com' }); + buildForm({ action: 'http://www.alfajango.com/' }); $('#qunit-fixture').append(''); $('#qunit-fixture').find('form') @@ -140,4 +140,23 @@ asyncTest('intelligently guesses crossDomain behavior when target URL is a diffe setTimeout(function() { start(); }, 13); }); + +asyncTest('intelligently guesses crossDomain behavior when target URL consists of only a path', 1, function(e, xhr) { + + // Don't set data-cross-domain here, just set action to be a different domain than localhost + buildForm({ action: '/just/a/path' }); + $('#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); +}); })(); From d41edc8abf90a3132c85c6b494135810c02f126c Mon Sep 17 00:00:00 2001 From: Leif Gustafson Date: Mon, 29 Jun 2015 18:25:52 -0800 Subject: [PATCH 04/37] Update wording of test --- test/public/test/call-remote.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/public/test/call-remote.js b/test/public/test/call-remote.js index a93bfc4b..80d801c5 100644 --- a/test/public/test/call-remote.js +++ b/test/public/test/call-remote.js @@ -122,7 +122,7 @@ asyncTest('sends CSRF token in custom header', 1, function() { }); }); -asyncTest('intelligently guesses crossDomain behavior when target URL has a protocol and hostname', 1, function(e, xhr) { +asyncTest('intelligently guesses crossDomain behavior when target URL has a different protocol and/or hostname', 1, function(e, xhr) { // Don't set data-cross-domain here, just set action to be a different domain than localhost buildForm({ action: 'http://www.alfajango.com/' }); From 4f2d946d2fa34b41f4c4b58682117c2985962c97 Mon Sep 17 00:00:00 2001 From: lulalala Date: Sat, 4 Jul 2015 00:02:19 +0800 Subject: [PATCH 05/37] Ignore disabled file input Disabled file input form should be ignored, however currently submitting a form with disabled file input will cause issue on Rails' side. --- src/rails.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rails.js b/src/rails.js index 2dc31e30..90d50bd4 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]', + fileInputSelector: 'input[type=file]:not([disabled])', // Link onClick disable selector with possible reenable after remote submission linkDisableSelector: 'a[data-disable-with], a[data-disable]', From c7e5f8f59db7e37410610658b7c3f1652fc01cbb Mon Sep 17 00:00:00 2001 From: Jens Balvig Date: Thu, 9 Jul 2015 09:41:39 +0200 Subject: [PATCH 06/37] Disabled blank inputs didn't reset on ajax submit Submitting a remote form with a blank input using [data-disable-with] would cause the disable-with message to get stuck since if("") == false --- src/rails.js | 2 +- test/public/test/data-disable-with.js | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/rails.js b/src/rails.js index 2dc31e30..7feda212 100644 --- a/src/rails.js +++ b/src/rails.js @@ -266,7 +266,7 @@ enableFormElement: function(element) { var method = element.is('button') ? 'html' : 'val'; - if (element.data('ujs:enable-with')) element[method](element.data('ujs:enable-with')); + if (typeof element.data('ujs:enable-with') !== 'undefined') element[method](element.data('ujs:enable-with')); element.prop('disabled', false); }, diff --git a/test/public/test/data-disable-with.js b/test/public/test/data-disable-with.js index 5e2a67da..0366f81e 100644 --- a/test/public/test/data-disable-with.js +++ b/test/public/test/data-disable-with.js @@ -61,6 +61,24 @@ asyncTest('form input field with "data-disable-with" attribute', 7, function() { App.checkDisabledState(input, 'processing ...'); }); +asyncTest('blank form input field with "data-disable-with" attribute', 7, function() { + var form = $('form[data-remote]'), input = form.find('input[type=text]'); + + input.val(''); + App.checkEnabledState(input, ''); + + form.bind('ajax:success', function(e, data) { + setTimeout(function() { + App.checkEnabledState(input, ''); + equal(data.params.user_name, ''); + start(); + }, 13); + }); + form.trigger('submit'); + + App.checkDisabledState(input, 'processing ...'); +}); + asyncTest('form button with "data-disable-with" attribute', 6, function() { var form = $('form[data-remote]'), button = $(''); form.append(button); From 3d58ddddba7222786a65b99e945980adfa648dd1 Mon Sep 17 00:00:00 2001 From: Leif Gustafson Date: Thu, 30 Jul 2015 14:17:15 -0800 Subject: [PATCH 07/37] Additional cross-domain fixes related to IE8 in compatibility mode (thanks to @dankohn and @blargoner) --- src/rails.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/rails.js b/src/rails.js index 65f8add0..4ffdf10a 100644 --- a/src/rails.js +++ b/src/rails.js @@ -189,11 +189,12 @@ // This is a workaround to a IE bug. urlAnchor.href = urlAnchor.href; - // If URL protocol *and* host are false, assume it is not a - // cross-domain request (should only be the case for IE7 and IE - // compatibility mode). Otherwise, evaluate protocol and host of the - // URL against the origin protocol and host - return !((!urlAnchor.protocol && !urlAnchor.host) || + // If URL protocol is false or is a string containing a single colon + // *and* host are false, assume it is not a cross-domain request + // (should only be the case for IE7 and IE compatibility mode). + // Otherwise, evaluate protocol and host of the URL against the origin + // protocol and host + return !(((!urlAnchor.protocol || urlAnchor.protocol === ':') && !urlAnchor.host) || (originAnchor.protocol + "//" + originAnchor.host === urlAnchor.protocol + "//" + urlAnchor.host)); } catch (e) { From e228a365686d5f1358c28feec8d81325cf45fa8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 1 Sep 2015 02:21:56 -0300 Subject: [PATCH 08/37] Release 1.1.0 --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a90470c..028ef2fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## v1.1.0 + +* Extract `$.rails.csrfToken` and `$.rails.csrfParam` functions to allow external usage. + +* Treat exception in `$.rails.confirm` as a false answer. + +* Don't fire Ajax requests if `data-remote` is `false`. + +* Fix IE7 bug with the cross domain check. + +* Ignore disabled file inputs when submitting the form. + ## v1.0.4 * Fix CSP bypass vulnerability. From 32bb07042b051d372fd12e3149896abfc513d9c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 1 Sep 2015 02:24:12 -0300 Subject: [PATCH 09/37] Remove CHANGELOG We are using GitHub releases now. --- CHANGELOG.md | 44 -------------------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 028ef2fa..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,44 +0,0 @@ -## v1.1.0 - -* Extract `$.rails.csrfToken` and `$.rails.csrfParam` functions to allow external usage. - -* Treat exception in `$.rails.confirm` as a false answer. - -* Don't fire Ajax requests if `data-remote` is `false`. - -* Fix IE7 bug with the cross domain check. - -* Ignore disabled file inputs when submitting the form. - -## v1.0.4 - -* Fix CSP bypass vulnerability. - - CVE-2015-1840. - - *Rafael Mendonça França* - -## 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. - - *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 b516178a9edd3d16eb5549ad57bce62909266ed2 Mon Sep 17 00:00:00 2001 From: maclover7 Date: Tue, 1 Sep 2015 12:08:59 -0400 Subject: [PATCH 10/37] Add CONTRIBUTING.md [ci skip] --- CONTRIBUTING.md | 110 +++++++++++++++++++++++++++++++++ MIT-LICENSE.txt => MIT-LICENSE | 2 +- README.md | 11 +++- 3 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 CONTRIBUTING.md rename MIT-LICENSE.txt => MIT-LICENSE (94%) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..64e6864d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,110 @@ +Contributing to jquery-ujs +===================== + +[![Build Status](https://travis-ci.org/rails/jquery-ujs.svg?branch=master)](https://travis-ci.org/rails/jquery-ujs) + +jquery-ujs is work of [many contributors](https://github.com/rails/jquery-ujs/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/rails/jquery-ujs/pulls), [propose features and discuss issues](https://github.com/rails/jquery-ujs/issues). + +#### Fork the Project + +Fork the [project on Github](https://github.com/rails/jquery-ujs) and check out your copy. + +``` +git clone https://github.com/contributor/jquery-ujs.git +cd jquery-ujs +git remote add upstream https://github.com/rails/jquery-ujs.git +``` + +#### Create a Topic Branch + +Make sure your fork is up-to-date and create a topic branch for your feature or bug fix. + +``` +git checkout master +git pull upstream master +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. + +``` +bundle install +rake test +ruby test/server.rb +``` + +#### Write Tests + +Try to write a test that reproduces the problem you're trying to fix or describes a feature that you want to build. Add to [test](test). + +Here are some additional notes to keep in mind when developing your patch for jquery-ujs. + +* The tests can be found in: +``` + |~test + |~public + |~test +``` +* Some tests ensure consistent behavior across the major browsers, meaning it is possible for tests to pass in Firefox, but fail in Internet Explorer. If possible, it helps if you can run the test suite in multiple browsers before submitting patches. + +We definitely appreciate pull requests that highlight or reproduce a problem, even without a fix. + +#### Write Code + +Implement your feature or bug fix. + +Make sure that `bundle exec rake test` completes without errors. + +#### Write Documentation + +Document any external behavior in the [README](README.md). + +#### Commit Changes + +Make sure git knows your name and email address: + +``` +git config --global user.name "Your Name" +git config --global user.email "contributor@example.com" +``` + +Writing good commit logs is important. A commit log should describe what changed and why. + +``` +git add ... +git commit +``` + +#### Push + +``` +git push origin my-feature-branch +``` + +#### Make a Pull Request + +Go to https://github.com/contributor/jquery-ujs and select your feature branch. Click the 'Pull Request' button and fill out the form. Pull requests are usually reviewed within a few days. + +#### Rebase + +If you've been working on a change for a while, rebase with upstream/master. + +``` +git fetch upstream +git rebase upstream/master +git push origin my-feature-branch -f +``` + +#### Check on Your Pull Request + +Go back to your pull request after a few minutes and see whether it passed muster with Travis-CI. Everything should look green, otherwise fix issues and amend your commit as described above. + +#### Be Patient + +It's likely that your change will not be merged and that the nitpicky maintainers will ask you to do more, or fix seemingly benign problems. Hang on there! + +#### Thank You + +Please do know that we really appreciate and value your time and work. We love you, really. diff --git a/MIT-LICENSE.txt b/MIT-LICENSE similarity index 94% rename from MIT-LICENSE.txt rename to MIT-LICENSE index ed37a233..ed4c3901 100644 --- a/MIT-LICENSE.txt +++ b/MIT-LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2007-2010 Contributors at http://github.com/rails/jquery-ujs/contributors +Copyright (c) 2007-2015 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 diff --git a/README.md b/README.md index 29ea432d..a9fd2ab4 100644 --- a/README.md +++ b/README.md @@ -60,8 +60,17 @@ Require both `jquery` and `jquery-ujs` into your application.js manifest. How to run tests ------------ -Follow [this wiki](https://github.com/rails/jquery-ujs/wiki/Running-Tests-and-Contributing) to run tests . +Follow [this wiki](https://github.com/rails/jquery-ujs/wiki/Running-Tests-and-Contributing) to run tests. +## Contributing to jquery-ujs + +jquery-ujs is work of many contributors. You're encouraged to submit pull requests, propose +features and discuss issues. + +See [CONTRIBUTING](CONTRIBUTING.md). + +## License +jquery-ujs is released under the [MIT License](MIT-LICENSE). [data]: http://www.w3.org/TR/html5/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes "Embedding custom non-visible data with the data-* attributes" [wiki]: https://github.com/rails/jquery-ujs/wiki From 2830202d52dc073c8b6c2337755ad4ffbcbe8bf2 Mon Sep 17 00:00:00 2001 From: Andy Lampert Date: Mon, 14 Sep 2015 19:10:04 -0600 Subject: [PATCH 11/37] uniform comment capitalization, fix small grammar issues --- README.md | 2 +- src/rails.js | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 29ea432d..872d9127 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ Require both `jquery` and `jquery-ujs` into your application.js manifest. How to run tests ------------ -Follow [this wiki](https://github.com/rails/jquery-ujs/wiki/Running-Tests-and-Contributing) to run tests . +Follow [this wiki](https://github.com/rails/jquery-ujs/wiki/Running-Tests-and-Contributing) to run tests. [data]: http://www.w3.org/TR/html5/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes "Embedding custom non-visible data with the data-* attributes" diff --git a/src/rails.js b/src/rails.js index ffbc0ef0..490a760c 100644 --- a/src/rails.js +++ b/src/rails.js @@ -72,7 +72,7 @@ if (token) xhr.setRequestHeader('X-CSRF-Token', token); }, - // making sure that all forms have actual up-to-date token(cached forms contain old one) + // Make sure that all forms have actual up-to-date tokens (cached forms contain old ones) refreshCSRFTokens: function(){ $('form input[name="' + rails.csrfParam() + '"]').val(rails.csrfToken()); }, @@ -334,7 +334,7 @@ return false; }, - // replace element's html with the 'data-disable-with' after storing original html + // Replace element's html with the 'data-disable-with' after storing original html // and prevent clicking on it disableElement: function(element) { var replacement = element.data('disable-with'); @@ -349,7 +349,7 @@ }); }, - // restore element to its original state which was disabled by 'disableElement' above + // Restore element to its original state which was disabled by 'disableElement' above enableElement: function(element) { if (element.data('ujs:enable-with') !== undefined) { element.html(element.data('ujs:enable-with')); // set to old enabled state @@ -404,7 +404,7 @@ if (metaClick && (!method || method === 'GET') && !data) { return true; } var handleRemote = rails.handleRemote(link); - // response from rails.handleRemote() will either be false or a deferred object promise. + // Response from rails.handleRemote() will either be false or a deferred object promise. if (handleRemote === false) { rails.enableElement(link); } else { @@ -426,7 +426,7 @@ if (button.is(rails.buttonDisableSelector)) rails.disableFormElement(button); var handleRemote = rails.handleRemote(button); - // response from rails.handleRemote() will either be false or a deferred object promise. + // Response from rails.handleRemote() will either be false or a deferred object promise. if (handleRemote === false) { rails.enableFormElement(button); } else { @@ -451,7 +451,7 @@ if (!rails.allowAction(form)) return rails.stopEverything(e); - // skip other logic when required values are missing or file upload is present + // Skip other logic when required values are missing or file upload is present if (form.attr('novalidate') === undefined) { blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector, false); if (blankRequiredInputs && rails.fire(form, 'ajax:aborted:required', [blankRequiredInputs])) { @@ -462,12 +462,12 @@ if (remote) { nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector); if (nonBlankFileInputs) { - // slight timeout so that the submit button gets properly serialized + // Slight timeout so that the submit button gets properly serialized // (make it easy for event handler to serialize form without disabled values) setTimeout(function(){ rails.disableFormElements(form); }, 13); var aborted = rails.fire(form, 'ajax:aborted:file', [nonBlankFileInputs]); - // re-enable form elements if event bindings return false (canceling normal form submission) + // Re-enable form elements if event bindings return false (canceling normal form submission) if (!aborted) { setTimeout(function(){ rails.enableFormElements(form); }, 13); } return aborted; @@ -477,7 +477,7 @@ return false; } else { - // slight timeout so that the submit button gets properly serialized + // Slight timeout so that the submit button gets properly serialized setTimeout(function(){ rails.disableFormElements(form); }, 13); } }); @@ -487,7 +487,7 @@ if (!rails.allowAction(button)) return rails.stopEverything(event); - // register the pressed submit button + // Register the pressed submit button var name = button.attr('name'), data = name ? {name:name, value:button.val()} : null; From c61ae519820079b75195adb1beac73ff3fcc6e3c Mon Sep 17 00:00:00 2001 From: Chris Howlett Date: Tue, 6 Oct 2015 12:41:26 +0100 Subject: [PATCH 12/37] Enable UJS on controls using the 'form' attribute * Ensure disassociated inputs are serialized with the form * Allow disassociated buttons to submit the form --- src/rails.js | 10 ++++--- test/public/test/data-remote.js | 48 ++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/rails.js b/src/rails.js index 490a760c..aaf2ba69 100644 --- a/src/rails.js +++ b/src/rails.js @@ -27,7 +27,7 @@ linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote], 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)', + buttonClickSelector: 'button[data-remote]:not([form]):not(form button), button[data-confirm]:not([form]):not(form button)', // Select elements bound by jquery-ujs inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]', @@ -115,7 +115,7 @@ if (element.is('form')) { method = element.attr('method'); url = element.attr('action'); - data = element.serializeArray(); + data = data = $(element[0].elements).serializeArray(); // memoized value from clicked submit button var button = element.data('ujs:submit-button'); if (button) { @@ -491,7 +491,11 @@ var name = button.attr('name'), data = name ? {name:name, value:button.val()} : null; - button.closest('form').data('ujs:submit-button', data); + var form = button.closest('form'); + if (form.length === 0) { + form = $('#' + button.attr('form')); + } + form.data('ujs:submit-button', data); }); $document.delegate(rails.formSubmitSelector, 'ajax:send.rails', function(event) { diff --git a/test/public/test/data-remote.js b/test/public/test/data-remote.js index c0b47586..6d2cda74 100644 --- a/test/public/test/data-remote.js +++ b/test/public/test/data-remote.js @@ -16,7 +16,8 @@ module('data-remote', { .append($('
', { action: '/echo', 'data-remote': 'true', - method: 'post' + method: 'post', + id: 'my-remote-form' })) .find('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 16/37] 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 17/37] 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 18/37] 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 19/37] 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 20/37] 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 21/37] 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 22/37] 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 23/37] 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 24/37] 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 25/37] 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 26/37] 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 27/37] 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 28/37] 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 29/37] 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 30/37] 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 31/37] 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 32/37] 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() }); $('