From 11341fdb3a1664ba58edf729ed46e04cd0e20ed6 Mon Sep 17 00:00:00 2001 From: Javan Makhmali Date: Thu, 30 Mar 2017 14:41:17 -0400 Subject: Reorganize rails-ujs files --- actionview/app/assets/javascripts/config.coffee | 34 -------- .../app/assets/javascripts/features/confirm.coffee | 26 ------ .../app/assets/javascripts/features/disable.coffee | 82 ------------------ .../app/assets/javascripts/features/method.coffee | 34 -------- .../app/assets/javascripts/features/remote.coffee | 90 -------------------- actionview/app/assets/javascripts/rails-ujs.coffee | 99 +++++++--------------- .../app/assets/javascripts/rails-ujs/BANNER.js | 5 ++ .../javascripts/rails-ujs/features/confirm.coffee | 26 ++++++ .../javascripts/rails-ujs/features/disable.coffee | 82 ++++++++++++++++++ .../javascripts/rails-ujs/features/method.coffee | 34 ++++++++ .../javascripts/rails-ujs/features/remote.coffee | 90 ++++++++++++++++++++ .../app/assets/javascripts/rails-ujs/start.coffee | 70 +++++++++++++++ .../assets/javascripts/rails-ujs/utils/ajax.coffee | 95 +++++++++++++++++++++ .../assets/javascripts/rails-ujs/utils/csrf.coffee | 25 ++++++ .../assets/javascripts/rails-ujs/utils/dom.coffee | 28 ++++++ .../javascripts/rails-ujs/utils/event.coffee | 40 +++++++++ .../assets/javascripts/rails-ujs/utils/form.coffee | 36 ++++++++ .../app/assets/javascripts/utils/ajax.coffee | 95 --------------------- .../app/assets/javascripts/utils/csrf.coffee | 25 ------ actionview/app/assets/javascripts/utils/dom.coffee | 28 ------ .../app/assets/javascripts/utils/event.coffee | 40 --------- .../app/assets/javascripts/utils/form.coffee | 36 -------- 22 files changed, 560 insertions(+), 560 deletions(-) delete mode 100644 actionview/app/assets/javascripts/config.coffee delete mode 100644 actionview/app/assets/javascripts/features/confirm.coffee delete mode 100644 actionview/app/assets/javascripts/features/disable.coffee delete mode 100644 actionview/app/assets/javascripts/features/method.coffee delete mode 100644 actionview/app/assets/javascripts/features/remote.coffee create mode 100644 actionview/app/assets/javascripts/rails-ujs/BANNER.js create mode 100644 actionview/app/assets/javascripts/rails-ujs/features/confirm.coffee create mode 100644 actionview/app/assets/javascripts/rails-ujs/features/disable.coffee create mode 100644 actionview/app/assets/javascripts/rails-ujs/features/method.coffee create mode 100644 actionview/app/assets/javascripts/rails-ujs/features/remote.coffee create mode 100644 actionview/app/assets/javascripts/rails-ujs/start.coffee create mode 100644 actionview/app/assets/javascripts/rails-ujs/utils/ajax.coffee create mode 100644 actionview/app/assets/javascripts/rails-ujs/utils/csrf.coffee create mode 100644 actionview/app/assets/javascripts/rails-ujs/utils/dom.coffee create mode 100644 actionview/app/assets/javascripts/rails-ujs/utils/event.coffee create mode 100644 actionview/app/assets/javascripts/rails-ujs/utils/form.coffee delete mode 100644 actionview/app/assets/javascripts/utils/ajax.coffee delete mode 100644 actionview/app/assets/javascripts/utils/csrf.coffee delete mode 100644 actionview/app/assets/javascripts/utils/dom.coffee delete mode 100644 actionview/app/assets/javascripts/utils/event.coffee delete mode 100644 actionview/app/assets/javascripts/utils/form.coffee (limited to 'actionview/app') diff --git a/actionview/app/assets/javascripts/config.coffee b/actionview/app/assets/javascripts/config.coffee deleted file mode 100644 index a93325e903..0000000000 --- a/actionview/app/assets/javascripts/config.coffee +++ /dev/null @@ -1,34 +0,0 @@ -#= export Rails - -@Rails = - # Link elements bound by rails-ujs - linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote]:not([disabled]), a[data-disable-with], a[data-disable]' - - # Button elements bound by rails-ujs - buttonClickSelector: - selector: 'button[data-remote]:not([form]), button[data-confirm]:not([form])' - exclude: 'form button' - - # Select elements bound by rails-ujs - inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]' - - # Form elements bound by rails-ujs - formSubmitSelector: 'form' - - # Form input elements bound by rails-ujs - 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])' - - # Form input elements disabled during form submission - formDisableSelector: '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' - - # Form input elements re-enabled after form submission - formEnableSelector: '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' - - # Form file input elements - fileInputSelector: 'input[name][type=file]:not([disabled])' - - # Link onClick disable selector with possible reenable after remote submission - linkDisableSelector: 'a[data-disable-with], a[data-disable]' - - # Button onClick disable selector with possible reenable after remote submission - buttonDisableSelector: 'button[data-remote][data-disable-with], button[data-remote][data-disable]' diff --git a/actionview/app/assets/javascripts/features/confirm.coffee b/actionview/app/assets/javascripts/features/confirm.coffee deleted file mode 100644 index 72b5aaa218..0000000000 --- a/actionview/app/assets/javascripts/features/confirm.coffee +++ /dev/null @@ -1,26 +0,0 @@ -#= require_tree ../utils - -{ fire, stopEverything } = Rails - -Rails.handleConfirm = (e) -> - stopEverything(e) unless allowAction(this) - -# For 'data-confirm' attribute: -# - Fires `confirm` event -# - Shows the confirmation dialog -# - Fires the `confirm:complete` event -# -# Returns `true` if no function stops the chain and user chose yes `false` otherwise. -# Attaching a handler to the element's `confirm` event that returns a `falsy` value cancels the confirmation dialog. -# Attaching a handler to the element's `confirm:complete` event that returns a `falsy` value makes this function -# return false. The `confirm:complete` event is fired whether or not the user answered true or false to the dialog. -allowAction = (element) -> - message = element.getAttribute('data-confirm') - return true unless message - - answer = false - if fire(element, 'confirm') - try answer = confirm(message) - callback = fire(element, 'confirm:complete', [answer]) - - answer and callback diff --git a/actionview/app/assets/javascripts/features/disable.coffee b/actionview/app/assets/javascripts/features/disable.coffee deleted file mode 100644 index 90aa3bdf0e..0000000000 --- a/actionview/app/assets/javascripts/features/disable.coffee +++ /dev/null @@ -1,82 +0,0 @@ -#= require_tree ../utils - -{ 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 - if matches(element, Rails.linkDisableSelector) - enableLinkElement(element) - else if matches(element, Rails.buttonDisableSelector) or matches(element, Rails.formEnableSelector) - enableFormElement(element) - else if matches(element, Rails.formSubmitSelector) - enableFormElements(element) - -# Unified function to disable an element (link, button and form) -Rails.disableElement = (e) -> - element = if e instanceof Event then e.target else e - if matches(element, Rails.linkDisableSelector) - disableLinkElement(element) - else if matches(element, Rails.buttonDisableSelector) or matches(element, Rails.formDisableSelector) - disableFormElement(element) - else if matches(element, Rails.formSubmitSelector) - disableFormElements(element) - -# Replace element's html with the 'data-disable-with' after storing original html -# and prevent clicking on it -disableLinkElement = (element) -> - replacement = element.getAttribute('data-disable-with') - if replacement? - setData(element, 'ujs:enable-with', element.innerHTML) # store enabled state - element.innerHTML = replacement - element.addEventListener('click', stopEverything) # prevent further clicking - setData(element, 'ujs:disabled', true) - -# Restore element to its original state which was disabled by 'disableLinkElement' above -enableLinkElement = (element) -> - originalText = getData(element, 'ujs:enable-with') - if originalText? - element.innerHTML = originalText # set to old enabled state - setData(element, 'ujs:enable-with', null) # clean up cache - element.removeEventListener('click', stopEverything) # enable element - setData(element, 'ujs:disabled', null) - -# Disables form elements: -# - Caches element value in 'ujs:enable-with' data store -# - Replaces element text with value of 'data-disable-with' attribute -# - Sets disabled property to true -disableFormElements = (form) -> - formElements(form, Rails.formDisableSelector).forEach(disableFormElement) - -disableFormElement = (element) -> - replacement = element.getAttribute('data-disable-with') - if replacement? - if matches(element, 'button') - setData(element, 'ujs:enable-with', element.innerHTML) - element.innerHTML = replacement - else - setData(element, 'ujs:enable-with', element.value) - element.value = replacement - element.disabled = true - setData(element, 'ujs:disabled', true) - -# Re-enables disabled form elements: -# - Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`) -# - Sets disabled property to false -enableFormElements = (form) -> - formElements(form, Rails.formEnableSelector).forEach(enableFormElement) - -enableFormElement = (element) -> - originalText = getData(element, 'ujs:enable-with') - if originalText? - if matches(element, 'button') - element.innerHTML = originalText - else - element.value = originalText - setData(element, 'ujs:enable-with', null) # clean up cache - element.disabled = false - setData(element, 'ujs:disabled', null) diff --git a/actionview/app/assets/javascripts/features/method.coffee b/actionview/app/assets/javascripts/features/method.coffee deleted file mode 100644 index d04d9414dd..0000000000 --- a/actionview/app/assets/javascripts/features/method.coffee +++ /dev/null @@ -1,34 +0,0 @@ -#= require_tree ../utils - -{ stopEverything } = Rails - -# Handles "data-method" on links such as: -# Delete -Rails.handleMethod = (e) -> - link = this - method = link.getAttribute('data-method') - return unless method - - href = Rails.href(link) - csrfToken = Rails.csrfToken() - csrfParam = Rails.csrfParam() - form = document.createElement('form') - formContent = "" - - if csrfParam? and csrfToken? and not Rails.isCrossDomain(href) - formContent += "" - - # Must trigger submit by click on a button, else "submit" event handler won't work! - # https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit - formContent += '' - - form.method = 'post' - form.action = href - form.target = link.target - form.innerHTML = formContent - form.style.display = 'none' - - document.body.appendChild(form) - form.querySelector('[type="submit"]').click() - - stopEverything(e) diff --git a/actionview/app/assets/javascripts/features/remote.coffee b/actionview/app/assets/javascripts/features/remote.coffee deleted file mode 100644 index 852587042c..0000000000 --- a/actionview/app/assets/javascripts/features/remote.coffee +++ /dev/null @@ -1,90 +0,0 @@ -#= require_tree ../utils - -{ - matches, getData, setData - fire, stopEverything - ajax, isCrossDomain - serializeElement -} = Rails - -# Checks "data-remote" if true to handle the request through a XHR request. -isRemote = (element) -> - value = element.getAttribute('data-remote') - value? and value isnt 'false' - -# Submits "remote" forms and links with ajax -Rails.handleRemote = (e) -> - element = this - - return true unless isRemote(element) - unless fire(element, 'ajax:before') - fire(element, 'ajax:stopped') - return false - - withCredentials = element.getAttribute('data-with-credentials') - dataType = element.getAttribute('data-type') or 'script' - - if matches(element, Rails.formSubmitSelector) - # memoized value from clicked submit button - button = getData(element, 'ujs:submit-button') - method = getData(element, 'ujs:submit-button-formmethod') or element.method - url = getData(element, 'ujs:submit-button-formaction') or element.getAttribute('action') or location.href - - # strip query string if it's a GET request - url = url.replace(/\?.*$/, '') if method.toUpperCase() is 'GET' - - if element.enctype is 'multipart/form-data' - data = new FormData(element) - data.append(button.name, button.value) if button? - else - data = serializeElement(element, button) - - setData(element, 'ujs:submit-button', null) - setData(element, 'ujs:submit-button-formmethod', null) - setData(element, 'ujs:submit-button-formaction', null) - else if matches(element, Rails.buttonClickSelector) or matches(element, Rails.inputChangeSelector) - method = element.getAttribute('data-method') - url = element.getAttribute('data-url') - data = serializeElement(element, element.getAttribute('data-params')) - else - method = element.getAttribute('data-method') - url = Rails.href(element) - data = element.getAttribute('data-params') - - ajax( - type: method or 'GET' - url: url - data: data - dataType: dataType - # stopping the "ajax:beforeSend" event will cancel the ajax request - beforeSend: (xhr, options) -> - if fire(element, 'ajax:beforeSend', [xhr, options]) - fire(element, 'ajax:send', [xhr]) - else - fire(element, 'ajax:stopped') - xhr.abort() - success: (args...) -> fire(element, 'ajax:success', args) - error: (args...) -> fire(element, 'ajax:error', args) - complete: (args...) -> fire(element, 'ajax:complete', args) - crossDomain: isCrossDomain(url) - withCredentials: withCredentials? and withCredentials isnt 'false' - ) - stopEverything(e) - -Rails.formSubmitButtonClick = (e) -> - button = this - form = button.form - return unless form - # Register the pressed submit button - setData(form, 'ujs:submit-button', name: button.name, value: button.value) if button.name - # Save attributes from button - setData(form, 'ujs:formnovalidate-button', button.formNoValidate) - setData(form, 'ujs:submit-button-formaction', button.getAttribute('formaction')) - setData(form, 'ujs:submit-button-formmethod', button.getAttribute('formmethod')) - -Rails.handleMetaClick = (e) -> - link = this - method = (link.getAttribute('data-method') or 'GET').toUpperCase() - data = link.getAttribute('data-params') - metaClick = e.metaKey or e.ctrlKey - e.stopImmediatePropagation() if metaClick and method is 'GET' and not data diff --git a/actionview/app/assets/javascripts/rails-ujs.coffee b/actionview/app/assets/javascripts/rails-ujs.coffee index 0c47e1bc60..bd6e9bb881 100644 --- a/actionview/app/assets/javascripts/rails-ujs.coffee +++ b/actionview/app/assets/javascripts/rails-ujs.coffee @@ -1,80 +1,39 @@ -# -# Unobtrusive JavaScript -# https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts -# -# Released under the MIT license -# -#= require ./config -#= require_tree ./utils -#= require_tree ./features +#= require ./rails-ujs/BANNER +#= export Rails +#= require_self +#= require_tree ./rails-ujs/utils +#= require_tree ./rails-ujs/features +#= require ./rails-ujs/start -{ - fire, delegate - getData, $ - refreshCSRFTokens, CSRFProtection - enableElement, disableElement, handleDisabledElement - handleConfirm - handleRemote, formSubmitButtonClick, handleMetaClick - handleMethod -} = Rails +@Rails = + # Link elements bound by rails-ujs + linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote]:not([disabled]), a[data-disable-with], a[data-disable]' -# For backward compatibility -if jQuery? and not jQuery.rails - jQuery.rails = Rails - jQuery.ajaxPrefilter (options, originalOptions, xhr) -> - CSRFProtection(xhr) unless options.crossDomain + # Button elements bound by rails-ujs + buttonClickSelector: + selector: 'button[data-remote]:not([form]), button[data-confirm]:not([form])' + exclude: 'form button' -Rails.start = -> - # Cut down on the number of issues from people inadvertently including - # rails-ujs twice by detecting and raising an error when it happens. - throw new Error('rails-ujs has already been loaded!') if window._rails_loaded + # Select elements bound by rails-ujs + inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]' - # This event works the same as the load event, except that it fires every - # time the page is loaded. - # See https://github.com/rails/jquery-ujs/issues/357 - # See https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching - window.addEventListener 'pageshow', -> - $(Rails.formEnableSelector).forEach (el) -> - enableElement(el) if getData(el, 'ujs:disabled') - $(Rails.linkDisableSelector).forEach (el) -> - enableElement(el) if getData(el, 'ujs:disabled') + # Form elements bound by rails-ujs + formSubmitSelector: 'form' - delegate document, Rails.linkDisableSelector, 'ajax:complete', enableElement - delegate document, Rails.linkDisableSelector, 'ajax:stopped', enableElement - delegate document, Rails.buttonDisableSelector, 'ajax:complete', enableElement - delegate document, Rails.buttonDisableSelector, 'ajax:stopped', enableElement + # Form input elements bound by rails-ujs + 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])' - 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 + # Form input elements disabled during form submission + formDisableSelector: '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' - delegate document, Rails.buttonClickSelector, 'click', handleDisabledElement - delegate document, Rails.buttonClickSelector, 'click', handleConfirm - delegate document, Rails.buttonClickSelector, 'click', disableElement - delegate document, Rails.buttonClickSelector, 'click', handleRemote + # Form input elements re-enabled after form submission + formEnableSelector: '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' - delegate document, Rails.inputChangeSelector, 'change', handleDisabledElement - delegate document, Rails.inputChangeSelector, 'change', handleConfirm - delegate document, Rails.inputChangeSelector, 'change', handleRemote + # Form file input elements + fileInputSelector: 'input[name][type=file]:not([disabled])' - delegate document, Rails.formSubmitSelector, 'submit', handleDisabledElement - delegate document, Rails.formSubmitSelector, 'submit', handleConfirm - delegate document, Rails.formSubmitSelector, 'submit', handleRemote - # Normal mode submit - # Slight timeout so that the submit button gets properly serialized - delegate document, Rails.formSubmitSelector, 'submit', (e) -> setTimeout((-> disableElement(e)), 13) - delegate document, Rails.formSubmitSelector, 'ajax:send', disableElement - delegate document, Rails.formSubmitSelector, 'ajax:complete', enableElement + # Link onClick disable selector with possible reenable after remote submission + linkDisableSelector: 'a[data-disable-with], a[data-disable]' - delegate document, Rails.formInputClickSelector, 'click', handleDisabledElement - delegate document, Rails.formInputClickSelector, 'click', handleConfirm - delegate document, Rails.formInputClickSelector, 'click', formSubmitButtonClick - - document.addEventListener('DOMContentLoaded', refreshCSRFTokens) - window._rails_loaded = true - -if window.Rails is Rails and fire(document, 'rails:attachBindings') - Rails.start() + # Button onClick disable selector with possible reenable after remote submission + buttonDisableSelector: 'button[data-remote][data-disable-with], button[data-remote][data-disable]' diff --git a/actionview/app/assets/javascripts/rails-ujs/BANNER.js b/actionview/app/assets/javascripts/rails-ujs/BANNER.js new file mode 100644 index 0000000000..47ecd66003 --- /dev/null +++ b/actionview/app/assets/javascripts/rails-ujs/BANNER.js @@ -0,0 +1,5 @@ +/* +Unobtrusive JavaScript +https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts +Released under the MIT license + */ diff --git a/actionview/app/assets/javascripts/rails-ujs/features/confirm.coffee b/actionview/app/assets/javascripts/rails-ujs/features/confirm.coffee new file mode 100644 index 0000000000..72b5aaa218 --- /dev/null +++ b/actionview/app/assets/javascripts/rails-ujs/features/confirm.coffee @@ -0,0 +1,26 @@ +#= require_tree ../utils + +{ fire, stopEverything } = Rails + +Rails.handleConfirm = (e) -> + stopEverything(e) unless allowAction(this) + +# For 'data-confirm' attribute: +# - Fires `confirm` event +# - Shows the confirmation dialog +# - Fires the `confirm:complete` event +# +# Returns `true` if no function stops the chain and user chose yes `false` otherwise. +# Attaching a handler to the element's `confirm` event that returns a `falsy` value cancels the confirmation dialog. +# Attaching a handler to the element's `confirm:complete` event that returns a `falsy` value makes this function +# return false. The `confirm:complete` event is fired whether or not the user answered true or false to the dialog. +allowAction = (element) -> + message = element.getAttribute('data-confirm') + return true unless message + + answer = false + if fire(element, 'confirm') + try answer = confirm(message) + callback = fire(element, 'confirm:complete', [answer]) + + answer and callback diff --git a/actionview/app/assets/javascripts/rails-ujs/features/disable.coffee b/actionview/app/assets/javascripts/rails-ujs/features/disable.coffee new file mode 100644 index 0000000000..90aa3bdf0e --- /dev/null +++ b/actionview/app/assets/javascripts/rails-ujs/features/disable.coffee @@ -0,0 +1,82 @@ +#= require_tree ../utils + +{ 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 + if matches(element, Rails.linkDisableSelector) + enableLinkElement(element) + else if matches(element, Rails.buttonDisableSelector) or matches(element, Rails.formEnableSelector) + enableFormElement(element) + else if matches(element, Rails.formSubmitSelector) + enableFormElements(element) + +# Unified function to disable an element (link, button and form) +Rails.disableElement = (e) -> + element = if e instanceof Event then e.target else e + if matches(element, Rails.linkDisableSelector) + disableLinkElement(element) + else if matches(element, Rails.buttonDisableSelector) or matches(element, Rails.formDisableSelector) + disableFormElement(element) + else if matches(element, Rails.formSubmitSelector) + disableFormElements(element) + +# Replace element's html with the 'data-disable-with' after storing original html +# and prevent clicking on it +disableLinkElement = (element) -> + replacement = element.getAttribute('data-disable-with') + if replacement? + setData(element, 'ujs:enable-with', element.innerHTML) # store enabled state + element.innerHTML = replacement + element.addEventListener('click', stopEverything) # prevent further clicking + setData(element, 'ujs:disabled', true) + +# Restore element to its original state which was disabled by 'disableLinkElement' above +enableLinkElement = (element) -> + originalText = getData(element, 'ujs:enable-with') + if originalText? + element.innerHTML = originalText # set to old enabled state + setData(element, 'ujs:enable-with', null) # clean up cache + element.removeEventListener('click', stopEverything) # enable element + setData(element, 'ujs:disabled', null) + +# Disables form elements: +# - Caches element value in 'ujs:enable-with' data store +# - Replaces element text with value of 'data-disable-with' attribute +# - Sets disabled property to true +disableFormElements = (form) -> + formElements(form, Rails.formDisableSelector).forEach(disableFormElement) + +disableFormElement = (element) -> + replacement = element.getAttribute('data-disable-with') + if replacement? + if matches(element, 'button') + setData(element, 'ujs:enable-with', element.innerHTML) + element.innerHTML = replacement + else + setData(element, 'ujs:enable-with', element.value) + element.value = replacement + element.disabled = true + setData(element, 'ujs:disabled', true) + +# Re-enables disabled form elements: +# - Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`) +# - Sets disabled property to false +enableFormElements = (form) -> + formElements(form, Rails.formEnableSelector).forEach(enableFormElement) + +enableFormElement = (element) -> + originalText = getData(element, 'ujs:enable-with') + if originalText? + if matches(element, 'button') + element.innerHTML = originalText + else + element.value = originalText + setData(element, 'ujs:enable-with', null) # clean up cache + element.disabled = false + setData(element, 'ujs:disabled', null) diff --git a/actionview/app/assets/javascripts/rails-ujs/features/method.coffee b/actionview/app/assets/javascripts/rails-ujs/features/method.coffee new file mode 100644 index 0000000000..d04d9414dd --- /dev/null +++ b/actionview/app/assets/javascripts/rails-ujs/features/method.coffee @@ -0,0 +1,34 @@ +#= require_tree ../utils + +{ stopEverything } = Rails + +# Handles "data-method" on links such as: +# Delete +Rails.handleMethod = (e) -> + link = this + method = link.getAttribute('data-method') + return unless method + + href = Rails.href(link) + csrfToken = Rails.csrfToken() + csrfParam = Rails.csrfParam() + form = document.createElement('form') + formContent = "" + + if csrfParam? and csrfToken? and not Rails.isCrossDomain(href) + formContent += "" + + # Must trigger submit by click on a button, else "submit" event handler won't work! + # https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit + formContent += '' + + form.method = 'post' + form.action = href + form.target = link.target + form.innerHTML = formContent + form.style.display = 'none' + + document.body.appendChild(form) + form.querySelector('[type="submit"]').click() + + stopEverything(e) diff --git a/actionview/app/assets/javascripts/rails-ujs/features/remote.coffee b/actionview/app/assets/javascripts/rails-ujs/features/remote.coffee new file mode 100644 index 0000000000..852587042c --- /dev/null +++ b/actionview/app/assets/javascripts/rails-ujs/features/remote.coffee @@ -0,0 +1,90 @@ +#= require_tree ../utils + +{ + matches, getData, setData + fire, stopEverything + ajax, isCrossDomain + serializeElement +} = Rails + +# Checks "data-remote" if true to handle the request through a XHR request. +isRemote = (element) -> + value = element.getAttribute('data-remote') + value? and value isnt 'false' + +# Submits "remote" forms and links with ajax +Rails.handleRemote = (e) -> + element = this + + return true unless isRemote(element) + unless fire(element, 'ajax:before') + fire(element, 'ajax:stopped') + return false + + withCredentials = element.getAttribute('data-with-credentials') + dataType = element.getAttribute('data-type') or 'script' + + if matches(element, Rails.formSubmitSelector) + # memoized value from clicked submit button + button = getData(element, 'ujs:submit-button') + method = getData(element, 'ujs:submit-button-formmethod') or element.method + url = getData(element, 'ujs:submit-button-formaction') or element.getAttribute('action') or location.href + + # strip query string if it's a GET request + url = url.replace(/\?.*$/, '') if method.toUpperCase() is 'GET' + + if element.enctype is 'multipart/form-data' + data = new FormData(element) + data.append(button.name, button.value) if button? + else + data = serializeElement(element, button) + + setData(element, 'ujs:submit-button', null) + setData(element, 'ujs:submit-button-formmethod', null) + setData(element, 'ujs:submit-button-formaction', null) + else if matches(element, Rails.buttonClickSelector) or matches(element, Rails.inputChangeSelector) + method = element.getAttribute('data-method') + url = element.getAttribute('data-url') + data = serializeElement(element, element.getAttribute('data-params')) + else + method = element.getAttribute('data-method') + url = Rails.href(element) + data = element.getAttribute('data-params') + + ajax( + type: method or 'GET' + url: url + data: data + dataType: dataType + # stopping the "ajax:beforeSend" event will cancel the ajax request + beforeSend: (xhr, options) -> + if fire(element, 'ajax:beforeSend', [xhr, options]) + fire(element, 'ajax:send', [xhr]) + else + fire(element, 'ajax:stopped') + xhr.abort() + success: (args...) -> fire(element, 'ajax:success', args) + error: (args...) -> fire(element, 'ajax:error', args) + complete: (args...) -> fire(element, 'ajax:complete', args) + crossDomain: isCrossDomain(url) + withCredentials: withCredentials? and withCredentials isnt 'false' + ) + stopEverything(e) + +Rails.formSubmitButtonClick = (e) -> + button = this + form = button.form + return unless form + # Register the pressed submit button + setData(form, 'ujs:submit-button', name: button.name, value: button.value) if button.name + # Save attributes from button + setData(form, 'ujs:formnovalidate-button', button.formNoValidate) + setData(form, 'ujs:submit-button-formaction', button.getAttribute('formaction')) + setData(form, 'ujs:submit-button-formmethod', button.getAttribute('formmethod')) + +Rails.handleMetaClick = (e) -> + link = this + method = (link.getAttribute('data-method') or 'GET').toUpperCase() + data = link.getAttribute('data-params') + metaClick = e.metaKey or e.ctrlKey + e.stopImmediatePropagation() if metaClick and method is 'GET' and not data diff --git a/actionview/app/assets/javascripts/rails-ujs/start.coffee b/actionview/app/assets/javascripts/rails-ujs/start.coffee new file mode 100644 index 0000000000..5746a22287 --- /dev/null +++ b/actionview/app/assets/javascripts/rails-ujs/start.coffee @@ -0,0 +1,70 @@ +{ + fire, delegate + getData, $ + refreshCSRFTokens, CSRFProtection + enableElement, disableElement, handleDisabledElement + handleConfirm + handleRemote, formSubmitButtonClick, handleMetaClick + handleMethod +} = Rails + +# For backward compatibility +if jQuery? and not jQuery.rails + jQuery.rails = Rails + jQuery.ajaxPrefilter (options, originalOptions, xhr) -> + CSRFProtection(xhr) unless options.crossDomain + +Rails.start = -> + # Cut down on the number of issues from people inadvertently including + # rails-ujs twice by detecting and raising an error when it happens. + throw new Error('rails-ujs has already been loaded!') if window._rails_loaded + + # This event works the same as the load event, except that it fires every + # time the page is loaded. + # See https://github.com/rails/jquery-ujs/issues/357 + # See https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching + window.addEventListener 'pageshow', -> + $(Rails.formEnableSelector).forEach (el) -> + enableElement(el) if getData(el, 'ujs:disabled') + $(Rails.linkDisableSelector).forEach (el) -> + enableElement(el) if getData(el, 'ujs:disabled') + + delegate document, Rails.linkDisableSelector, 'ajax:complete', enableElement + delegate document, Rails.linkDisableSelector, 'ajax:stopped', enableElement + 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 + # Slight timeout so that the submit button gets properly serialized + delegate document, Rails.formSubmitSelector, 'submit', (e) -> setTimeout((-> disableElement(e)), 13) + 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 + + document.addEventListener('DOMContentLoaded', refreshCSRFTokens) + window._rails_loaded = true + +if window.Rails is Rails and fire(document, 'rails:attachBindings') + Rails.start() diff --git a/actionview/app/assets/javascripts/rails-ujs/utils/ajax.coffee b/actionview/app/assets/javascripts/rails-ujs/utils/ajax.coffee new file mode 100644 index 0000000000..9af515beda --- /dev/null +++ b/actionview/app/assets/javascripts/rails-ujs/utils/ajax.coffee @@ -0,0 +1,95 @@ +#= require ./csrf +#= require ./event + +{ CSRFProtection, fire } = Rails + +AcceptHeaders = + '*': '*/*' + text: 'text/plain' + html: 'text/html' + xml: 'application/xml, text/xml' + json: 'application/json, text/javascript' + script: 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript' + +Rails.ajax = (options) -> + options = prepareOptions(options) + xhr = createXHR options, -> + response = processResponse(xhr.response, xhr.getResponseHeader('Content-Type')) + if xhr.status // 100 == 2 + options.success?(response, xhr.statusText, xhr) + else + options.error?(response, xhr.statusText, xhr) + options.complete?(xhr, xhr.statusText) + # Call beforeSend hook + options.beforeSend?(xhr, options) + # Send the request + if xhr.readyState is XMLHttpRequest.OPENED + xhr.send(options.data) + else + fire(document, 'ajaxStop') # to be compatible with jQuery.ajax + +prepareOptions = (options) -> + options.type = options.type.toUpperCase() + # append data to url if it's a GET request + if options.type is 'GET' and options.data + if options.url.indexOf('?') < 0 + options.url += '?' + options.data + else + options.url += '&' + options.data + # Use "*" as default dataType + options.dataType = '*' unless AcceptHeaders[options.dataType]? + options.accept = AcceptHeaders[options.dataType] + options.accept += ', */*; q=0.01' if options.dataType isnt '*' + options + +createXHR = (options, done) -> + xhr = new XMLHttpRequest() + # Open and setup xhr + xhr.open(options.type, options.url, true) + xhr.setRequestHeader('Accept', options.accept) + # Set Content-Type only when sending a string + # Sending FormData will automatically set Content-Type to multipart/form-data + if typeof options.data is 'string' + xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8') + xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest') unless options.crossDomain + # Add X-CSRF-Token + CSRFProtection(xhr) + xhr.withCredentials = !!options.withCredentials + xhr.onreadystatechange = -> + done(xhr) if xhr.readyState is XMLHttpRequest.DONE + xhr + +processResponse = (response, type) -> + if typeof response is 'string' and typeof type is 'string' + if type.match(/\bjson\b/) + try response = JSON.parse(response) + else if type.match(/\bjavascript\b/) + script = document.createElement('script') + script.innerHTML = response + document.body.appendChild(script) + else if type.match(/\b(xml|html|svg)\b/) + parser = new DOMParser() + type = type.replace(/;.+/, '') # remove something like ';charset=utf-8' + try response = parser.parseFromString(response, type) + response + +# Default way to get an element's href. May be overridden at Rails.href. +Rails.href = (element) -> element.href + +# Determines if the request is a cross domain request. +Rails.isCrossDomain = (url) -> + originAnchor = document.createElement('a') + originAnchor.href = location.href + urlAnchor = document.createElement('a') + try + urlAnchor.href = url + # If URL protocol is false or is a string containing a single colon + # *and* host are false, assume it is not a cross-domain request + # (should only be the case for IE7 and IE compatibility mode). + # Otherwise, evaluate protocol and host of the URL against the origin + # protocol and host. + !(((!urlAnchor.protocol || urlAnchor.protocol == ':') && !urlAnchor.host) || + (originAnchor.protocol + '//' + originAnchor.host == urlAnchor.protocol + '//' + urlAnchor.host)) + catch e + # If there is an error parsing the URL, assume it is crossDomain. + true diff --git a/actionview/app/assets/javascripts/rails-ujs/utils/csrf.coffee b/actionview/app/assets/javascripts/rails-ujs/utils/csrf.coffee new file mode 100644 index 0000000000..4eb5ebb414 --- /dev/null +++ b/actionview/app/assets/javascripts/rails-ujs/utils/csrf.coffee @@ -0,0 +1,25 @@ +#= require ./dom + +{ $ } = Rails + +# Up-to-date Cross-Site Request Forgery token +csrfToken = Rails.csrfToken = -> + meta = document.querySelector('meta[name=csrf-token]') + meta and meta.content + +# URL param that must contain the CSRF token +csrfParam = Rails.csrfParam = -> + meta = document.querySelector('meta[name=csrf-param]') + meta and meta.content + +# Make sure that every Ajax request sends the CSRF token +Rails.CSRFProtection = (xhr) -> + token = csrfToken() + xhr.setRequestHeader('X-CSRF-Token', token) if token? + +# Make sure that all forms have actual up-to-date tokens (cached forms contain old ones) +Rails.refreshCSRFTokens = -> + token = csrfToken() + param = csrfParam() + if token? and param? + $('form input[name="' + param + '"]').forEach (input) -> input.value = token diff --git a/actionview/app/assets/javascripts/rails-ujs/utils/dom.coffee b/actionview/app/assets/javascripts/rails-ujs/utils/dom.coffee new file mode 100644 index 0000000000..6bef618147 --- /dev/null +++ b/actionview/app/assets/javascripts/rails-ujs/utils/dom.coffee @@ -0,0 +1,28 @@ +m = Element.prototype.matches or + Element.prototype.matchesSelector or + Element.prototype.mozMatchesSelector or + Element.prototype.msMatchesSelector or + Element.prototype.oMatchesSelector or + Element.prototype.webkitMatchesSelector + +Rails.matches = (element, selector) -> + if selector.exclude? + m.call(element, selector.selector) and not m.call(element, selector.exclude) + else + m.call(element, selector) + +# get and set data on a given element using "expando properties" +# See: https://developer.mozilla.org/en-US/docs/Glossary/Expando +expando = '_ujsData' + +Rails.getData = (element, key) -> + element[expando]?[key] + +Rails.setData = (element, key, value) -> + element[expando] ?= {} + element[expando][key] = value + +# a wrapper for document.querySelectorAll +# returns an Array +Rails.$ = (selector) -> + Array.prototype.slice.call(document.querySelectorAll(selector)) diff --git a/actionview/app/assets/javascripts/rails-ujs/utils/event.coffee b/actionview/app/assets/javascripts/rails-ujs/utils/event.coffee new file mode 100644 index 0000000000..8d3ff007ea --- /dev/null +++ b/actionview/app/assets/javascripts/rails-ujs/utils/event.coffee @@ -0,0 +1,40 @@ +#= require ./dom + +{ matches } = Rails + +# Polyfill for CustomEvent in IE9+ +# https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill +CustomEvent = window.CustomEvent + +if typeof CustomEvent isnt 'function' + CustomEvent = (event, params) -> + evt = document.createEvent('CustomEvent') + evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail) + evt + CustomEvent.prototype = window.Event.prototype + +# Triggers a custom event on an element and returns false if the event result is false +fire = Rails.fire = (obj, name, data) -> + event = new CustomEvent( + name, + bubbles: true, + cancelable: true, + detail: data, + ) + obj.dispatchEvent(event) + !event.defaultPrevented + +# Helper function, needed to provide consistent behavior in IE +Rails.stopEverything = (e) -> + fire(e.target, 'ujs:everythingStopped') + e.preventDefault() + e.stopPropagation() + e.stopImmediatePropagation() + +Rails.delegate = (element, selector, eventType, handler) -> + element.addEventListener eventType, (e) -> + target = e.target + target = target.parentNode until not (target instanceof Element) or matches(target, selector) + if target instanceof Element and handler.call(target, e) == false + e.preventDefault() + e.stopPropagation() diff --git a/actionview/app/assets/javascripts/rails-ujs/utils/form.coffee b/actionview/app/assets/javascripts/rails-ujs/utils/form.coffee new file mode 100644 index 0000000000..5fa337b518 --- /dev/null +++ b/actionview/app/assets/javascripts/rails-ujs/utils/form.coffee @@ -0,0 +1,36 @@ +#= require ./dom + +{ matches } = Rails + +toArray = (e) -> Array.prototype.slice.call(e) + +Rails.serializeElement = (element, additionalParam) -> + inputs = [element] + inputs = toArray(element.elements) if matches(element, 'form') + params = [] + + inputs.forEach (input) -> + return unless input.name + if matches(input, 'select') + toArray(input.options).forEach (option) -> + params.push(name: input.name, value: option.value) if option.selected + else if input.checked or ['radio', 'checkbox', 'submit'].indexOf(input.type) == -1 + params.push(name: input.name, value: input.value) + + params.push(additionalParam) if additionalParam + + params.map (param) -> + if param.name? + "#{encodeURIComponent(param.name)}=#{encodeURIComponent(param.value)}" + else + param + .join('&') + +# Helper function that returns form elements that match the specified CSS selector +# If form is actually a "form" element this will return associated elements outside the from that have +# the html form attribute set +Rails.formElements = (form, selector) -> + if matches(form, 'form') + toArray(form.elements).filter (el) -> matches(el, selector) + else + toArray(form.querySelectorAll(selector)) diff --git a/actionview/app/assets/javascripts/utils/ajax.coffee b/actionview/app/assets/javascripts/utils/ajax.coffee deleted file mode 100644 index 9af515beda..0000000000 --- a/actionview/app/assets/javascripts/utils/ajax.coffee +++ /dev/null @@ -1,95 +0,0 @@ -#= require ./csrf -#= require ./event - -{ CSRFProtection, fire } = Rails - -AcceptHeaders = - '*': '*/*' - text: 'text/plain' - html: 'text/html' - xml: 'application/xml, text/xml' - json: 'application/json, text/javascript' - script: 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript' - -Rails.ajax = (options) -> - options = prepareOptions(options) - xhr = createXHR options, -> - response = processResponse(xhr.response, xhr.getResponseHeader('Content-Type')) - if xhr.status // 100 == 2 - options.success?(response, xhr.statusText, xhr) - else - options.error?(response, xhr.statusText, xhr) - options.complete?(xhr, xhr.statusText) - # Call beforeSend hook - options.beforeSend?(xhr, options) - # Send the request - if xhr.readyState is XMLHttpRequest.OPENED - xhr.send(options.data) - else - fire(document, 'ajaxStop') # to be compatible with jQuery.ajax - -prepareOptions = (options) -> - options.type = options.type.toUpperCase() - # append data to url if it's a GET request - if options.type is 'GET' and options.data - if options.url.indexOf('?') < 0 - options.url += '?' + options.data - else - options.url += '&' + options.data - # Use "*" as default dataType - options.dataType = '*' unless AcceptHeaders[options.dataType]? - options.accept = AcceptHeaders[options.dataType] - options.accept += ', */*; q=0.01' if options.dataType isnt '*' - options - -createXHR = (options, done) -> - xhr = new XMLHttpRequest() - # Open and setup xhr - xhr.open(options.type, options.url, true) - xhr.setRequestHeader('Accept', options.accept) - # Set Content-Type only when sending a string - # Sending FormData will automatically set Content-Type to multipart/form-data - if typeof options.data is 'string' - xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8') - xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest') unless options.crossDomain - # Add X-CSRF-Token - CSRFProtection(xhr) - xhr.withCredentials = !!options.withCredentials - xhr.onreadystatechange = -> - done(xhr) if xhr.readyState is XMLHttpRequest.DONE - xhr - -processResponse = (response, type) -> - if typeof response is 'string' and typeof type is 'string' - if type.match(/\bjson\b/) - try response = JSON.parse(response) - else if type.match(/\bjavascript\b/) - script = document.createElement('script') - script.innerHTML = response - document.body.appendChild(script) - else if type.match(/\b(xml|html|svg)\b/) - parser = new DOMParser() - type = type.replace(/;.+/, '') # remove something like ';charset=utf-8' - try response = parser.parseFromString(response, type) - response - -# Default way to get an element's href. May be overridden at Rails.href. -Rails.href = (element) -> element.href - -# Determines if the request is a cross domain request. -Rails.isCrossDomain = (url) -> - originAnchor = document.createElement('a') - originAnchor.href = location.href - urlAnchor = document.createElement('a') - try - urlAnchor.href = url - # If URL protocol is false or is a string containing a single colon - # *and* host are false, assume it is not a cross-domain request - # (should only be the case for IE7 and IE compatibility mode). - # Otherwise, evaluate protocol and host of the URL against the origin - # protocol and host. - !(((!urlAnchor.protocol || urlAnchor.protocol == ':') && !urlAnchor.host) || - (originAnchor.protocol + '//' + originAnchor.host == urlAnchor.protocol + '//' + urlAnchor.host)) - catch e - # If there is an error parsing the URL, assume it is crossDomain. - true diff --git a/actionview/app/assets/javascripts/utils/csrf.coffee b/actionview/app/assets/javascripts/utils/csrf.coffee deleted file mode 100644 index 4eb5ebb414..0000000000 --- a/actionview/app/assets/javascripts/utils/csrf.coffee +++ /dev/null @@ -1,25 +0,0 @@ -#= require ./dom - -{ $ } = Rails - -# Up-to-date Cross-Site Request Forgery token -csrfToken = Rails.csrfToken = -> - meta = document.querySelector('meta[name=csrf-token]') - meta and meta.content - -# URL param that must contain the CSRF token -csrfParam = Rails.csrfParam = -> - meta = document.querySelector('meta[name=csrf-param]') - meta and meta.content - -# Make sure that every Ajax request sends the CSRF token -Rails.CSRFProtection = (xhr) -> - token = csrfToken() - xhr.setRequestHeader('X-CSRF-Token', token) if token? - -# Make sure that all forms have actual up-to-date tokens (cached forms contain old ones) -Rails.refreshCSRFTokens = -> - token = csrfToken() - param = csrfParam() - if token? and param? - $('form input[name="' + param + '"]').forEach (input) -> input.value = token diff --git a/actionview/app/assets/javascripts/utils/dom.coffee b/actionview/app/assets/javascripts/utils/dom.coffee deleted file mode 100644 index 6bef618147..0000000000 --- a/actionview/app/assets/javascripts/utils/dom.coffee +++ /dev/null @@ -1,28 +0,0 @@ -m = Element.prototype.matches or - Element.prototype.matchesSelector or - Element.prototype.mozMatchesSelector or - Element.prototype.msMatchesSelector or - Element.prototype.oMatchesSelector or - Element.prototype.webkitMatchesSelector - -Rails.matches = (element, selector) -> - if selector.exclude? - m.call(element, selector.selector) and not m.call(element, selector.exclude) - else - m.call(element, selector) - -# get and set data on a given element using "expando properties" -# See: https://developer.mozilla.org/en-US/docs/Glossary/Expando -expando = '_ujsData' - -Rails.getData = (element, key) -> - element[expando]?[key] - -Rails.setData = (element, key, value) -> - element[expando] ?= {} - element[expando][key] = value - -# a wrapper for document.querySelectorAll -# returns an Array -Rails.$ = (selector) -> - Array.prototype.slice.call(document.querySelectorAll(selector)) diff --git a/actionview/app/assets/javascripts/utils/event.coffee b/actionview/app/assets/javascripts/utils/event.coffee deleted file mode 100644 index 8d3ff007ea..0000000000 --- a/actionview/app/assets/javascripts/utils/event.coffee +++ /dev/null @@ -1,40 +0,0 @@ -#= require ./dom - -{ matches } = Rails - -# Polyfill for CustomEvent in IE9+ -# https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill -CustomEvent = window.CustomEvent - -if typeof CustomEvent isnt 'function' - CustomEvent = (event, params) -> - evt = document.createEvent('CustomEvent') - evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail) - evt - CustomEvent.prototype = window.Event.prototype - -# Triggers a custom event on an element and returns false if the event result is false -fire = Rails.fire = (obj, name, data) -> - event = new CustomEvent( - name, - bubbles: true, - cancelable: true, - detail: data, - ) - obj.dispatchEvent(event) - !event.defaultPrevented - -# Helper function, needed to provide consistent behavior in IE -Rails.stopEverything = (e) -> - fire(e.target, 'ujs:everythingStopped') - e.preventDefault() - e.stopPropagation() - e.stopImmediatePropagation() - -Rails.delegate = (element, selector, eventType, handler) -> - element.addEventListener eventType, (e) -> - target = e.target - target = target.parentNode until not (target instanceof Element) or matches(target, selector) - if target instanceof Element and handler.call(target, e) == false - e.preventDefault() - e.stopPropagation() diff --git a/actionview/app/assets/javascripts/utils/form.coffee b/actionview/app/assets/javascripts/utils/form.coffee deleted file mode 100644 index 5fa337b518..0000000000 --- a/actionview/app/assets/javascripts/utils/form.coffee +++ /dev/null @@ -1,36 +0,0 @@ -#= require ./dom - -{ matches } = Rails - -toArray = (e) -> Array.prototype.slice.call(e) - -Rails.serializeElement = (element, additionalParam) -> - inputs = [element] - inputs = toArray(element.elements) if matches(element, 'form') - params = [] - - inputs.forEach (input) -> - return unless input.name - if matches(input, 'select') - toArray(input.options).forEach (option) -> - params.push(name: input.name, value: option.value) if option.selected - else if input.checked or ['radio', 'checkbox', 'submit'].indexOf(input.type) == -1 - params.push(name: input.name, value: input.value) - - params.push(additionalParam) if additionalParam - - params.map (param) -> - if param.name? - "#{encodeURIComponent(param.name)}=#{encodeURIComponent(param.value)}" - else - param - .join('&') - -# Helper function that returns form elements that match the specified CSS selector -# If form is actually a "form" element this will return associated elements outside the from that have -# the html form attribute set -Rails.formElements = (form, selector) -> - if matches(form, 'form') - toArray(form.elements).filter (el) -> matches(el, selector) - else - toArray(form.querySelectorAll(selector)) -- cgit v1.2.3