Class: Volt::DomTemplate

Inherits:
Object show all
Includes:
CommentSearchers
Defined in:
lib/volt/page/targets/dom_template.rb

Overview

A dom template is used to optimize going from a template name to dom nodes and bindings. It stores a copy of the template’s parsed dom nodes, then when a new instance is requested, it updates the dom markers (comments) for new binding numbers and returns a cloneNode’d version of the dom nodes and the bindings.

Constant Summary

Constants included from CommentSearchers

CommentSearchers::NO_XPATH

Instance Method Summary collapse

Methods included from CommentSearchers

#build_from_html, #find_by_comment, #find_by_comment_without_xml

Constructor Details

#initialize(page, template_name) ⇒ DomTemplate

Returns a new instance of DomTemplate.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/volt/page/targets/dom_template.rb', line 12

def initialize(page, template_name)
  template = page.templates[template_name]

  if template
    html      = template['html']
    @bindings = template['bindings']
  else
    html      = "<div>-- &lt; missing template #{template_name.inspect.gsub('<', '&lt;').gsub('>', '&gt;')} &gt; --</div>"
    @bindings = {}
  end

  @nodes = build_from_html(html)

  track_binding_anchors
end

Instance Method Details

#make_newObject

Returns the dom nodes and bindings



29
30
31
32
33
34
35
# File 'lib/volt/page/targets/dom_template.rb', line 29

def make_new
  bindings = update_binding_anchors!(`self.nodes`)

  new_nodes = `self.nodes.cloneNode(true)`

  [new_nodes, bindings]
end

#track_binding_anchorsObject

Finds each of the binding anchors in the temp dom, then stores a reference to them so they can be quickly updated without using xpath to find them again.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/volt/page/targets/dom_template.rb', line 39

def track_binding_anchors
  @binding_anchors = {}

  # Loop through the bindings, find in nodes.
  @bindings.each_pair do |name, binding|
    if name.is_a?(String)
      # Find the dom node for an attribute anchor
      node = nil
      `
        node = self.nodes.querySelector('#' + name);
      `
      @binding_anchors[name] = node
    else
      # Find the dom node for a comment anchor
      start_comment = find_by_comment("$#{name}", @nodes)
      end_comment   = find_by_comment("$/#{name}", @nodes)

      @binding_anchors[name] = [start_comment, end_comment]
    end
  end
end

#update_binding_anchors!(nodes) ⇒ Object

Takes the binding_anchors and updates them with new numbers (comments and id’s) then returns the bindings updated to the new numbers.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/volt/page/targets/dom_template.rb', line 63

def update_binding_anchors!(nodes)
  new_bindings = {}

  @binding_anchors.each_pair do |name, anchors|
    new_name         = @@binding_number
    @@binding_number += 1

    if name.is_a?(String)
      if name[0..1] == 'id'
        # A generated id
        # update the id
        `anchors.setAttribute('id', 'id' + new_name);`

        new_bindings["id#{new_name}"] = @bindings[name]
      else
        # Assume a fixed id, should not be updated
        # TODO: Might want to check the page to see if a node
        # with this id already exists and raise if it does.

        # Copy from existing binding
        new_bindings[name] = @bindings[name]
      end
    else
      start_comment, end_comment = anchors

      `
        if (start_comment.textContent) {
          // direct update
          start_comment.textContent = " $" + new_name + " ";
          end_comment.textContent = " $/" + new_name + " ";
        } else if (start_comment.innerText) {
          start_comment.innerText = " $" + new_name + " ";
          end_comment.innerText = " $/" + new_name + " ";
        } else {
          // phantomjs doesn't work with textContent, so we replace the nodes
          // and update the references
          start_comment.nodeValue = " $" + new_name + " ";
          end_comment.nodeValue = " $/" + new_name + " ";
        }
      `

      # %x{
      #   start_comment.innerText = " $" + new_name + " ";
      #   end_comment.innerText = " $/" + new_name + " ";
      # }

      new_bindings[new_name] = @bindings[name]
    end
  end

  new_bindings
end