jquery-rails 3.0.4 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.travis.yml +32 -0
- data/CHANGELOG.md +99 -2
- data/CONTRIBUTING.md +103 -7
- data/Gemfile +18 -0
- data/{LICENSE → MIT-LICENSE} +2 -2
- data/README.md +34 -39
- data/Rakefile +39 -1
- data/VERSIONS.md +63 -39
- data/jquery-rails.gemspec +7 -5
- data/lib/jquery/assert_select.rb +141 -89
- data/lib/jquery/rails/version.rb +5 -3
- data/lib/jquery/rails.rb +1 -3
- data/test/assert_select_jquery_test.rb +91 -0
- data/test/test_helper.rb +6 -0
- data/vendor/assets/javascripts/jquery.js +7550 -6331
- data/vendor/assets/javascripts/jquery.min.js +5 -6
- data/vendor/assets/javascripts/jquery.min.map +1 -1
- data/vendor/assets/javascripts/jquery2.js +9814 -0
- data/vendor/assets/javascripts/jquery2.min.js +4 -0
- data/vendor/assets/javascripts/jquery2.min.map +1 -0
- data/vendor/assets/javascripts/jquery3.js +10872 -0
- data/vendor/assets/javascripts/jquery3.min.js +2 -0
- data/vendor/assets/javascripts/jquery3.min.map +1 -0
- data/vendor/assets/javascripts/jquery_ujs.js +256 -95
- metadata +62 -34
- data/lib/generators/jquery/install/install_generator.rb +0 -50
- data/lib/jquery/rails/railtie.rb +0 -18
@@ -4,7 +4,7 @@
|
|
4
4
|
* Unobtrusive scripting adapter for jQuery
|
5
5
|
* https://github.com/rails/jquery-ujs
|
6
6
|
*
|
7
|
-
* Requires jQuery 1.
|
7
|
+
* Requires jQuery 1.8.0 or later.
|
8
8
|
*
|
9
9
|
* Released under the MIT license
|
10
10
|
*
|
@@ -12,6 +12,8 @@
|
|
12
12
|
|
13
13
|
// Cut down on the number of issues from people inadvertently including jquery_ujs twice
|
14
14
|
// by detecting and raising an error when it happens.
|
15
|
+
'use strict';
|
16
|
+
|
15
17
|
if ( $.rails !== undefined ) {
|
16
18
|
$.error('jquery-ujs has already been loaded!');
|
17
19
|
}
|
@@ -22,10 +24,10 @@
|
|
22
24
|
|
23
25
|
$.rails = rails = {
|
24
26
|
// Link elements bound by jquery-ujs
|
25
|
-
linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote], a[data-disable-with]',
|
27
|
+
linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote]:not([disabled]), a[data-disable-with], a[data-disable]',
|
26
28
|
|
27
|
-
// Button elements
|
28
|
-
buttonClickSelector: 'button[data-remote]',
|
29
|
+
// Button elements bound by jquery-ujs
|
30
|
+
buttonClickSelector: 'button[data-remote]:not([form]):not(form button), button[data-confirm]:not([form]):not(form button)',
|
29
31
|
|
30
32
|
// Select elements bound by jquery-ujs
|
31
33
|
inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]',
|
@@ -34,29 +36,47 @@
|
|
34
36
|
formSubmitSelector: 'form',
|
35
37
|
|
36
38
|
// Form input elements bound by jquery-ujs
|
37
|
-
formInputClickSelector: 'form input[type=submit], form input[type=image], form button[type=submit], form button:not([type])',
|
39
|
+
formInputClickSelector: 'form input[type=submit], form input[type=image], form button[type=submit], form button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])',
|
38
40
|
|
39
41
|
// Form input elements disabled during form submission
|
40
|
-
disableSelector: 'input[data-disable-with], button[data-disable-with], textarea[data-disable-with]',
|
42
|
+
disableSelector: 'input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled',
|
41
43
|
|
42
44
|
// Form input elements re-enabled after form submission
|
43
|
-
enableSelector: 'input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled',
|
45
|
+
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',
|
44
46
|
|
45
47
|
// Form required input elements
|
46
|
-
requiredInputSelector: 'input[name][required]:not([disabled]),textarea[name][required]:not([disabled])',
|
48
|
+
requiredInputSelector: 'input[name][required]:not([disabled]), textarea[name][required]:not([disabled])',
|
47
49
|
|
48
50
|
// Form file input elements
|
49
|
-
fileInputSelector: 'input[type=file]',
|
51
|
+
fileInputSelector: 'input[name][type=file]:not([disabled])',
|
50
52
|
|
51
53
|
// Link onClick disable selector with possible reenable after remote submission
|
52
|
-
linkDisableSelector: 'a[data-disable-with]',
|
54
|
+
linkDisableSelector: 'a[data-disable-with], a[data-disable]',
|
55
|
+
|
56
|
+
// Button onClick disable selector with possible reenable after remote submission
|
57
|
+
buttonDisableSelector: 'button[data-remote][data-disable-with], button[data-remote][data-disable]',
|
58
|
+
|
59
|
+
// Up-to-date Cross-Site Request Forgery token
|
60
|
+
csrfToken: function() {
|
61
|
+
return $('meta[name=csrf-token]').attr('content');
|
62
|
+
},
|
63
|
+
|
64
|
+
// URL param that must contain the CSRF token
|
65
|
+
csrfParam: function() {
|
66
|
+
return $('meta[name=csrf-param]').attr('content');
|
67
|
+
},
|
53
68
|
|
54
69
|
// Make sure that every Ajax request sends the CSRF token
|
55
70
|
CSRFProtection: function(xhr) {
|
56
|
-
var token =
|
71
|
+
var token = rails.csrfToken();
|
57
72
|
if (token) xhr.setRequestHeader('X-CSRF-Token', token);
|
58
73
|
},
|
59
74
|
|
75
|
+
// Make sure that all forms have actual up-to-date tokens (cached forms contain old ones)
|
76
|
+
refreshCSRFTokens: function(){
|
77
|
+
$('form input[name="' + rails.csrfParam() + '"]').val(rails.csrfToken());
|
78
|
+
},
|
79
|
+
|
60
80
|
// Triggers an event on an element and returns false if the event result is false
|
61
81
|
fire: function(obj, name, data) {
|
62
82
|
var event = $.Event(name);
|
@@ -76,39 +96,44 @@
|
|
76
96
|
|
77
97
|
// Default way to get an element's href. May be overridden at $.rails.href.
|
78
98
|
href: function(element) {
|
79
|
-
return element.
|
99
|
+
return element[0].href;
|
100
|
+
},
|
101
|
+
|
102
|
+
// Checks "data-remote" if true to handle the request through a XHR request.
|
103
|
+
isRemote: function(element) {
|
104
|
+
return element.data('remote') !== undefined && element.data('remote') !== false;
|
80
105
|
},
|
81
106
|
|
82
107
|
// Submits "remote" forms and links with ajax
|
83
108
|
handleRemote: function(element) {
|
84
|
-
var method, url, data,
|
109
|
+
var method, url, data, withCredentials, dataType, options;
|
85
110
|
|
86
111
|
if (rails.fire(element, 'ajax:before')) {
|
87
|
-
elCrossDomain = element.data('cross-domain');
|
88
|
-
crossDomain = elCrossDomain === undefined ? null : elCrossDomain;
|
89
112
|
withCredentials = element.data('with-credentials') || null;
|
90
113
|
dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType);
|
91
114
|
|
92
115
|
if (element.is('form')) {
|
93
|
-
method = element.attr('method');
|
94
|
-
url = element.attr('action');
|
95
|
-
data = element.serializeArray();
|
116
|
+
method = element.data('ujs:submit-button-formmethod') || element.attr('method');
|
117
|
+
url = element.data('ujs:submit-button-formaction') || element.attr('action');
|
118
|
+
data = $(element[0]).serializeArray();
|
96
119
|
// memoized value from clicked submit button
|
97
120
|
var button = element.data('ujs:submit-button');
|
98
121
|
if (button) {
|
99
122
|
data.push(button);
|
100
123
|
element.data('ujs:submit-button', null);
|
101
124
|
}
|
125
|
+
element.data('ujs:submit-button-formmethod', null);
|
126
|
+
element.data('ujs:submit-button-formaction', null);
|
102
127
|
} else if (element.is(rails.inputChangeSelector)) {
|
103
128
|
method = element.data('method');
|
104
129
|
url = element.data('url');
|
105
130
|
data = element.serialize();
|
106
|
-
if (element.data('params')) data = data +
|
131
|
+
if (element.data('params')) data = data + '&' + element.data('params');
|
107
132
|
} else if (element.is(rails.buttonClickSelector)) {
|
108
133
|
method = element.data('method') || 'get';
|
109
134
|
url = element.data('url');
|
110
135
|
data = element.serialize();
|
111
|
-
if (element.data('params')) data = data +
|
136
|
+
if (element.data('params')) data = data + '&' + element.data('params');
|
112
137
|
} else {
|
113
138
|
method = element.data('method');
|
114
139
|
url = rails.href(element);
|
@@ -122,7 +147,11 @@
|
|
122
147
|
if (settings.dataType === undefined) {
|
123
148
|
xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script);
|
124
149
|
}
|
125
|
-
|
150
|
+
if (rails.fire(element, 'ajax:beforeSend', [xhr, settings])) {
|
151
|
+
element.trigger('ajax:send', xhr);
|
152
|
+
} else {
|
153
|
+
return false;
|
154
|
+
}
|
126
155
|
},
|
127
156
|
success: function(data, status, xhr) {
|
128
157
|
element.trigger('ajax:success', [data, status, xhr]);
|
@@ -133,7 +162,7 @@
|
|
133
162
|
error: function(xhr, status, error) {
|
134
163
|
element.trigger('ajax:error', [xhr, status, error]);
|
135
164
|
},
|
136
|
-
crossDomain:
|
165
|
+
crossDomain: rails.isCrossDomain(url)
|
137
166
|
};
|
138
167
|
|
139
168
|
// There is no withCredentials for IE6-8 when
|
@@ -147,61 +176,111 @@
|
|
147
176
|
// Only pass url to `ajax` options if not blank
|
148
177
|
if (url) { options.url = url; }
|
149
178
|
|
150
|
-
|
151
|
-
element.trigger('ajax:send', jqxhr);
|
152
|
-
return jqxhr;
|
179
|
+
return rails.ajax(options);
|
153
180
|
} else {
|
154
181
|
return false;
|
155
182
|
}
|
156
183
|
},
|
157
184
|
|
185
|
+
// Determines if the request is a cross domain request.
|
186
|
+
isCrossDomain: function(url) {
|
187
|
+
var originAnchor = document.createElement('a');
|
188
|
+
originAnchor.href = location.href;
|
189
|
+
var urlAnchor = document.createElement('a');
|
190
|
+
|
191
|
+
try {
|
192
|
+
urlAnchor.href = url;
|
193
|
+
// This is a workaround to a IE bug.
|
194
|
+
urlAnchor.href = urlAnchor.href;
|
195
|
+
|
196
|
+
// If URL protocol is false or is a string containing a single colon
|
197
|
+
// *and* host are false, assume it is not a cross-domain request
|
198
|
+
// (should only be the case for IE7 and IE compatibility mode).
|
199
|
+
// Otherwise, evaluate protocol and host of the URL against the origin
|
200
|
+
// protocol and host.
|
201
|
+
return !(((!urlAnchor.protocol || urlAnchor.protocol === ':') && !urlAnchor.host) ||
|
202
|
+
(originAnchor.protocol + '//' + originAnchor.host ===
|
203
|
+
urlAnchor.protocol + '//' + urlAnchor.host));
|
204
|
+
} catch (e) {
|
205
|
+
// If there is an error parsing the URL, assume it is crossDomain.
|
206
|
+
return true;
|
207
|
+
}
|
208
|
+
},
|
209
|
+
|
158
210
|
// Handles "data-method" on links such as:
|
159
211
|
// <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>
|
160
212
|
handleMethod: function(link) {
|
161
213
|
var href = rails.href(link),
|
162
214
|
method = link.data('method'),
|
163
215
|
target = link.attr('target'),
|
164
|
-
|
165
|
-
|
216
|
+
csrfToken = rails.csrfToken(),
|
217
|
+
csrfParam = rails.csrfParam(),
|
166
218
|
form = $('<form method="post" action="' + href + '"></form>'),
|
167
|
-
|
219
|
+
metadataInput = '<input name="_method" value="' + method + '" type="hidden" />';
|
168
220
|
|
169
|
-
if (
|
170
|
-
|
221
|
+
if (csrfParam !== undefined && csrfToken !== undefined && !rails.isCrossDomain(href)) {
|
222
|
+
metadataInput += '<input name="' + csrfParam + '" value="' + csrfToken + '" type="hidden" />';
|
171
223
|
}
|
172
224
|
|
173
225
|
if (target) { form.attr('target', target); }
|
174
226
|
|
175
|
-
form.hide().append(
|
227
|
+
form.hide().append(metadataInput).appendTo('body');
|
176
228
|
form.submit();
|
177
229
|
},
|
178
230
|
|
231
|
+
// Helper function that returns form elements that match the specified CSS selector
|
232
|
+
// If form is actually a "form" element this will return associated elements outside the from that have
|
233
|
+
// the html form attribute set
|
234
|
+
formElements: function(form, selector) {
|
235
|
+
return form.is('form') ? $(form[0].elements).filter(selector) : form.find(selector);
|
236
|
+
},
|
237
|
+
|
179
238
|
/* Disables form elements:
|
180
239
|
- Caches element value in 'ujs:enable-with' data store
|
181
240
|
- Replaces element text with value of 'data-disable-with' attribute
|
182
241
|
- Sets disabled property to true
|
183
242
|
*/
|
184
243
|
disableFormElements: function(form) {
|
185
|
-
|
186
|
-
|
187
|
-
element.data('ujs:enable-with', element[method]());
|
188
|
-
element[method](element.data('disable-with'));
|
189
|
-
element.prop('disabled', true);
|
244
|
+
rails.formElements(form, rails.disableSelector).each(function() {
|
245
|
+
rails.disableFormElement($(this));
|
190
246
|
});
|
191
247
|
},
|
192
248
|
|
249
|
+
disableFormElement: function(element) {
|
250
|
+
var method, replacement;
|
251
|
+
|
252
|
+
method = element.is('button') ? 'html' : 'val';
|
253
|
+
replacement = element.data('disable-with');
|
254
|
+
|
255
|
+
if (replacement !== undefined) {
|
256
|
+
element.data('ujs:enable-with', element[method]());
|
257
|
+
element[method](replacement);
|
258
|
+
}
|
259
|
+
|
260
|
+
element.prop('disabled', true);
|
261
|
+
element.data('ujs:disabled', true);
|
262
|
+
},
|
263
|
+
|
193
264
|
/* Re-enables disabled form elements:
|
194
265
|
- Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
|
195
266
|
- Sets disabled property to false
|
196
267
|
*/
|
197
268
|
enableFormElements: function(form) {
|
198
|
-
|
199
|
-
|
200
|
-
if (element.data('ujs:enable-with')) element[method](element.data('ujs:enable-with'));
|
201
|
-
element.prop('disabled', false);
|
269
|
+
rails.formElements(form, rails.enableSelector).each(function() {
|
270
|
+
rails.enableFormElement($(this));
|
202
271
|
});
|
203
272
|
},
|
204
273
|
|
274
|
+
enableFormElement: function(element) {
|
275
|
+
var method = element.is('button') ? 'html' : 'val';
|
276
|
+
if (element.data('ujs:enable-with') !== undefined) {
|
277
|
+
element[method](element.data('ujs:enable-with'));
|
278
|
+
element.removeData('ujs:enable-with'); // clean up cache
|
279
|
+
}
|
280
|
+
element.prop('disabled', false);
|
281
|
+
element.removeData('ujs:disabled');
|
282
|
+
},
|
283
|
+
|
205
284
|
/* For 'data-confirm' attribute:
|
206
285
|
- Fires `confirm` event
|
207
286
|
- Shows the confirmation dialog
|
@@ -218,7 +297,11 @@
|
|
218
297
|
if (!message) { return true; }
|
219
298
|
|
220
299
|
if (rails.fire(element, 'confirm')) {
|
221
|
-
|
300
|
+
try {
|
301
|
+
answer = rails.confirm(message);
|
302
|
+
} catch (e) {
|
303
|
+
(console.error || console.log).call(console, e.stack || e);
|
304
|
+
}
|
222
305
|
callback = rails.fire(element, 'confirm:complete', [answer]);
|
223
306
|
}
|
224
307
|
return answer && callback;
|
@@ -226,25 +309,45 @@
|
|
226
309
|
|
227
310
|
// Helper function which checks for blank inputs in a form that match the specified CSS selector
|
228
311
|
blankInputs: function(form, specifiedSelector, nonBlank) {
|
229
|
-
var
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
312
|
+
var foundInputs = $(),
|
313
|
+
input,
|
314
|
+
valueToCheck,
|
315
|
+
radiosForNameWithNoneSelected,
|
316
|
+
radioName,
|
317
|
+
selector = specifiedSelector || 'input,textarea',
|
318
|
+
requiredInputs = form.find(selector),
|
319
|
+
checkedRadioButtonNames = {};
|
320
|
+
|
321
|
+
requiredInputs.each(function() {
|
234
322
|
input = $(this);
|
235
|
-
|
236
|
-
// If nonBlank and valueToCheck are both truthy, or nonBlank and valueToCheck are both falsey
|
237
|
-
if (!valueToCheck === !nonBlank) {
|
323
|
+
if (input.is('input[type=radio]')) {
|
238
324
|
|
239
|
-
// Don't count unchecked required radio if other radio with same name is checked
|
240
|
-
|
241
|
-
|
242
|
-
|
325
|
+
// Don't count unchecked required radio as blank if other radio with same name is checked,
|
326
|
+
// regardless of whether same-name radio input has required attribute or not. The spec
|
327
|
+
// states https://www.w3.org/TR/html5/forms.html#the-required-attribute
|
328
|
+
radioName = input.attr('name');
|
329
|
+
|
330
|
+
// Skip if we've already seen the radio with this name.
|
331
|
+
if (!checkedRadioButtonNames[radioName]) {
|
243
332
|
|
244
|
-
|
333
|
+
// If none checked
|
334
|
+
if (form.find('input[type=radio]:checked[name="' + radioName + '"]').length === 0) {
|
335
|
+
radiosForNameWithNoneSelected = form.find(
|
336
|
+
'input[type=radio][name="' + radioName + '"]');
|
337
|
+
foundInputs = foundInputs.add(radiosForNameWithNoneSelected);
|
338
|
+
}
|
339
|
+
|
340
|
+
// We only need to check each name once.
|
341
|
+
checkedRadioButtonNames[radioName] = radioName;
|
342
|
+
}
|
343
|
+
} else {
|
344
|
+
valueToCheck = input.is('input[type=checkbox],input[type=radio]') ? input.is(':checked') : !!input.val();
|
345
|
+
if (valueToCheck === nonBlank) {
|
346
|
+
foundInputs = foundInputs.add(input);
|
347
|
+
}
|
245
348
|
}
|
246
349
|
});
|
247
|
-
return
|
350
|
+
return foundInputs.length ? foundInputs : false;
|
248
351
|
},
|
249
352
|
|
250
353
|
// Helper function which checks for non-blank inputs in a form that match the specified CSS selector
|
@@ -259,96 +362,148 @@
|
|
259
362
|
return false;
|
260
363
|
},
|
261
364
|
|
262
|
-
//
|
365
|
+
// Replace element's html with the 'data-disable-with' after storing original html
|
263
366
|
// and prevent clicking on it
|
264
367
|
disableElement: function(element) {
|
265
|
-
element.data('
|
266
|
-
|
368
|
+
var replacement = element.data('disable-with');
|
369
|
+
|
370
|
+
if (replacement !== undefined) {
|
371
|
+
element.data('ujs:enable-with', element.html()); // store enabled state
|
372
|
+
element.html(replacement);
|
373
|
+
}
|
374
|
+
|
267
375
|
element.bind('click.railsDisable', function(e) { // prevent further clicking
|
268
376
|
return rails.stopEverything(e);
|
269
377
|
});
|
378
|
+
element.data('ujs:disabled', true);
|
270
379
|
},
|
271
380
|
|
272
|
-
//
|
381
|
+
// Restore element to its original state which was disabled by 'disableElement' above
|
273
382
|
enableElement: function(element) {
|
274
383
|
if (element.data('ujs:enable-with') !== undefined) {
|
275
384
|
element.html(element.data('ujs:enable-with')); // set to old enabled state
|
276
385
|
element.removeData('ujs:enable-with'); // clean up cache
|
277
386
|
}
|
278
387
|
element.unbind('click.railsDisable'); // enable element
|
388
|
+
element.removeData('ujs:disabled');
|
279
389
|
}
|
280
|
-
|
281
390
|
};
|
282
391
|
|
283
392
|
if (rails.fire($document, 'rails:attachBindings')) {
|
284
393
|
|
285
394
|
$.ajaxPrefilter(function(options, originalOptions, xhr){ if ( !options.crossDomain ) { rails.CSRFProtection(xhr); }});
|
286
395
|
|
287
|
-
|
396
|
+
// This event works the same as the load event, except that it fires every
|
397
|
+
// time the page is loaded.
|
398
|
+
//
|
399
|
+
// See https://github.com/rails/jquery-ujs/issues/357
|
400
|
+
// See https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching
|
401
|
+
$(window).on('pageshow.rails', function () {
|
402
|
+
$($.rails.enableSelector).each(function () {
|
403
|
+
var element = $(this);
|
404
|
+
|
405
|
+
if (element.data('ujs:disabled')) {
|
406
|
+
$.rails.enableFormElement(element);
|
407
|
+
}
|
408
|
+
});
|
409
|
+
|
410
|
+
$($.rails.linkDisableSelector).each(function () {
|
411
|
+
var element = $(this);
|
412
|
+
|
413
|
+
if (element.data('ujs:disabled')) {
|
414
|
+
$.rails.enableElement(element);
|
415
|
+
}
|
416
|
+
});
|
417
|
+
});
|
418
|
+
|
419
|
+
$document.on('ajax:complete', rails.linkDisableSelector, function() {
|
288
420
|
rails.enableElement($(this));
|
289
421
|
});
|
290
422
|
|
291
|
-
$document.
|
292
|
-
|
423
|
+
$document.on('ajax:complete', rails.buttonDisableSelector, function() {
|
424
|
+
rails.enableFormElement($(this));
|
425
|
+
});
|
426
|
+
|
427
|
+
$document.on('click.rails', rails.linkClickSelector, function(e) {
|
428
|
+
var link = $(this), method = link.data('method'), data = link.data('params'), metaClick = e.metaKey || e.ctrlKey;
|
293
429
|
if (!rails.allowAction(link)) return rails.stopEverything(e);
|
294
430
|
|
295
|
-
if (link.is(rails.linkDisableSelector)) rails.disableElement(link);
|
431
|
+
if (!metaClick && link.is(rails.linkDisableSelector)) rails.disableElement(link);
|
296
432
|
|
297
|
-
if (
|
298
|
-
if (
|
433
|
+
if (rails.isRemote(link)) {
|
434
|
+
if (metaClick && (!method || method === 'GET') && !data) { return true; }
|
299
435
|
|
300
436
|
var handleRemote = rails.handleRemote(link);
|
301
|
-
//
|
437
|
+
// Response from rails.handleRemote() will either be false or a deferred object promise.
|
302
438
|
if (handleRemote === false) {
|
303
439
|
rails.enableElement(link);
|
304
440
|
} else {
|
305
|
-
handleRemote.
|
441
|
+
handleRemote.fail( function() { rails.enableElement(link); } );
|
306
442
|
}
|
307
443
|
return false;
|
308
444
|
|
309
|
-
} else if (
|
445
|
+
} else if (method) {
|
310
446
|
rails.handleMethod(link);
|
311
447
|
return false;
|
312
448
|
}
|
313
449
|
});
|
314
450
|
|
315
|
-
$document.
|
451
|
+
$document.on('click.rails', rails.buttonClickSelector, function(e) {
|
316
452
|
var button = $(this);
|
317
|
-
if (!rails.allowAction(button)) return rails.stopEverything(e);
|
318
453
|
|
319
|
-
rails.
|
454
|
+
if (!rails.allowAction(button) || !rails.isRemote(button)) return rails.stopEverything(e);
|
455
|
+
|
456
|
+
if (button.is(rails.buttonDisableSelector)) rails.disableFormElement(button);
|
457
|
+
|
458
|
+
var handleRemote = rails.handleRemote(button);
|
459
|
+
// Response from rails.handleRemote() will either be false or a deferred object promise.
|
460
|
+
if (handleRemote === false) {
|
461
|
+
rails.enableFormElement(button);
|
462
|
+
} else {
|
463
|
+
handleRemote.fail( function() { rails.enableFormElement(button); } );
|
464
|
+
}
|
320
465
|
return false;
|
321
466
|
});
|
322
467
|
|
323
|
-
$document.
|
468
|
+
$document.on('change.rails', rails.inputChangeSelector, function(e) {
|
324
469
|
var link = $(this);
|
325
|
-
if (!rails.allowAction(link)) return rails.stopEverything(e);
|
470
|
+
if (!rails.allowAction(link) || !rails.isRemote(link)) return rails.stopEverything(e);
|
326
471
|
|
327
472
|
rails.handleRemote(link);
|
328
473
|
return false;
|
329
474
|
});
|
330
475
|
|
331
|
-
$document.
|
476
|
+
$document.on('submit.rails', rails.formSubmitSelector, function(e) {
|
332
477
|
var form = $(this),
|
333
|
-
remote =
|
334
|
-
blankRequiredInputs
|
335
|
-
nonBlankFileInputs
|
478
|
+
remote = rails.isRemote(form),
|
479
|
+
blankRequiredInputs,
|
480
|
+
nonBlankFileInputs;
|
336
481
|
|
337
482
|
if (!rails.allowAction(form)) return rails.stopEverything(e);
|
338
483
|
|
339
|
-
//
|
340
|
-
if (
|
341
|
-
|
484
|
+
// Skip other logic when required values are missing or file upload is present
|
485
|
+
if (form.attr('novalidate') === undefined) {
|
486
|
+
if (form.data('ujs:formnovalidate-button') === undefined) {
|
487
|
+
blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector, false);
|
488
|
+
if (blankRequiredInputs && rails.fire(form, 'ajax:aborted:required', [blankRequiredInputs])) {
|
489
|
+
return rails.stopEverything(e);
|
490
|
+
}
|
491
|
+
} else {
|
492
|
+
// Clear the formnovalidate in case the next button click is not on a formnovalidate button
|
493
|
+
// Not strictly necessary to do here, since it is also reset on each button click, but just to be certain
|
494
|
+
form.data('ujs:formnovalidate-button', undefined);
|
495
|
+
}
|
342
496
|
}
|
343
497
|
|
344
498
|
if (remote) {
|
499
|
+
nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector);
|
345
500
|
if (nonBlankFileInputs) {
|
346
|
-
//
|
501
|
+
// Slight timeout so that the submit button gets properly serialized
|
347
502
|
// (make it easy for event handler to serialize form without disabled values)
|
348
503
|
setTimeout(function(){ rails.disableFormElements(form); }, 13);
|
349
504
|
var aborted = rails.fire(form, 'ajax:aborted:file', [nonBlankFileInputs]);
|
350
505
|
|
351
|
-
//
|
506
|
+
// Re-enable form elements if event bindings return false (canceling normal form submission)
|
352
507
|
if (!aborted) { setTimeout(function(){ rails.enableFormElements(form); }, 13); }
|
353
508
|
|
354
509
|
return aborted;
|
@@ -358,36 +513,42 @@
|
|
358
513
|
return false;
|
359
514
|
|
360
515
|
} else {
|
361
|
-
//
|
516
|
+
// Slight timeout so that the submit button gets properly serialized
|
362
517
|
setTimeout(function(){ rails.disableFormElements(form); }, 13);
|
363
518
|
}
|
364
519
|
});
|
365
520
|
|
366
|
-
$document.
|
521
|
+
$document.on('click.rails', rails.formInputClickSelector, function(event) {
|
367
522
|
var button = $(this);
|
368
523
|
|
369
524
|
if (!rails.allowAction(button)) return rails.stopEverything(event);
|
370
525
|
|
371
|
-
//
|
526
|
+
// Register the pressed submit button
|
372
527
|
var name = button.attr('name'),
|
373
528
|
data = name ? {name:name, value:button.val()} : null;
|
374
529
|
|
375
|
-
button.closest('form')
|
530
|
+
var form = button.closest('form');
|
531
|
+
if (form.length === 0) {
|
532
|
+
form = $('#' + button.attr('form'));
|
533
|
+
}
|
534
|
+
form.data('ujs:submit-button', data);
|
535
|
+
|
536
|
+
// Save attributes from button
|
537
|
+
form.data('ujs:formnovalidate-button', button.attr('formnovalidate'));
|
538
|
+
form.data('ujs:submit-button-formaction', button.attr('formaction'));
|
539
|
+
form.data('ujs:submit-button-formmethod', button.attr('formmethod'));
|
376
540
|
});
|
377
541
|
|
378
|
-
$document.
|
379
|
-
if (this
|
542
|
+
$document.on('ajax:send.rails', rails.formSubmitSelector, function(event) {
|
543
|
+
if (this === event.target) rails.disableFormElements($(this));
|
380
544
|
});
|
381
545
|
|
382
|
-
$document.
|
383
|
-
if (this
|
546
|
+
$document.on('ajax:complete.rails', rails.formSubmitSelector, function(event) {
|
547
|
+
if (this === event.target) rails.enableFormElements($(this));
|
384
548
|
});
|
385
549
|
|
386
550
|
$(function(){
|
387
|
-
|
388
|
-
var csrf_token = $('meta[name=csrf-token]').attr('content');
|
389
|
-
var csrf_param = $('meta[name=csrf-param]').attr('content');
|
390
|
-
$('form input[name="' + csrf_param + '"]').val(csrf_token);
|
551
|
+
rails.refreshCSRFTokens();
|
391
552
|
});
|
392
553
|
}
|
393
554
|
|