1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge pull request #32574 from DmytroVasin/rails-ujs-stoppable-events

Rails-ujs: Info about stoppable events
This commit is contained in:
Rafael França 2018-04-19 23:37:01 -04:00 committed by GitHub
commit 3812ef8b66
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 73 additions and 64 deletions

View file

@ -75,9 +75,9 @@ 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.bindNative('ajax:beforeSend', function() {
form.bindNative('ajax:beforeSend', function(e) {
ok(true, 'aborting request in ajax:beforeSend')
return false
e.preventDefault()
})
form.unbind('ajax:send').bindNative('ajax:send', function() {
ok(false, 'ajax:send should not run')
@ -148,8 +148,8 @@ function skipIt() {
.bind('iframe:loading', function() {
ok(false, 'form should not get submitted')
})
.bindNative('ajax:aborted:file', function() {
return false
.bindNative('ajax:aborted:file', function(e) {
e.preventDefault()
})
.triggerNative('submit')
@ -162,9 +162,9 @@ function skipIt() {
}
asyncTest('"ajax:beforeSend" can be observed and stopped with event delegation', 1, function() {
$(document).delegate('form[data-remote]', 'ajax:beforeSend', function() {
$(document).delegate('form[data-remote]', 'ajax:beforeSend', function(e) {
ok(true, 'ajax:beforeSend observed with event delegation')
return false
e.preventDefault()
})
submit(function(form) {

View file

@ -210,7 +210,7 @@ asyncTest('allow empty form "action"', 1, function() {
buildForm({ action: '' })
$('#qunit-fixture').find('form')
.bindNative('ajax:beforeSend', function(e, xhr, settings) {
.bindNative('ajax:beforeSend', function(evt, xhr, settings) {
// Get current location (the same way jQuery does)
try {
currentLocation = location.href
@ -229,7 +229,7 @@ asyncTest('allow empty form "action"', 1, function() {
// Prevent the request from actually getting sent to the current page and
// causing an error.
return false
evt.preventDefault()
})
.triggerNative('submit')
@ -257,7 +257,7 @@ asyncTest('intelligently guesses crossDomain behavior when target URL has a diff
equal(settings.crossDomain, true, 'crossDomain should be set to true')
// prevent request from actually getting sent off-domain
return false
evt.preventDefault()
})
.triggerNative('submit')
@ -276,7 +276,7 @@ asyncTest('intelligently guesses crossDomain behavior when target URL consists o
equal(settings.crossDomain, false, 'crossDomain should be set to false')
// prevent request from actually getting sent off-domain
return false
evt.preventDefault()
})
.triggerNative('submit')

View file

@ -173,9 +173,9 @@ asyncTest('binding to confirm event of a link and returning false', 1, function(
}
$('a[data-confirm]')
.bindNative('confirm', function() {
.bindNative('confirm', function(e) {
App.assertCallbackInvoked('confirm')
return false
e.preventDefault()
})
.bindNative('confirm:complete', function() {
App.assertCallbackNotInvoked('confirm:complete')
@ -194,9 +194,9 @@ asyncTest('binding to confirm event of a button and returning false', 1, functio
}
$('button[data-confirm]')
.bindNative('confirm', function() {
.bindNative('confirm', function(e) {
App.assertCallbackInvoked('confirm')
return false
e.preventDefault()
})
.bindNative('confirm:complete', function() {
App.assertCallbackNotInvoked('confirm:complete')
@ -216,9 +216,9 @@ asyncTest('binding to confirm:complete event of a link and returning false', 2,
}
$('a[data-confirm]')
.bindNative('confirm:complete', function() {
.bindNative('confirm:complete', function(e) {
App.assertCallbackInvoked('confirm:complete')
return false
e.preventDefault()
})
.bindNative('ajax:beforeSend', function() {
App.assertCallbackNotInvoked('ajax:beforeSend')
@ -238,9 +238,9 @@ asyncTest('binding to confirm:complete event of a button and returning false', 2
}
$('button[data-confirm]')
.bindNative('confirm:complete', function() {
.bindNative('confirm:complete', function(e) {
App.assertCallbackInvoked('confirm:complete')
return false
e.preventDefault()
})
.bindNative('ajax:beforeSend', function() {
App.assertCallbackNotInvoked('ajax:beforeSend')

View file

@ -132,7 +132,8 @@ 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()
var form = $('#qunit-fixture form:not([data-remote])').attr('data-remote', 'true'),
origFormContents = form.html()
form.bindNative('ajax:success', function() {
form.html(origFormContents)
@ -146,7 +147,8 @@ asyncTest('form[data-remote] input[type=submit][data-disable-with] is replaced i
})
asyncTest('form[data-remote] input[data-disable-with] is replaced with disabled field in ajax callback', 2, function() {
var form = $('form:not([data-remote])').attr('data-remote', 'true'), input = form.find('input[type=submit]'),
var form = $('#qunit-fixture form:not([data-remote])').attr('data-remote', 'true'),
input = form.find('input[type=submit]'),
newDisabledInput = input.clone().attr('disabled', 'disabled')
form.bindNative('ajax:success', function() {
@ -238,9 +240,9 @@ asyncTest('a[data-remote][data-disable-with] re-enables when `ajax:before` event
App.checkEnabledState(link, 'Click me')
link
.bindNative('ajax:before', function() {
.bindNative('ajax:before', function(e) {
App.checkDisabledState(link, 'clicking...')
return false
e.preventDefault()
})
.triggerNative('click')
@ -256,9 +258,9 @@ asyncTest('a[data-remote][data-disable-with] re-enables when `ajax:beforeSend` e
App.checkEnabledState(link, 'Click me')
link
.bindNative('ajax:beforeSend', function() {
.bindNative('ajax:beforeSend', function(e) {
App.checkDisabledState(link, 'clicking...')
return false
e.preventDefault()
})
.triggerNative('click')
@ -293,8 +295,9 @@ asyncTest('form[data-remote] input|button|textarea[data-disable-with] does not d
submit = $('<input type="submit" data-disable-with="submitting ..." name="submit2" value="Submit" />').appendTo(form)
form
.bindNative('ajax:beforeSend', function() {
return false
.bindNative('ajax:beforeSend', function(e) {
e.preventDefault()
e.stopPropagation()
})
.triggerNative('submit')
@ -343,9 +346,9 @@ asyncTest('button[data-remote][data-disable-with] re-enables when `ajax:before`
App.checkEnabledState(button, 'Click me')
button
.bindNative('ajax:before', function() {
.bindNative('ajax:before', function(e) {
App.checkDisabledState(button, 'clicking...')
return false
e.preventDefault()
})
.triggerNative('click')
@ -361,9 +364,9 @@ asyncTest('button[data-remote][data-disable-with] re-enables when `ajax:beforeSe
App.checkEnabledState(button, 'Click me')
button
.bindNative('ajax:beforeSend', function() {
.bindNative('ajax:beforeSend', function(e) {
App.checkDisabledState(button, 'clicking...')
return false
e.preventDefault()
})
.triggerNative('click')

View file

@ -91,7 +91,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()
var form = $('#qunit-fixture form:not([data-remote])').attr('data-remote', 'true'), origFormContents = form.html()
form.bindNative('ajax:success', function() {
form.html(origFormContents)
@ -105,7 +105,7 @@ asyncTest('form[data-remote] input[type=submit][data-disable] is replaced in aja
})
asyncTest('form[data-remote] input[data-disable] is replaced with disabled field in ajax callback', 2, function() {
var form = $('form:not([data-remote])').attr('data-remote', 'true'), input = form.find('input[type=submit]'),
var form = $('#qunit-fixture form:not([data-remote])').attr('data-remote', 'true'), input = form.find('input[type=submit]'),
newDisabledInput = input.clone().attr('disabled', 'disabled')
form.bindNative('ajax:success', function() {
@ -168,9 +168,9 @@ asyncTest('a[data-remote][data-disable] re-enables when `ajax:before` event is c
App.checkEnabledState(link, 'Click me')
link
.bindNative('ajax:before', function() {
.bindNative('ajax:before', function(e) {
App.checkDisabledState(link, 'Click me')
return false
e.preventDefault()
})
.triggerNative('click')
@ -186,9 +186,9 @@ asyncTest('a[data-remote][data-disable] re-enables when `ajax:beforeSend` event
App.checkEnabledState(link, 'Click me')
link
.bindNative('ajax:beforeSend', function() {
.bindNative('ajax:beforeSend', function(e) {
App.checkDisabledState(link, 'Click me')
return false
e.preventDefault()
})
.triggerNative('click')
@ -223,8 +223,9 @@ asyncTest('form[data-remote] input|button|textarea[data-disable] does not disabl
submit = $('<input type="submit" data-disable="submitting ..." name="submit2" value="Submit" />').appendTo(form)
form
.bindNative('ajax:beforeSend', function() {
return false
.bindNative('ajax:beforeSend', function(e) {
e.preventDefault()
e.stopPropagation()
})
.triggerNative('submit')
@ -273,9 +274,9 @@ asyncTest('button[data-remote][data-disable] re-enables when `ajax:before` event
App.checkEnabledState(button, 'Click me')
button
.bindNative('ajax:before', function() {
.bindNative('ajax:before', function(e) {
App.checkDisabledState(button, 'Click me')
return false
e.preventDefault()
})
.triggerNative('click')
@ -291,9 +292,9 @@ asyncTest('button[data-remote][data-disable] re-enables when `ajax:beforeSend` e
App.checkEnabledState(button, 'Click me')
button
.bindNative('ajax:beforeSend', function() {
.bindNative('ajax:beforeSend', function(e) {
App.checkDisabledState(button, 'Click me')
return false
e.preventDefault()
})
.triggerNative('click')

View file

@ -272,9 +272,10 @@ asyncTest('returning false in form\'s submit bindings in non-submit-bubbling bro
form
.append($('<input type="submit" />'))
.bindNative('submit', function() {
.bindNative('submit', function(e) {
ok(true, 'binding handler is called')
return false
e.preventDefault()
e.stopPropagation()
})
.bindNative('ajax:beforeSend', function() {
ok(false, 'form should not be submitted')
@ -296,8 +297,8 @@ asyncTest('clicking on a link with falsy "data-remote" attribute does not fire a
.bindNative('ajax:beforeSend', function() {
ok(false, 'ajax should not be triggered')
})
.bindNative('click', function() {
return false
.bindNative('click', function(e) {
e.preventDefault()
})
.triggerNative('click')
@ -314,8 +315,8 @@ asyncTest('ctrl-clicking on a link with falsy "data-remote" attribute does not f
.bindNative('ajax:beforeSend', function() {
ok(false, 'ajax should not be triggered')
})
.bindNative('click', function() {
return false
.bindNative('click', function(e) {
e.preventDefault()
})
.triggerNative('click', { metaKey: true })
@ -333,8 +334,8 @@ asyncTest('clicking on a button with falsy "data-remote" attribute', 0, function
.bindNative('ajax:beforeSend', function() {
ok(false, 'ajax should not be triggered')
})
.bindNative('click', function() {
return false
.bindNative('click', function(e) {
e.preventDefault()
})
.triggerNative('click')
@ -347,8 +348,8 @@ asyncTest('submitting a form with falsy "data-remote" attribute', 0, function()
.bindNative('ajax:beforeSend', function() {
ok(false, 'ajax should not be triggered')
})
.bindNative('submit', function() {
return false
.bindNative('submit', function(e) {
e.preventDefault()
})
.triggerNative('submit')
@ -429,7 +430,7 @@ asyncTest('changing a select option without "data-url" attribute still fires aja
ajaxLocation = settings.url.replace(settings.data, '').replace(/&$/, '').replace(/\?$/, '')
equal(ajaxLocation, currentLocation, 'URL should be current page by default')
return false
e.preventDefault()
})
.val('optionValue2')
.triggerNative('change')

View file

@ -25,7 +25,7 @@ asyncTest('the getter for an element\'s href is overridable', 1, function() {
$('#qunit-fixture a')
.bindNative('ajax:beforeSend', function(e, xhr, options) {
equal('/data/href', options.url)
return false
e.preventDefault()
})
.triggerNative('click')
start()
@ -35,7 +35,7 @@ asyncTest('the getter for an element\'s href works normally if not overridden',
$('#qunit-fixture a')
.bindNative('ajax:beforeSend', function(e, xhr, options) {
equal(location.protocol + '//' + location.host + '/real/href', options.url)
return false
e.preventDefault()
})
.triggerNative('click')
start()

View file

@ -103,14 +103,16 @@ $.fn.extend({
bindNative: function(event, handler) {
if (!handler) return this
this.bind(event, function(e) {
var el = this[0]
el.addEventListener(event, function(e) {
var args = []
if (e.originalEvent.detail) {
args = e.originalEvent.detail.slice()
if (e.detail) {
args = e.detail.slice()
}
args.unshift(e)
return handler.apply(this, args)
})
return handler.apply(el, args)
}, false)
return this
}
})

View file

@ -382,10 +382,9 @@ have been bundled into `event.detail`. For information about the previously used
`jquery-ujs` in Rails 5 and earlier, read the [`jquery-ujs` wiki](https://github.com/rails/jquery-ujs/wiki/ajax).
### Stoppable events
If you stop `ajax:before` or `ajax:beforeSend` by returning false from the
handler method, the Ajax request will never take place. The `ajax:before` event
can manipulate form data before serialization and the
You can stop execution of the Ajax request by running `event.preventDefault()`
from the handlers methods `ajax:before` or `ajax:beforeSend`.
The `ajax:before` event can manipulate form data before serialization and the
`ajax:beforeSend` event is useful for adding custom request headers.
If you stop the `ajax:aborted:file` event, the default behavior of allowing the
@ -393,6 +392,9 @@ browser to submit the form via normal means (i.e. non-Ajax submission) will be
canceled and the form will not be submitted at all. This is useful for
implementing your own Ajax file upload workaround.
Note, you should use `return false` to prevent event for `jquery-ujs` and
`e.preventDefault()` for `rails-ujs`
Server-Side Concerns
--------------------