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