Module: Hyalite::MultiChildren

Included in:
DOMComponent
Defined in:
lib/hyalite/multi_children.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.clear_queueObject



128
129
130
131
# File 'lib/hyalite/multi_children.rb', line 128

def clear_queue
  self.update_queue.clear
  self.markup_queue.clear
end

.insert_child_at(parent_node, child_node, index) ⇒ Object



197
198
199
200
201
202
203
# File 'lib/hyalite/multi_children.rb', line 197

def insert_child_at(parent_node, child_node, index)
  if index >= parent_node.children.length
    parent_node.add_child(child_node)
  else
    parent_node.children[index].add_previous_sibling(child_node)
  end
end

.markup_queueObject



124
125
126
# File 'lib/hyalite/multi_children.rb', line 124

def markup_queue
  @markup_queue ||= []
end

.process_children_updates(updates, markup) ⇒ Object



140
141
142
143
144
145
# File 'lib/hyalite/multi_children.rb', line 140

def process_children_updates(updates, markup)
  updates.each do |update|
    update[:parentNode] = Mount.node(update[:parentID])
  end
  process_updates(updates, markup)
end

.process_queueObject



133
134
135
136
137
138
# File 'lib/hyalite/multi_children.rb', line 133

def process_queue
  if MultiChildren.update_queue.any?
    process_children_updates(MultiChildren.update_queue, MultiChildren.markup_queue)
    clear_queue
  end
end

.process_updates(updates, markup_list) ⇒ Object



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/hyalite/multi_children.rb', line 147

def process_updates(updates, markup_list)
  initial_children = {}
  updated_children = []

  updates.each_with_index do |update, updated_index|
    if update[:type] == :move_existing || update[:type] == :remove_node
      updated_index = update[:fromIndex]
      updated_child = update[:parentNode].children[updated_index]
      parent_id = update[:parentID]

      initial_children[parent_id] ||= []
      initial_children[parent_id] << updated_child

      updated_children << updated_child
    end
  end

  if markup_list.any? && markup_list[0].is_a?(String)
    #rendered_markup = Danger.dangerouslyRenderMarkup(markupList);
    raise "not implemented"
  else
    rendered_markup = markup_list
  end

  updated_children.each do |child|
    child.remove
  end

  updates.each do |update|
    case update[:type]
    when :insert_markup
      insert_child_at(
        update[:parentNode],
        rendered_markup[update[:markupIndex]],
        update[:toIndex])
    when :move_existing
      insert_child_at(
        update[:parentNode],
        initial_children[update[:parentID]][update[:fromIndex]],
        update[:toIndex])
    when :set_markup
      update[:parentNode].inner_html = update[:textContent]
    when :text_content
      update[:parentNode].text = update[:textContent]
    when :remove_node
      # Already removed above.
    end
  end
end

.update_depthObject



112
113
114
# File 'lib/hyalite/multi_children.rb', line 112

def update_depth
  @update_depth ||= 0
end

.update_depth=(depth) ⇒ Object



116
117
118
# File 'lib/hyalite/multi_children.rb', line 116

def update_depth=(depth)
  @update_depth = depth
end

.update_queueObject



120
121
122
# File 'lib/hyalite/multi_children.rb', line 120

def update_queue
  @update_queue ||= []
end

.wrap_update(&block) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/hyalite/multi_children.rb', line 96

def wrap_update(&block)
  self.update_depth += 1
  error_thrown = true
  yield
  error_thrown = false
ensure
  self.update_depth -= 1
  if self.update_depth == 0
    unless error_thrown
      self.process_queue
    else
      self.clear_queue
    end
  end
end

Instance Method Details

#instantiate_children(nested_child_nodes, context) ⇒ Object



86
87
88
89
90
91
# File 'lib/hyalite/multi_children.rb', line 86

def instantiate_children(nested_child_nodes, context)
  Reconciler.flatten_children(nested_child_nodes).map {|name, child|
    child_instance = Hyalite.instantiate_component(child)
    [name, child_instance]
  }.to_h
end

#mount_children(nested_children, mount_ready, context) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
15
# File 'lib/hyalite/multi_children.rb', line 3

def mount_children(nested_children, mount_ready, context)
  children = instantiate_children(nested_children, context)
  @rendered_children = children
  index = 0
  children.keys.map do |name|
    child = children[name]
    root_id = root_node_id + name
    mount_image = Reconciler.mount_component(children[name], root_id, mount_ready, context)
    child.mount_index = index
    index += 1
    mount_image
  end
end

#move_child(child, to_index, last_index) ⇒ Object



71
72
73
74
75
# File 'lib/hyalite/multi_children.rb', line 71

def move_child(child, to_index, last_index)
  if child.mount_index < last_index
    enqueue_move(root_node_id, child.mount_index, to_index)
  end
end

#remove_child(child) ⇒ Object



77
78
79
# File 'lib/hyalite/multi_children.rb', line 77

def remove_child(child)
  enqueue_remove(root_node_id, child.mount_index)
end

#unmount_child(child) ⇒ Object



81
82
83
84
# File 'lib/hyalite/multi_children.rb', line 81

def unmount_child(child)
  remove_child(child)
  child.mount_index = nil
end

#unmount_childrenObject



17
18
19
20
21
22
# File 'lib/hyalite/multi_children.rb', line 17

def unmount_children
  if @rendered_children
    Reconciler.unmount_children(@rendered_children)
    @rendered_children = nil
  end
end

#update_children(next_nested_children, mount_ready, context) ⇒ Object



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
# File 'lib/hyalite/multi_children.rb', line 24

def update_children(next_nested_children, mount_ready, context)
  MultiChildren.wrap_update do
    prev_children = @rendered_children
    next_children = Reconciler.update_children(prev_children, next_nested_children, mount_ready, context)
    @rendered_children = next_children
    return if next_children.nil? && prev_children.nil?

    last_index = 0
    next_index = 0
    next_children.each do |name, next_child|
      prev_child = prev_children && prev_children[name]
      if prev_child == next_child
        move_child(prev_child, next_index, last_index)
        last_index = [prev_child.mount_index, last_index].max
        prev_child.mount_index = next_index
      else
        if prev_child
          last_index = [prev_child.mount_index, last_index].max
          unmount_child(prev_child)
        end

        mount_child_by_name_at_index(next_child, name, next_index, mount_ready, context)
      end
      next_index += 1
    end

    prev_children.each do |name, prev_child|
      unless next_children && next_children.has_key?(name)
        unmount_child(prev_child)
      end
    end
  end
end

#update_text_content(next_content) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/hyalite/multi_children.rb', line 58

def update_text_content(next_content)
  MultiChildren.wrap_update do
    prev_children = @rendered_children
    if prev_children
      Reconciler.unmount_children(prev_children)
      prev_children.each do |prev_child|
        unmount_child(prev_child)
      end
    end
    set_text_content(next_content)
  end
end