Batman binding for executing script blocks in views
# Execscripts.coffee
# John Lynch / Rigel Group, LLC
# Open source under the MIT License.
#
# Create a new binding that marks a specific node as having children scripts blocks, and then executes those script
# blocks as soon as the node has been added to the DOM by Batman. (This is necessary as many jQuery-type plugins
# wont work if run on an isolated node before it has been added to the DOM.)
#
# (Thanks to SO for some of this code. http://stackoverflow.com/questions/220188/how-can-i-determine-if-a-dynamically-created-dom-element-has-been-added-to-the-d)
#
# <div data-execscripts="true">
# <h1>Title</h1>
# <script type="text/javascript">
# alert("Hi Mom!");
# </script
# </div>
#
#
Batman.DOM.readers.execscripts = (node, key, context, renderer) ->
new Batman.DOM.ExecscriptBinding(node, key, context, renderer)
true
class Batman.DOM.ExecscriptBinding extends Batman.DOM.AbstractBinding
bindImmediately: false
constructor: ->
super
# Only run the script blocks once this node has been added to the DOM by Batman
@_executeOnLoad(@node, @_exec_body_scripts) if @value
_exec_body_scripts: (elem) =>
scripts = []
for child in elem.childNodes
scripts.push(child) if @_isScriptNode(child)
for script in scripts
script.parentNode?.removeChild(script)
@_evalScript(script)
_isScriptNode: (elem) =>
elem.nodeName && elem.nodeName.toLowerCase() == "script" && (!elem.type || elem.type.toLowerCase() == "text/javascript")
_evalScript: (elem) =>
data = (elem.text || elem.textContent || elem.innerHTML || "" )
head = document.getElementsByTagName("head")[0] || document.documentElement
script = document.createElement("script")
script.type = "text/javascript"
try
script.appendChild(document.createTextNode(data))
catch e
script.text = data
head.insertBefore(script, head.firstChild)
head.removeChild(script)
_isInDOMTree: (node) =>
!! @_findUltimateAncestor(node).body
_findUltimateAncestor: (node) =>
ancestor = node
(ancestor = ancestor.parentNode) while ancestor.parentNode
ancestor
_executeOnLoad: (node, func) =>
if @_isInDOMTree(node) then func(node) else setTimeout( (() => @_executeOnLoad(node, func)), 100)