Class: History

Inherits:
Object
  • Object
show all
Defined in:
lib/reactrb-router/history.rb

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, preactivate_path = nil, &on_state_change) ⇒ History

Returns a new instance of History.



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/reactrb-router/history.rb', line 102

def initialize(name, preactivate_path = nil, &on_state_change)
  @name = name
  if History[@name]
    raise "a history location named #{@name} already exists"
  else
    History[@name] = self
  end
  @on_state_change = on_state_change
  @initial_path = @preactivate_path = preactivate_path
  self.class.setup_handler
  @listeners = []
  @location = {
    addChangeListener: lambda { |listener| @listeners << listener unless @listeners.include? listener} ,
    removeChangeListener: lambda { |listener| @listeners.delete(listener) },
    push: lambda { |path| self.class.push_path(path) },
    pop: lambda { self.class.pop_path },
    replace: lambda { |path| self.class.replace_path path },
    getCurrentPath: lambda { (@preactivate_path || self.class.current_path)},
    toString: lambda { '<HistoryLocation>'}
  }.to_n
end

Class Attribute Details

.historyObject

Returns the value of attribute history.



21
22
23
# File 'lib/reactrb-router/history.rb', line 21

def history
  @history
end

Instance Attribute Details

#locationObject (readonly)

Returns the value of attribute location.



94
95
96
# File 'lib/reactrb-router/history.rb', line 94

def location
  @location
end

#nameObject (readonly)

Returns the value of attribute name.



96
97
98
# File 'lib/reactrb-router/history.rb', line 96

def name
  @name
end

#on_state_changeObject (readonly)

Returns the value of attribute on_state_change.



95
96
97
# File 'lib/reactrb-router/history.rb', line 95

def on_state_change
  @on_state_change
end

Class Method Details

.[](name) ⇒ Object



23
24
25
# File 'lib/reactrb-router/history.rb', line 23

def [](name)
  (@histories ||= {})[name]
end

.[]=(name, value) ⇒ Object



27
28
29
# File 'lib/reactrb-router/history.rb', line 27

def []=(name, value)
  (@histories ||= {})[name] = value
end

.current_pathObject



17
18
19
# File 'lib/reactrb-router/history.rb', line 17

def current_path
  @current_path ||= `decodeURI(window.location.pathname + window.location.search)`
end

.pop_pathObject



89
90
91
# File 'lib/reactrb-router/history.rb', line 89

def pop_path
  `window.history.go(-1)`
end

.push_path(path) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/reactrb-router/history.rb', line 63

def push_path(path)
  puts "pushing path #{path}"
  unless @history # needed because safari strangly pops off outer most history on initialization
    @history = @saved_history
    @current_path = @saved_path
    `ReactRouter.History.length = #{@saved_history_length}`
    @history.on_state_change.call(:active) if @history.on_state_change
  end
  `window.history.pushState({ path: path, history_id: #{@history.name}, history_length: (ReactRouter.History.length += 1)}, '', path);`
  @current_path = path
  @history.notify_listeners(:push)
end

.replace_path(path) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/reactrb-router/history.rb', line 76

def replace_path(path)
  puts "replacing path #{path}"
  unless @history # needed because safari strangly pops off outer most history on initialization
    @history = @saved_history
    @current_path = @saved_path
    `ReactRouter.History.length = #{@saved_history_length}`
    @history.on_state_change.call(:active) if @history.on_state_change
  end
  `window.history.replaceState({ path: path, history_id: #{@history.name}, history_length: ReactRouter.History.length}, '', path);`
  @current_path = path
  @history.notify_listeners(:replace)
end

.setup_handlerObject



3
4
5
6
7
8
9
10
11
12
13
14
15
# File 'lib/reactrb-router/history.rb', line 3

def setup_handler
  unless @handlers_setup
    handler = lambda { |event| window_history_pop_handler(event) }
    %x{
      if (window.addEventListener) {
        window.addEventListener('popstate', handler, false);
      } else {
        window.attachEvent('onpopstate', handler);
      }
    }
  end
  @handlers_setup = true
end

.window_history_pop_handler(event) ⇒ Object



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
# File 'lib/reactrb-router/history.rb', line 31

def window_history_pop_handler(event)
  return if `event.state === undefined`
  if `event.state == null` # happens when popping off outer dialog
    puts "pop handler pops off last value"
    old_history = @history
    @saved_history = @history # for safari's sake
    @saved_path = @current_path
    @saved_history_length = `ReactRouter.History.length`
    @current_path = ""
    @history = nil
    `ReactRouter.History.length = 0`
    old_history.on_state_change.call(:inactive) if old_history.on_state_change
  else
    puts "pop handler #{`event.state.history_id`}, #{`ReactRouter.History.length`} -> #{`event.state.history_length`}, #{`event.state.path`}"
    old_history = @history
    old_history_length = `ReactRouter.History.length`
    @current_path = `event.state.path`
    @history= History[`event.state.history_id`]
    `ReactRouter.History.length = event.state.history_length`
    if old_history != @history
      if `ReactRouter.History.length` > old_history_length
        puts "activating "
        @history.on_state_change.call(:active) if @history.on_state_change
      else
        puts "deactivating"
        old_history.on_state_change.call(:inactive) if old_history.on_state_change
      end
    end
    @history.notify_listeners(:pop)
  end
end

Instance Method Details

#activate(initial_path = nil) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/reactrb-router/history.rb', line 124

def activate(initial_path = nil)
  puts "activating #{self}"
  @preactivate_path = nil
  initial_path ||= @initial_path || self.class.current_path
  current_history = self.class.history
  self.class.history = self
  @starting_history_length = `ReactRouter.History.length` if current_history != self
  if @name == "MainApp"
    self.class.replace_path initial_path
  else
    self.class.push_path initial_path
  end
  @on_state_change.call(:active) if @on_state_change and current_history != self
  self
end

#deactivateObject



140
141
142
143
144
# File 'lib/reactrb-router/history.rb', line 140

def deactivate
  puts "deactivate go(#{@starting_history_length-`ReactRouter.History.length`})"
  `window.history.go(#{@starting_history_length}-ReactRouter.History.length)`
  self
end

#notify_listeners(type) ⇒ Object



146
147
148
149
150
151
152
# File 'lib/reactrb-router/history.rb', line 146

def notify_listeners(type)
  puts "!! #{self}.notify_listeners(#{type}) listeners_count: #{@listeners.count}, path: #{self.class.current_path}"
  @listeners.each { |listener| `listener.call(#{@location}, {path: #{self.class.current_path}, type: type})` }
rescue Exception => e
  `debugger`
  nil
end

#to_sObject



98
99
100
# File 'lib/reactrb-router/history.rb', line 98

def to_s
  "History<#{@name}>"
end