app/assets/javascripts/pwn-fx.js.coffee in pwnstyles_rails-0.2.4 vs app/assets/javascripts/pwn-fx.js.coffee in pwnstyles_rails-0.2.5
- old
+ new
@@ -13,16 +13,25 @@
# After defining an effect class, call registerEffect on this instance to make
# it aware of the effect.
constructor: ->
@effects = []
@effectsByName = {}
+ @hiddenClassName = null
+ # @attribute {String} the default name of the DOM class used to hide
+ # elements; by default, this is set to the data-pwnfx-hidden-class
+ # attribute of the <body> element
+ hiddenClassName: null
+
# Wires JS to elements with data-pwnfx attributes.
#
# @param {Element} root the element whose content is wired; use document at
# load time
wire: (root) ->
+ @hiddenClassName ||=
+ document.body.getAttribute('data-pwnfx-hidden-class') || 'hidden'
+
for effect in @effects
attrName = "data-pwnfx-#{effect[0]}"
effectClass = effect[1]
scopeAttrName = "#{attrName}-scope"
doneAttrName = "#{attrName}-done"
@@ -53,11 +62,12 @@
# @return {HTMLElement} the closest parent of the given element whose
# data-pwnfx-scope matches the scopeId argument; window.document is
# returned if no such element exists or if scope is null
resolveScope: (scopeId, element) ->
element = null if scopeId is null
- while element != null && element.getAttribute('data-pwnfx-scope') != scopeId
+ while element isnt null &&
+ element.getAttribute('data-pwnfx-scope') isnt scopeId
element = element.parentElement
element || document
# Performs a scoped querySelectAll.
#
@@ -65,11 +75,11 @@
# @param {String} selector the CSS selector to query
# @return {NodeList, Array} the elements in the scope that match the CSS
# selector; the scope container can belong to the returned array
queryScope: (scope, selector) ->
scopeMatches = false
- if scope != document
+ if scope isnt document
# TODO: machesSelector is in a W3C spec, but only implemented using
# prefixes; the code below should be simplified once browsers
# implement it without vendor prefixes
if scope.matchesSelector
scopeMatches = scope.matchesSelector selector
@@ -104,11 +114,11 @@
# @param {HTMLElement} element the element whose parent chain will be searched
# @return {HTMLFormElement} the element's closest parent form, or null if the
# element is not wrapped in a <form>
parentForm: (element) ->
while element
- return element if element.nodeName == 'FORM'
+ return element if element.nodeName is 'FORM'
element = element.parentNode
null
# Do AJAX.
#
@@ -128,11 +138,11 @@
else
xhr.send null
# Called when an XHR request issued by PwnFx.xhr works out.
_xhr_onload: ->
- if (@status < 200 || @status >= 300) && (@status != 304)
+ if (@status < 200 || @status >= 300) && (@status isnt 304)
throw new Error(
"XHR result ignored due to HTTP #{@status}: #{@statusText}")
@pwnfxOnData @responseText
# Singleton instance.
@@ -221,12 +231,12 @@
# data-pwnfx-delayed: identifier connecting the AJAX data receiver
# data-pwnfx-delayed-url: URL to perform an AJAX request to
# data-pwnfx-delayed-method: the HTTP method of AJAX request (default: POST)
# data-pwnfx-delayed-ms: the delay between the page load and the issuing of
# the AJAX request (default: 1000ms)
-# data-pwnfx-delayed-target: a space-separated list of identifiers, one of which
-# should match the value of data-pwnfx-delayed; set on the element
+# data-pwnfx-delayed-target: a space-separated list of identifiers, one of
+# which should match the value of data-pwnfx-delayed; set on the element
# populated with the AJAX response
class PwnFxDelayed
constructor: (element, identifier, scopeId) ->
targetSelector = "[data-pwnfx-delayed-target~=\"#{identifier}\"]"
xhrUrl = element.getAttribute('data-pwnfx-delayed-url')
@@ -255,12 +265,12 @@
# data-pwnfx-refresh: identifier connecting the AJAX data receiver
# data-pwnfx-refresh-url: URL to perform an AJAX request to
# data-pwnfx-refresh-method: the HTTP method of AJAX request (default: POST)
# data-pwnfx-refresh-ms: delay between a change on the source element and
# AJAX refresh requests (default: 200ms)
-# data-pwnfx-refresh-target: a space-separated list of identifiers, one of which
-# should match the value of data-pwnfx-refresh; set on the element
+# data-pwnfx-refresh-target: a space-separated list of identifiers, one of
+# which should match the value of data-pwnfx-refresh; set on the element
# populated with the AJAX response
class PwnFxRefresh
constructor: (element, identifier, scopeId) ->
targetSelector = "[data-pwnfx-refresh-target~=\"#{identifier}\"]"
xhrUrl = element.getAttribute('data-pwnfx-refresh-url')
@@ -280,14 +290,14 @@
changeTimeout = null
PwnFx.xhr xhrUrl, xhrMethod, xhrForm, onXhrData
onChange = ->
value = element.value
- return true if value == refreshOldValue
+ return true if value is refreshOldValue
refreshOldValue = value
- window.clearTimeout changeTimeout if changeTimeout != null
+ window.clearTimeout changeTimeout if changeTimeout isnt null
changeTimeout = window.setTimeout ajaxRefresh, refreshDelay
true
element.addEventListener 'change', onChange, false
element.addEventListener 'keydown', onChange, false
@@ -301,30 +311,32 @@
# Element attributes:
# data-pwnfx-confirm: all elements with the same value for this attribute
# belong to the same confirmation group; their values have to match to
# trigger the "win" condition
# data-pwnfx-confirm-class: the CSS class that is added to hidden elements;
-# (default: hidden)
+# by default, this is {PwnFx.hiddenClassName}, which gets its value from
+# the data-pwnfx-hidden-class attribute on <body>
# data-pwnfx-confirm-win: CSS selector identifying the elements to be shown
# when the "win" condition is triggered, and hidden otherwise
# data-pwnfx-confirm-fail: CSS selector identifying the elements to be hidden
# when the "win" condition is triggered, and shown otherwise
class PwnFxConfirm
constructor: (element, identifier, scopeId) ->
- hiddenClass = element.getAttribute('data-pwnfx-confirm-class') || 'hidden'
+ hiddenClass = element.getAttribute('data-pwnfx-confirm-class') ||
+ PwnFx.hiddenClassName
sourceSelector = "[data-pwnfx-confirm-done=\"#{identifier}\"]"
winSelector = "[data-pwnfx-confirm-win=\"#{identifier}\"]"
failSelector = "[data-pwnfx-confirm-fail=\"#{identifier}\"]"
onChange = ->
scope = PwnFx.resolveScope scopeId, element
value = null
matching = true
for sourceElement, index in PwnFx.queryScope(scope, sourceSelector)
- if index == 0
+ if index is 0
value = sourceElement.value
- else if sourceElement.value != value
+ else if sourceElement.value isnt value
matching = false
break
hideSelector = if matching then failSelector else winSelector
showSelector = if matching then winSelector else failSelector
@@ -348,42 +360,44 @@
# data-pwnfx-hide: a name for the events caused by this element's triggering
# data-pwnfx-hide-trigger: "click" means events are triggered when the
# element is clicked, "checked" means events are triggered when the
# element is checked; (default: click)
# data-pwnfx-hide-class: the CSS class that is added to hidden elements;
-# (default: hidden)
+# by default, this is {PwnFx.hiddenClassName}, which gets its value from
+# the data-pwnfx-hidden-class attribute on <body>
# data-pwnfx-hide-positive: set to the same value as data-pwnfx-hide on
# elements that will be hidden when a positive event (click / check) is
# triggered, and shown when a negative event (uncheck) is triggered
# data-pwnfx-hide-negative: set to the same value as data-pwnfx-hide on
# elements that will be shown when a positive event (click / check) is
# triggered, and hidden when a negative event (uncheck) is triggered
class PwnFxHide
constructor: (element, identifier, scopeId) ->
trigger = element.getAttribute('data-pwnfx-hide-trigger') || 'click'
- hiddenClass = element.getAttribute('data-pwnfx-hide-class') || 'hidden'
+ hiddenClass = element.getAttribute('data-pwnfx-hide-class') ||
+ PwnFx.hiddenClassName
positiveSelector = "[data-pwnfx-hide-positive=\"#{identifier}\"]"
negativeSelector = "[data-pwnfx-hide-negative=\"#{identifier}\"]"
onChange = (event) ->
- positive = (trigger == 'click') || element.checked
+ positive = (trigger is 'click') || element.checked
hideSelector = if positive then positiveSelector else negativeSelector
showSelector = if positive then negativeSelector else positiveSelector
scope = PwnFx.resolveScope scopeId, element
for targetElement in PwnFx.queryScope(scope, hideSelector)
targetElement.classList.add hiddenClass
for targetElement in PwnFx.queryScope(scope, showSelector)
targetElement.classList.remove hiddenClass
- if trigger == 'click'
+ if trigger is 'click'
event.preventDefault()
false
else
true
- if trigger == 'click'
+ if trigger is 'click'
element.addEventListener 'click', onChange, false
- else if trigger == 'checked'
+ else if trigger is 'checked'
element.addEventListener 'change', onChange, false
onChange()
else
throw new Error("Unimplemented pwnfx-hide trigger #{trigger}")
@@ -395,18 +409,20 @@
# Attributes:
# data-pwnfx-showif: an identifier that connects the source <input>
# data-pwnfx-showif-replace: the name of a tag that will be used to replace
# the hidden element (default: don't replace the hidden element)
# data-pwnfx-showif-class: the CSS class that is added to hidden elements;
-# (default: hidden)
+# by default, this is {PwnFx.hiddenClassName}, which gets its value from
+# the data-pwnfx-hidden-class attribute on <body>
# data-pwnfx-showif-is: the value that the <input> has to match for this
# element to be shown
# data-pwnfx-showif-source: set to the identifier in data-pwnfx-showif
# on the <input> whose value determines if this element is shown or not
class PwnFxShowIf
constructor: (element, identifier, scopeId) ->
- hiddenClass = element.getAttribute('data-pwnfx-showif-class') || 'hidden'
+ hiddenClass = element.getAttribute('data-pwnfx-showif-class') ||
+ PwnFx.hiddenClassName
showValue = element.getAttribute 'data-pwnfx-showif-is'
sourceSelector = "[data-pwnfx-showif-source=\"#{identifier}\"]"
replacementTag = element.getAttribute 'data-pwnfx-showif-replace'
if replacementTag
@@ -416,12 +432,12 @@
replacement = null
isHidden = false
onChange = (event) ->
value = event.target.value
- willHide = value != showValue
- return if isHidden == willHide
+ willHide = value isnt showValue
+ return if isHidden is willHide
isHidden = willHide
if replacement
if willHide
element.parentElement.replaceChild replacement, element
@@ -446,13 +462,13 @@
# Removes elements from the DOM when an element is clicked.
#
# Attributes:
# data-pwnfx-remove: an identifier connecting the elements to be removed
-# data-pwnfx-remove-target: a space-separated list of identifiers, one of which
-# should match the value of data-pwnfx-remove; set on elements that will
-# be removed when the element is clicked
+# data-pwnfx-remove-target: a space-separated list of identifiers, one of
+# which should match the value of data-pwnfx-remove; set on elements that
+# will be removed when the element is clicked
class PwnFxRemove
constructor: (element, identifier, scopeId) ->
targetSelector = "[data-pwnfx-remove-target~=\"#{identifier}\"]"
onClick = (event) ->
@@ -468,14 +484,14 @@
# Export the PwnFx instance.
window.PwnFx = PwnFx
# Wire up the entire DOM after the document is loaded.
-if document.readyState == 'loading'
+if document.readyState is 'loading'
loaded = false
document.addEventListener 'readystatechange', ->
return if loaded
- if document.readyState != 'loading'
+ if document.readyState isnt 'loading'
PwnFx.wire(document)
loaded = true
else
PwnFx.wire document