Rigel Group

They shoot Yaks, don't they?

Batmanjs Binding for Executing Script Blocks in Views.

You may have noticed that if you add a <script> block to your Batmanjs views, it never gets executed. This binding will look for any <script> nodes that are immediate children and executes them.

Note that you probably should NOT be doing this, as it is certainly going against the grain of Batman, but for quickly trying out standard jquery code without any modifications, it’s nice.

Execscripts.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# 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)