reactive-router 0.7.3 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 73020402b77bb3c9e6fd7b7ecb6e5473a1909629
4
- data.tar.gz: 83324993db70d197472abb0f6e54d45b87fb40f0
3
+ metadata.gz: 4a37cfefc5d18c03f42d0302fd1e56360ab0acdf
4
+ data.tar.gz: c367a01366dca24fed30dfa4bbf332d7b6e83163
5
5
  SHA512:
6
- metadata.gz: c13b7252cf9d88f0bae57f3abbf1d549a8ed972c145688eea7e866556a15cba181293caffbe16fcd19cd38a588d5ee39d53e34de4c135d1e89721e7e58d79e43
7
- data.tar.gz: 84d07d8faf68375b6360fedf326415d8f586e886caf44e9ec1d326d90d8a7404cc55e3da894fe0ddc1a1d02de31f038b77e26823f77f16366bb5e571ff2aede5
6
+ metadata.gz: 84257330b586a80d5d958207e31f2797bf95e4ee8538c4ffd4fd1bc80f8c47b93302ef1b1eb9c10da86e6500ad5a34d90c7e2b9c60eb107cf6f523359528f157
7
+ data.tar.gz: 5d130e422da66bcbc0ed5f3bd7c89f69c312349de727086fe26ab41fdae9019c27203794cf4ccd997cc16b18ab65bb76556e3f084de4e55de8bc7c0e6c7d6b69
@@ -1,6 +1,7 @@
1
1
  if RUBY_ENGINE == 'opal'
2
2
  require 'reactive-ruby'
3
3
  require 'reactive-router/component'
4
+ require 'reactive-router/history'
4
5
  require 'reactive-router/router'
5
6
  require 'reactive-router/version'
6
7
  else
@@ -2,27 +2,39 @@ module React
2
2
  module Component
3
3
 
4
4
  module ClassMethods
5
-
5
+
6
+ def url_param_evaluators
7
+ @url_param_evaluators ||= {}
8
+ end
9
+
10
+ attr_accessor :evaluated_url_params
11
+
6
12
  def router_param(name, &block)
7
- define_state name
8
- before_mount do
9
- send("#{name}!", yield(params[:params][name]))
13
+
14
+ url_param_evaluators[name] = block
15
+
16
+ class << self
17
+ define_method name do
18
+ evaluated_url_params[name]
19
+ end
10
20
  end
11
- before_receive_props do |new_params|
12
- send("#{name}!", yield(new_params[:params][name]))
21
+
22
+ define_method name do
23
+ self.class.send(name)
13
24
  end
25
+
14
26
  end
15
-
27
+
16
28
  end
17
29
 
18
- def route_handler
19
- Router::RR::RouteHandler()
30
+ def route_handler(*args)
31
+ Router::RR::RouteHandler(*args)
20
32
  end
21
33
 
22
34
  def link(opts = {}, &block)
23
35
  opts[:params] = opts[:params].to_n if opts[:params]
24
36
  Router::RR::Link(opts, &block)
25
37
  end
26
-
38
+
27
39
  end
28
40
  end
