Class: History

Inherits:
Object
  • Object
show all
Defined in:
lib/reactive-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.



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/reactive-router/history.rb', line 89

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.



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

def history
  @history
end

Instance Attribute Details

#locationObject (readonly)

Returns the value of attribute location.



81
82
83
# File 'lib/reactive-router/history.rb', line 81

def location
  @location
end

#nameObject (readonly)

Returns the value of attribute name.



83
84
85
# File 'lib/reactive-router/history.rb', line 83

def name
  @name
end

#on_state_changeObject (readonly)

Returns the value of attribute on_state_change.



82
83
84
# File 'lib/reactive-router/history.rb', line 82

def on_state_change
  @on_state_change
end

Class Method Details

.[](name) ⇒ Object



25
26
27
# File 'lib/reactive-router/history.rb', line 25

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

.[]=(name, value) ⇒ Object



29
30
31
# File 'lib/reactive-router/history.rb', line 29

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

.current_pathObject



19
20
21
# File 'lib/reactive-router/history.rb', line 19

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

.pop_pathObject



76
77
78
# File 'lib/reactive-router/history.rb', line 76

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

.push_path(path) ⇒ Object



62
63
64
65
66
67
# File 'lib/reactive-router/history.rb', line 62

def push_path(path)
  puts "pushing path #{path}"
  `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



69
70
71
72
73
74
# File 'lib/reactive-router/history.rb', line 69

def replace_path(path)
  puts "replacing path #{path}"
  `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



5
6
7
8
9
10
11
12
13
14
15
16
17
# File 'lib/reactive-router/history.rb', line 5

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



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

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
    @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



111
112
113
114
115
116
117
118
119
120
121
# File 'lib/reactive-router/history.rb', line 111

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
  self.class.push_path initial_path
  @on_state_change.call(:active) if @on_state_change and current_history != self
  self
end

#deactivateObject



123
124
125
126
127
# File 'lib/reactive-router/history.rb', line 123

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



129
130
131
132
# File 'lib/reactive-router/history.rb', line 129

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})` }
end

#to_sObject



85
86
87
# File 'lib/reactive-router/history.rb', line 85

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