Class: Isomorfeus::TopLevel

Inherits:
Object show all
Defined in:
lib/isomorfeus/top_level.rb,
lib/isomorfeus/preact/ssr/top_level.rb

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.first_passObject

Returns the value of attribute first_pass.



5
6
7
# File 'lib/isomorfeus/top_level.rb', line 5

def first_pass
  @first_pass
end

.hydratedObject

Returns the value of attribute hydrated.



4
5
6
# File 'lib/isomorfeus/top_level.rb', line 4

def hydrated
  @hydrated
end

.transport_ws_urlObject

Returns the value of attribute transport_ws_url.



10
11
12
# File 'lib/isomorfeus/preact/ssr/top_level.rb', line 10

def transport_ws_url
  @transport_ws_url
end

Class Method Details

.cached_component_class(class_name) ⇒ Object



31
32
33
34
# File 'lib/isomorfeus/preact/ssr/top_level.rb', line 31

def cached_component_class(class_name)
  return cached_component_classes[class_name] if cached_component_classes.key?(class_name)
  cached_component_classes[class_name] = "::#{class_name}".constantize
end

.cached_component_classesObject



27
28
29
# File 'lib/isomorfeus/preact/ssr/top_level.rb', line 27

def cached_component_classes
  @cached_component_classes ||= {}
end

.render_component_to_string(component_name, props) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/isomorfeus/preact/ssr/top_level.rb', line 12

def render_component_to_string(component_name, props)
  component = nil
  %x{
    if (typeof component_name === 'string' || component_name instanceof String) {
      component = component_name.split(".").reduce(function(o, x) {
        return (o !== null && typeof o[x] !== "undefined" && o[x] !== null) ? o[x] : null;
      }, Opal.global)
    } else {
      component = component_name;
    }
  }
  component = cached_component_class(component_name) unless component
  Preact.render_to_string(Preact.create_element(component, `Opal.Hash.$new(props)`))
end

Instance Method Details

#mount!Object



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
# File 'lib/isomorfeus/top_level.rb', line 8

def mount!
  Isomorfeus.init
  Isomorfeus::TopLevel.on_ready do
    root_element = `document.querySelector('div[data-iso-root]')`
    Isomorfeus.raise_error(message: "Isomorfeus root element not found!") unless root_element
    component_name = root_element.JS.getAttribute('data-iso-root')
    Isomorfeus.env = root_element.JS.getAttribute('data-iso-env')
    user_sid = root_element.JS.getAttribute('data-iso-usid')
    Isomorfeus.current_user_sid =`JSON.parse(user_sid)` if user_sid
    component = nil
    begin
      component = component_name.constantize
    rescue Exception => e
      `console.warn("Deferring mount: " + #{e.message})`
      @timeout_start = Time.now unless @timeout_start
      if (Time.now - @timeout_start) < 10
        `setTimeout(Opal.Isomorfeus.TopLevel['$mount!'], 100)`
      else
        `console.error("Unable to mount '" + #{component_name} + "'!")`
      end
    end
    if component
      props_json = root_element.JS.getAttribute('data-iso-props')
      props = `Opal.Hash.$new(JSON.parse(props_json))`
      raw_hydrated = root_element.JS.getAttribute('data-iso-hydrated')
      self.hydrated = (raw_hydrated && raw_hydrated == "true")
      %x{
        if (global.ServerSideRenderingStateJSON) {
        var state = global.ServerSideRenderingStateJSON;
          var keys = Object.keys(state);
          for(var i=0; i < keys.length; i++) {
            if (Object.keys(state[keys[i]]).length > 0) {
              global.Opal.Isomorfeus.store.native.dispatch({ type: keys[i].toUpperCase(), set_state: state[keys[i]] });
            }
          }
        }
      }
      Isomorfeus.execute_init_after_store_classes
      begin
        self.first_pass = true
        result = Isomorfeus::TopLevel.mount_component(component, props, root_element, self.hydrated)
        self.first_pass = false
        @tried_another_time = false
        result
      rescue Exception => e
        self.first_pass = false
        if  !@tried_another_time
          @tried_another_time = true
          `console.warn("Deferring mount: " + #{e.message})`
          `console.error(#{e.backtrace.join("\n")})`
          `setTimeout(Opal.Isomorfeus.TopLevel['$mount!'], 250)`
        else
          `console.error("Unable to mount '" + #{component_name} + "'! Error: " + #{e.message} + "!")`
          `console.error(#{e.backtrace.join("\n")})`
        end
      end
    end
  end
end

#mount_component(component, props, element_or_query, hydrated = false) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/isomorfeus/top_level.rb', line 90

def mount_component(component, props, element_or_query, hydrated = false)
  if `(typeof element_or_query === 'string')` || (`(typeof element_or_query.$class === 'function')` && element_or_query.class == String)
    element = `document.body.querySelector(element_or_query)`
  elsif `(typeof element_or_query.$is_a === 'function')` && element_or_query.is_a?(Browser::Element)
    element = element_or_query.to_n
  else
    element = element_or_query
  end

  top = Preact.create_element(component, props)
  hydrated ? Preact.hydrate(top, element) : Preact.render(top, element)
  Isomorfeus.top_component = top
end

#on_ready(&block) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/isomorfeus/top_level.rb', line 68

def on_ready(&block)
  %x{
    function run() { block.$call() };
    function ready_fun(fn) {
      if (document.readyState === "complete" || document.readyState === "interactive") {
        setTimeout(fn, 1);
      } else {
        document.addEventListener("DOMContentLoaded", fn);
      }
    }
    ready_fun(run);
  }
end

#on_ready_mount(component, props = nil, element_query = nil) ⇒ Object



82
83
84
85
86
87
88
# File 'lib/isomorfeus/top_level.rb', line 82

def on_ready_mount(component, props = nil, element_query = nil)
  # init in case it hasn't been run yet
  Isomorfeus.init
  on_ready do
    Isomorfeus::TopLevel.mount_component(component, props, element_query)
  end
end