Completed
Push — master ( bfd053...49d9d4 )
by Yoh
54s
created

Hyalite.create_element_hook()   A

Complexity

Conditions 1

Duplication

Lines 0
Ratio 0 %

Size

Total Lines 7

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 1
1
require 'opal'
2
require 'hyalite/logger'
3
require 'hyalite/transaction'
4
require 'hyalite/adler32'
5
require 'hyalite/mount'
6
require 'hyalite/element'
7
require 'hyalite/dom_component'
8
require 'hyalite/text_component'
9
require 'hyalite/dom'
10
11
module Hyalite
12
  class << self
13
    RESERVED_PROPS = [:key, :ref, :children]
14
15
    def create_element(type, config = nil, *children)
16
      key = nil
17
      ref = nil
18
19
      props = {}
20
21
      if config
22
        key = config[:key]
23
        ref = config[:ref]
24
25
        config.each do |name, value|
26
          unless RESERVED_PROPS.include?(name)
27
            props[name] = config[name];
28
          end
29
        end
30
      end
31
32
      props[:children] = case children.length
33
                         when 0
34
                           nil
35
                         when 1
36
                           children.first
37
                         else
38
                           children
39
                         end
40
41
      ElementObject.new(type, key, ref, Hyalite.current_owner, props).tap {|el| element_created(el) }
42
    end
43
44
    def element_created(element)
45
      return unless @hooks
46
      @hooks.each do |hook|
47
        hook.call(element)
48
      end
49
    end
50
51
    def create_element_hook(&block)
52
      @hooks ||= []
53
      hook_setter = HookSetter.new(@hooks)
54
      yield hook_setter
55
    ensure
56
      hook_setter.destroy
57
    end
58
59
    class HookSetter
60
      def initialize(hooks)
61
        @hooks = hooks
62
        @memo = []
63
      end
64
65
      def hook(&block)
66
        @memo << block
67
        @hooks << block
68
      end
69
70
      def destroy
71
        @memo.each do |m|
72
          @hooks.delete(m)
73
        end
74
      end
75
    end
76
77
    def fn(&block)
78
      Class.new {
79
        include Component
80
        include Component::ShortHand
81
82
        def self.render_proc=(proc)
83
          @render_proc = proc
84
        end
85
86
        def self.render_proc
87
          @render_proc
88
        end
89
90
        def render
91
          self.instance_exec(@props, &self.class.render_proc)
92
        end
93
      }.tap{|cl| cl.render_proc = block }
94
    end
95
96
    def instantiate_component(node)
97
      node = EmptyComponent.empty_element if node.nil?
98
99
      case node
100
      when ElementObject
101
        case node.type
102
        when String
103
          DOMComponent.new node
104
        when Class
105
          if node.type.include?(InternalComponent)
106
            node.type.new
107
          elsif node.type.include?(Component)
108
            CompositeComponent.new node
109
          else
110
            raise "Encountered invalid type of Hyalite node. type: #{node.type}"
111
          end
112
        end
113
      when String, Numeric
114
        TextComponent.new node
115
      when EmptyComponent
116
        CompositeComponent.new node
117
      else
118
        raise "Encountered invalid Hyalite node: #{node}"
119
      end
120
    end
121
122
    def render(next_element, container, &block)
123
      case container
124
      when DOM::Node
125
        Mount.render_subtree_into_container(next_element, container, &block)
126
      when Enumerable
127
        container.each {|node| render(next_element, node, &block) }
128
      end
129
    end
130
131
    def instance_map
132
      @instance_map ||= {}
133
    end
134
135
    def current_owner(current_owner = nil)
136
      if current_owner && block_given?
137
        begin
138
          @current_owner = current_owner
139
          yield(@current_owner)
140
        ensure
141
          @current_owner = nil
142
        end
143
      else
144
        @current_owner
145
      end
146
    end
147
148
    def find_dom_node(component_or_element)
149
      return component_or_element if component_or_element.respond_to?(:node_type) && component_or_element.element?
150
151
      if instance_map.has_key?(component_or_element)
152
        return Mount.node(instance_map[component_or_element].root_node_id)
153
      end
154
    end
155
  end
156
end
157