From 8fc44057482460793052d8ff2e0ccb74448dd702 Mon Sep 17 00:00:00 2001
From: Krzysztof Kotlarski
Date: Fri, 5 Dec 2014 14:29:53 +0100
Subject: [PATCH 01/28] 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/28] 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 c61ae519820079b75195adb1beac73ff3fcc6e3c Mon Sep 17 00:00:00 2001
From: Chris Howlett
Date: Tue, 6 Oct 2015 12:41:26 +0100
Subject: [PATCH 03/28] 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() });
+
+ $('', {
+ type: "submit",
+ name: "user_data",
+ value: "value1",
+ form: "my-remote-form"
+ })
+ .appendTo($('#qunit-fixture'));
+
+ $('', {
+ type: "submit",
+ name: "user_data",
+ value: "value2",
+ form: "my-remote-form"
+ })
+ .appendTo($('#qunit-fixture'))
+ .trigger('click');
+});
+
asyncTest('form\'s submit bindings in browsers that don\'t support submit bubbling', 5, function() {
var form = $('form[data-remote]'), directBindingCalled = false;
From be31d8b0905424d60ff1e9a051ece877123e33c7 Mon Sep 17 00:00:00 2001
From: Rune Schjellerup Philosof