Skip to content

Commit a1fd42a

Browse files
committed
Merge pull request #367 from helloenvoy/remote-button-disable-with
add disable-with support for standalone remote buttons
2 parents a71b901 + 24917cd commit a1fd42a

File tree

2 files changed

+110
-10
lines changed

2 files changed

+110
-10
lines changed

src/rails.js

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@
5151
// Link onClick disable selector with possible reenable after remote submission
5252
linkDisableSelector: 'a[data-disable-with]',
5353

54+
// Button onClick disable selector with possible reenable after remote submission
55+
buttonDisableSelector: 'button[data-remote][data-disable-with]',
56+
5457
// Make sure that every Ajax request sends the CSRF token
5558
CSRFProtection: function(xhr) {
5659
var token = $('meta[name="csrf-token"]').attr('content');
@@ -199,25 +202,33 @@
199202
*/
200203
disableFormElements: function(form) {
201204
rails.formElements(form, rails.disableSelector).each(function() {
202-
var element = $(this), method = element.is('button') ? 'html' : 'val';
203-
element.data('ujs:enable-with', element[method]());
204-
element[method](element.data('disable-with'));
205-
element.prop('disabled', true);
205+
rails.disableFormElement($(this));
206206
});
207207
},
208208

209+
disableFormElement: function(element) {
210+
var method = element.is('button') ? 'html' : 'val';
211+
element.data('ujs:enable-with', element[method]());
212+
element[method](element.data('disable-with'));
213+
element.prop('disabled', true);
214+
},
215+
209216
/* Re-enables disabled form elements:
210217
- Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
211218
- Sets disabled property to false
212219
*/
213220
enableFormElements: function(form) {
214221
rails.formElements(form, rails.enableSelector).each(function() {
215-
var element = $(this), method = element.is('button') ? 'html' : 'val';
216-
if (element.data('ujs:enable-with')) element[method](element.data('ujs:enable-with'));
217-
element.prop('disabled', false);
222+
rails.enableFormElement($(this));
218223
});
219224
},
220225

226+
enableFormElement: function(element) {
227+
var method = element.is('button') ? 'html' : 'val';
228+
if (element.data('ujs:enable-with')) element[method](element.data('ujs:enable-with'));
229+
element.prop('disabled', false);
230+
},
231+
221232
/* For 'data-confirm' attribute:
222233
- Fires `confirm` event
223234
- Shows the confirmation dialog
@@ -293,7 +304,6 @@
293304
}
294305
element.unbind('click.railsDisable'); // enable element
295306
}
296-
297307
};
298308

299309
if (rails.fire($document, 'rails:attachBindings')) {
@@ -304,6 +314,10 @@
304314
rails.enableElement($(this));
305315
});
306316

317+
$document.delegate(rails.buttonDisableSelector, 'ajax:complete', function() {
318+
rails.enableFormElement($(this));
319+
});
320+
307321
$document.delegate(rails.linkClickSelector, 'click.rails', function(e) {
308322
var link = $(this), method = link.data('method'), data = link.data('params'), metaClick = e.metaKey || e.ctrlKey;
309323
if (!rails.allowAction(link)) return rails.stopEverything(e);
@@ -332,7 +346,15 @@
332346
var button = $(this);
333347
if (!rails.allowAction(button)) return rails.stopEverything(e);
334348

335-
rails.handleRemote(button);
349+
if (button.is(rails.buttonDisableSelector)) rails.disableFormElement(button);
350+
351+
var handleRemote = rails.handleRemote(button);
352+
// response from rails.handleRemote() will either be false or a deferred object promise.
353+
if (handleRemote === false) {
354+
rails.enableFormElement(button);
355+
} else {
356+
handleRemote.error( function() { rails.enableFormElement(button); } );
357+
}
336358
return false;
337359
});
338360

test/public/test/data-disable.js

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,21 @@ module('data-disable', {
2222
href: '/echo',
2323
'data-disable-with': 'clicking...'
2424
}));
25-
25+
2626
$('#qunit-fixture').append($('<input />', {
2727
type: 'submit',
2828
form: 'not_remote',
2929
'data-disable-with': 'form attr submitting',
3030
name: 'submit3',
3131
value: 'Form Attr Submit'
3232
}));
33+
34+
$('#qunit-fixture').append($('<button />', {
35+
text: 'Click me',
36+
'data-remote': true,
37+
'data-url': '/echo',
38+
'data-disable-with': 'clicking...'
39+
}));
3340
},
3441
teardown: function() {
3542
$(document).unbind('iframe:loaded');
@@ -293,3 +300,74 @@ asyncTest('ctrl-clicking on a link does not disables the link', 6, function() {
293300
checkEnabledState(link, 'Click me');
294301
start();
295302
});
303+
304+
asyncTest('button[data-remote][data-disable-with] disables and re-enables', 6, function() {
305+
var button = $('button[data-remote][data-disable-with]');
306+
307+
checkEnabledState(button, 'Click me');
308+
309+
button
310+
.bind('ajax:send', function() {
311+
checkDisabledState(button, 'clicking...');
312+
})
313+
.bind('ajax:complete', function() {
314+
setTimeout( function() {
315+
checkEnabledState(button, 'Click me');
316+
start();
317+
}, 15);
318+
})
319+
.trigger('click');
320+
});
321+
322+
asyncTest('button[data-remote][data-disable-with] re-enables when `ajax:before` event is cancelled', 6, function() {
323+
var button = $('button[data-remote][data-disable-with]');
324+
325+
checkEnabledState(button, 'Click me');
326+
327+
button
328+
.bind('ajax:before', function() {
329+
checkDisabledState(button, 'clicking...');
330+
return false;
331+
})
332+
.trigger('click');
333+
334+
setTimeout(function() {
335+
checkEnabledState(button, 'Click me');
336+
start();
337+
}, 30);
338+
});
339+
340+
asyncTest('button[data-remote][data-disable-with] re-enables when `ajax:beforeSend` event is cancelled', 6, function() {
341+
var button = $('button[data-remote][data-disable-with]');
342+
343+
checkEnabledState(button, 'Click me');
344+
345+
button
346+
.bind('ajax:beforeSend', function() {
347+
checkDisabledState(button, 'clicking...');
348+
return false;
349+
})
350+
.trigger('click');
351+
352+
setTimeout(function() {
353+
checkEnabledState(button, 'Click me');
354+
start();
355+
}, 30);
356+
});
357+
358+
asyncTest('button[data-remote][data-disable-with] re-enables when `ajax:error` event is triggered', 6, function() {
359+
var button = $('a[data-disable-with]').attr('data-remote', true).attr('href', '/error');
360+
361+
checkEnabledState(button, 'Click me');
362+
363+
button
364+
.bind('ajax:send', function() {
365+
checkDisabledState(button, 'clicking...');
366+
})
367+
.trigger('click');
368+
369+
setTimeout(function() {
370+
checkEnabledState(button, 'Click me');
371+
start();
372+
}, 30);
373+
});

0 commit comments

Comments
 (0)