aboutsummaryrefslogtreecommitdiffstats
path: root/actionview/app
diff options
context:
space:
mode:
authorPatrick Toomey <ptoomey3@biasedcoin.com>2017-03-09 23:06:18 -0700
committerPatrick Toomey <ptoomey3@biasedcoin.com>2017-03-09 23:06:18 -0700
commit9ca712348e547815d04a6e1e13b9faf71ebce987 (patch)
treedda05f1c91dc19e8ef5a92e618a891af125a8e8a /actionview/app
parent9f9e57339bb88fcf5f8e47a048d8201b97cd5f53 (diff)
downloadrails-9ca712348e547815d04a6e1e13b9faf71ebce987.tar.gz
rails-9ca712348e547815d04a6e1e13b9faf71ebce987.tar.bz2
rails-9ca712348e547815d04a6e1e13b9faf71ebce987.zip
Prevent event propogation if element is disabled when event chain begins.
The existing UJS event behavior relies on browsers not sending events for various events when an element is disabled. For example, imagine the following: <button type="submit" disabled="disabled">Click me</button> The above button is disabled, so browsers will not trigger a click event and all UJS behavior is prevented. However, imagine a button like this: <button type="submit" disabled="disabled"><strong>Click me</strong></button> The above is treated differently by browsers such as Chrome/Safari. These browsers do not consider the strong tag to be disabled, and will trigger click events. UJS has logic to walk up the DOM to find an associated element subject to UJS behavior. But, this logic does not take into account the disabled status of the element. I originally thought we could simply change the selectors used to match elements to ignore disabled elements. However, UJS disables some elements as part of the event chain. So, an element might match early in the chain and then fail to match later. Instead of changing the selectors I added a callback to the chain that calls `stopEverything` if an element is disabled when the event chain begins.
Diffstat (limited to 'actionview/app')
-rw-r--r--actionview/app/assets/javascripts/features/disable.coffee4
-rw-r--r--actionview/app/assets/javascripts/rails-ujs.coffee7
2 files changed, 10 insertions, 1 deletions
diff --git a/actionview/app/assets/javascripts/features/disable.coffee b/actionview/app/assets/javascripts/features/disable.coffee
index e8cce7da40..90aa3bdf0e 100644
--- a/actionview/app/assets/javascripts/features/disable.coffee
+++ b/actionview/app/assets/javascripts/features/disable.coffee
@@ -2,6 +2,10 @@
{ matches, getData, setData, stopEverything, formElements } = Rails
+Rails.handleDisabledElement = (e) ->
+ element = this
+ stopEverything(e) if element.disabled
+
# Unified function to enable an element (link, button and form)
Rails.enableElement = (e) ->
element = if e instanceof Event then e.target else e
diff --git a/actionview/app/assets/javascripts/rails-ujs.coffee b/actionview/app/assets/javascripts/rails-ujs.coffee
index df889ce067..afe7d6f7a3 100644
--- a/actionview/app/assets/javascripts/rails-ujs.coffee
+++ b/actionview/app/assets/javascripts/rails-ujs.coffee
@@ -12,7 +12,7 @@
fire, delegate
getData, $
refreshCSRFTokens, CSRFProtection
- enableElement, disableElement
+ enableElement, disableElement, handleDisabledElement
handleConfirm
handleRemote, formSubmitButtonClick, handleMetaClick
handleMethod
@@ -44,19 +44,23 @@ Rails.start = ->
delegate document, Rails.buttonDisableSelector, 'ajax:complete', enableElement
delegate document, Rails.buttonDisableSelector, 'ajax:stopped', enableElement
+ delegate document, Rails.linkClickSelector, 'click', handleDisabledElement
delegate document, Rails.linkClickSelector, 'click', handleConfirm
delegate document, Rails.linkClickSelector, 'click', handleMetaClick
delegate document, Rails.linkClickSelector, 'click', disableElement
delegate document, Rails.linkClickSelector, 'click', handleRemote
delegate document, Rails.linkClickSelector, 'click', handleMethod
+ delegate document, Rails.buttonClickSelector, 'click', handleDisabledElement
delegate document, Rails.buttonClickSelector, 'click', handleConfirm
delegate document, Rails.buttonClickSelector, 'click', disableElement
delegate document, Rails.buttonClickSelector, 'click', handleRemote
+ delegate document, Rails.inputChangeSelector, 'change', handleDisabledElement
delegate document, Rails.inputChangeSelector, 'change', handleConfirm
delegate document, Rails.inputChangeSelector, 'change', handleRemote
+ delegate document, Rails.formSubmitSelector, 'submit', handleDisabledElement
delegate document, Rails.formSubmitSelector, 'submit', handleConfirm
delegate document, Rails.formSubmitSelector, 'submit', handleRemote
# Normal mode submit
@@ -65,6 +69,7 @@ Rails.start = ->
delegate document, Rails.formSubmitSelector, 'ajax:send', disableElement
delegate document, Rails.formSubmitSelector, 'ajax:complete', enableElement
+ delegate document, Rails.formInputClickSelector, 'click', handleDisabledElement
delegate document, Rails.formInputClickSelector, 'click', handleConfirm
delegate document, Rails.formInputClickSelector, 'click', formSubmitButtonClick