@@ -0,0 +1,134 @@
1
+ class History
2
+
3
+ class << self
4
+
5
+ def setup_handler
6
+ unless @handlers_setup
7
+ %x{
8
+ if (window.addEventListener) {
9
+ window.addEventListener('popstate', #{method(:window_history_pop_handler).to_n}, false);
10
+ } else {
11
+ window.attachEvent('onpopstate', #{method(:window_history_pop_handler).to_n});
12
+ }
13
+ }
14
+ end
15
+ @handlers_setup = true
16
+ end
17
+
18
+ def current_path
19
+ @current_path ||= `decodeURI(window.location.pathname + window.location.search)`
20
+ end
21
+
22
+ attr_accessor :history
23
+
24
+ def [](name)
25
+ (@histories ||= {})[name]
26
+ end
27
+
28
+ def []=(name, value)
29
+ (@histories ||= {})[name] = value
30
+ end
31
+
32
+ def window_history_pop_handler(event)
33
+ return if `event.state === undefined`
34
+ if `event.state == null` # happens when popping off outer dialog
35
+ puts "pop handler pops off last value"
36
+ old_history = @history
37
+ @current_path = ""
38
+ @history = nil
39
+ `ReactRouter.History.length = 0`
40
+ old_history.on_state_change.call(:inactive) if old_history.on_state_change
41
+ else
42
+ puts "pop handler #{`event.state.history_id`}, #{`ReactRouter.History.length`} -> #{`event.state.history_length`}, #{`event.state.path`}"
43
+ old_history = @history
44
+ old_history_length = `ReactRouter.History.length`
45
+ @current_path = `event.state.path`
46
+ @history= History[`event.state.history_id`]
47
+ `ReactRouter.History.length = event.state.history_length`
48
+ if old_history != @history
49
+ if `ReactRouter.History.length` > old_history_length
50
+ puts "activating "
51
+ @history.on_state_change.call(:active) if @history.on_state_change
52
+ else
53
+ puts "deactivating"
54
+ old_history.on_state_change.call(:inactive) if old_history.on_state_change
55
+ end
56
+ end
57
+ @history.notify_listeners(:pop)
58
+ end
59
+ end
60
+
61
+ def push_path(path)
62
+ puts "pushing path #{path}"
63
+ `window.history.pushState({ path: path, history_id: #{@history.name}, history_length: (ReactRouter.History.length += 1)}, '', path);`
64
+ @current_path = path
65
+ @history.notify_listeners(:push)
66
+ end
67
+
68
+ def replace_path(path)
69
+ puts "replacing path #{path}"
70
+ `window.history.replaceState({ path: path, history_id: #{@history.name}, history_length: ReactRouter.History.length}, '', path);`
71
+ @current_path = path
72
+ @history.notify_listeners(:replace)
73
+ end
74
+
75
+ def pop_path
76
+ `window.history.go(-1)`
77
+ end
78
+ end
79
+
80
+ attr_reader :location
81
+ attr_reader :on_state_change
82
+ attr_reader :name
83
+
84
+ def to_s
85
+ "History<#{@name}>"
86
+ end
87
+
88
+ def initialize(name, preactivate_path = nil, &on_state_change)
89
+ @name = name
90
+ if History[@name]
91
+ raise "a history location named #{@name} already exists"
92
+ else
93
+ History[@name] = self
94
+ end
95
+ @on_state_change = on_state_change
96
+ @initial_path = @preactivate_path = preactivate_path
97
+ self.class.setup_handler
98
+ @listeners = []
99
+ @location = {
100
+ addChangeListener: lambda { |listener| @listeners << listener unless @listeners.include? listener} ,
101
+ removeChangeListener: lambda { |listener| @listeners.delete(listener) },
102
+ push: lambda { |path| self.class.push_path(path) },
103
+ pop: lambda { self.class.pop_path },
104
+ replace: lambda { |path| self.class.replace_path path },
105
+ getCurrentPath: lambda { (@preactivate_path || self.class.current_path)},
106
+ toString: lambda { '<HistoryLocation>'}
107
+ }.to_n
108
+ end
109
+
110
+ def activate(initial_path = nil)
111
+ puts "activating #{self}"
112
+ @preactivate_path = nil
113
+ initial_path ||= @initial_path || self.class.current_path
114
+ current_history = self.class.history
115
+ self.class.history = self
116
+ @starting_history_length = `ReactRouter.History.length` if current_history != self
117
+ self.class.push_path initial_path
118
+ @on_state_change.call(:active) if @on_state_change and current_history != self
119
+ self
120
+ end
121
+
122
+ def deactivate
123
+ puts "deactivate go(#{@starting_history_length-`ReactRouter.History.length`})"
124
+ `window.history.go(#{@starting_history_length}-ReactRouter.History.length)`
125
+ self
126
+ end
127
+
128
+ def notify_listeners(type)
129
+ puts "#{self}.notify_listeners(#{type}) listeners_count: #{@listeners.count}, path: #{self.class.current_path}"
130
+ @listeners.each { |listener| `listener.call(#{@location}, {path: #{self.class.current_path}, type: type})` }
131
+ end
132
+
133
+
134
+ end
@@ -3,6 +3,9 @@ module React
3
3
 
4
4
  module Router
5
5
 
6
+ class AbortTransition < Exception
7
+ end
8
+
6
9
  class RR < React::NativeLibrary
7
10
  imports ReactRouter
8
11
  end
@@ -12,9 +15,56 @@ module React
12
15
 
13
16
  include React::Component
14
17
  include React::IsomorphicHelpers
15
-
18
+
19
+ native_mixin `ReactRouter.Navigation`
20
+ native_mixin `ReactRouter.State`
21
+
22
+ def get_path
23
+ path = `self.native.getPath()`
24
+ path = nil if `typeof path === 'undefined'`
25
+ path
26
+ end
27
+
28
+ def replace_with(route_or_path, params = nil, query = nil)
29
+ `self.native.replaceWith.apply(self.native, #{[route_or_path, params].compact})`
30
+ end
31
+
32
+ def transition_to(route_or_path, params = nil, query = nil)
33
+ `self.native.transitionTo.apply(self.native, #{[route_or_path, params].compact})`
34
+ end
35
+
36
+ static_call_back "willTransitionTo" do |transition, params, query, callback|
37
+ params = Hash.new(params)
38
+ query = Hash.new(query)
39
+ transition = `transition.path`
40
+ puts "willTransitionTo(#{transition}, #{params}, #{query})"
41
+ begin
42
+ params.each do |param, value|
43
+ if evaluator = url_param_evaluators[param]
44
+ evaluated_url_params[param] = evaluator.call(value)
45
+ end
46
+ end
47
+ if self.respond_to? :will_transition_to
48
+ result = will_transition_to transition, params, query if self.respond_to? :will_transition_to
49
+ if result.is_a? Promise
50
+ result.then { |r| callback(r) }
51
+ else
52
+ callback.call()
53
+ end
54
+ else
55
+ callback.call()
56
+ end
57
+ rescue AbortTransition
58
+ raise "transition aborted"
59
+ end
60
+ end
61
+
16
62
  before_first_mount do |context|
17
- if `typeof ReactRouter === 'undefined'`
63
+
64
+ @evaluated_url_params = {}
65
+ if !self.instance_methods.include?(:show) # if there is no show method this is NOT a top level router so we assume routing will begin elsewhere
66
+ @routing = true
67
+ elsif `typeof ReactRouter === 'undefined'`
18
68
  if on_opal_client?
19
69
  message = "ReactRouter not defined in browser assets - you must manually include it in your assets"
20
70
  else
@@ -29,14 +79,24 @@ module React
29
79
 
30
80
  export_component
31
81
 
82
+ optional_param :router_state # optional because it is not initially passed in but we add it when running the router
83
+ optional_param :query
84
+ optional_param :params
85
+
86
+ def url_params(params)
87
+ params[:params] || (params[:router_state] && params[:router_state][:params]) || {}
88
+ end
89
+
90
+
32
91
  def render
33
92
  if self.class.routing?
34
93
  show
35
94
  elsif on_opal_server?
36
95
  self.class.routing!
37
- routes = self.class.build_routes
96
+ routes = self.class.build_routes(true)
38
97
  %x{
39
- ReactRouter.run(#{routes}, window.reactive_router_static_location, function(root) {
98
+ ReactRouter.run(#{routes}, window.reactive_router_static_location, function(root, state) {
99
+ self.native.props.router_state = state
40
100
  self.root = React.createElement(root, self.native.props);
41
101
  });
42
102
  }
@@ -54,6 +114,12 @@ module React
54
114
  was_routing
55
115
  end
56
116
 
117
+ # override self.location to provide application specific location handlers
118
+
119
+ def location
120
+ (@location ||= History.new("MainApp")).activate.location
121
+ end
122
+
57
123
  after_mount do
58
124
  unless self.class.routing!
59
125
  dom_node = if `typeof React.findDOMNode === 'undefined'`
@@ -61,9 +127,10 @@ module React
61
127
  else
62
128
  `React.findDOMNode(#{self}.native)` # v0.13.0
63
129
  end
64
- routes = self.class.build_routes
130
+ routes = self.class.build_routes(true)
65
131
  %x{
66
- ReactRouter.run(#{routes}, ReactRouter.HistoryLocation, function(root) {
132
+ ReactRouter.run(#{routes}, #{location}, function(root, state) {
133
+ self.native.props.router_state = state
67
134
  React.render(React.createElement(root, self.native.props), #{dom_node});
68
135
  });
69
136
  }
@@ -74,17 +141,23 @@ module React
74
141
  @routes_opts = opts
75
142
  @routes_block = block
76
143
  end
77
-
78
- def self.build_routes
144
+
145
+ def self.routes_block
146
+ @routes_block
147
+ end
148
+
149
+ def self.build_routes(generate_node = nil)
150
+ #raise "You must define a routes block in a router component" unless @routes_block
79
151
  routes_opts = @routes_opts.dup
80
- routes_opts[:handler] ||= self
81
- route(routes_opts, generate_node = true, &@routes_block)
152
+ routes_opts[:handler] ||= self
153
+ route(routes_opts, generate_node, &@routes_block)
82
154
  end
83
155
 
84
156
  def self.route(opts = {}, generate_node = nil, &block)
157
+ block ||= opts[:handler].routes_block if opts[:handler].respond_to? :routes_block
85
158
  opts = opts.dup
86
159
  opts[:handler] = React::API.create_native_react_class(opts[:handler])
87
- (generate_node ? RR::Route_as_node(opts, &block) : RR::Route(opts, &block))
160
+ (generate_node ? RR::Route_as_node(opts, &block) : RR::Route(opts, &block))
88
161
  end
89
162
 
90
163
  def self.default_route(ops = {}, &block)
@@ -95,6 +168,11 @@ module React
95
168
  RR::Redirect(opts, &block)
96
169
  end
97
170
 
171
+ def self.not_found(opts={}, &block)
172
+ opts[:handler] = React::API.create_native_react_class(opts[:handler])
173
+ RR::NotFoundRoute(opts, &block)
174
+ end
175
+
98
176
  end
99
177
  end
100
178
 
@@ -1,3 +1,3 @@
1
1
  module ReactiveRouter
2
- VERSION = "0.7.3"
2
+ VERSION = "0.7.4"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reactive-router
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.3
4
+ version: 0.7.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam George
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-07 00:00:00.000000000 Z
11
+ date: 2015-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -64,6 +64,7 @@ files:
64
64
  - Rakefile
65
65
  - lib/reactive-router.rb
66
66
  - lib/reactive-router/component.rb
67
+ - lib/reactive-router/history.rb
67
68
  - lib/reactive-router/router.rb
68
69
  - lib/reactive-router/version.rb
69
70
  - lib/reactive-router/window_location.rb