Class: Ferro::Router
- Inherits:
-
Object
- Object
- Ferro::Router
- Defined in:
- opal/opal-ferro/ferro_router.js.rb
Overview
Wrapper for the web browsers history API. Note that there are no private methods in Opal. Methods that should be private are marked in the docs with ‘Internal method’.
Instance Method Summary collapse
-
#add_route(path, callback) ⇒ Object
Add a new route to the router.
-
#add_search_to_params(search) ⇒ Object
Internal method to split search parameters.
-
#decode(value) ⇒ Object
URI decode a value.
-
#get_location ⇒ Object
Internal method to get the new location.
-
#get_matches(path) ⇒ Object
Internal method to match a path to possible routes.
-
#go_back ⇒ Object
Navigate back.
-
#go_to(url) ⇒ Object
Navigate to url.
-
#initialize(page404) ⇒ Router
constructor
Create the router.
-
#match(path, search) ⇒ Object
Internal method to match a path to the most likely route.
-
#navigated ⇒ Object
Internal method called when the web browser navigates.
-
#path_to_parts(path) ⇒ Object
Internal method to split a path into components.
-
#push_state(url) ⇒ Object
Add a location to the web browsers history.
-
#replace_state(url) ⇒ Object
Replace the current location in the web browsers history.
-
#score_route(parts, path) ⇒ Object
Internal method to add a match score.
-
#setup_navigation_listener ⇒ Object
Internal method to set ‘onpopstate’.
Constructor Details
#initialize(page404) ⇒ Router
Create the router. Do not create a router directly, instead call the ‘router’ method that is available in all Ferro classes That method points to the router instance that is attached to the FerroDocument.
18 19 20 21 22 |
# File 'opal/opal-ferro/ferro_router.js.rb', line 18 def initialize(page404) @routes = [] @page404 = page404 end |
Instance Method Details
#add_route(path, callback) ⇒ Object
Add a new route to the router.
Examples: when the following routes are created and the web browser navigates to a url matching the route, the callback method will be called with parameters:
add_route('/ferro/page1', my_cb) # '/ferro/page1' => my_cb({})
add_route('/user/:id', my_cb) # '/user/1' => my_cb({id: 1})
add_route('/ferro', my_cb) # '/ferro?page=1' => my_cb({page: 1})
38 39 40 |
# File 'opal/opal-ferro/ferro_router.js.rb', line 38 def add_route(path, callback) @routes << { parts: path_to_parts(path), callback: callback } end |
#add_search_to_params(search) ⇒ Object
Internal method to split search parameters
167 168 169 170 171 172 173 174 175 176 |
# File 'opal/opal-ferro/ferro_router.js.rb', line 167 def add_search_to_params(search) if !search.empty? pars = search[1..-1].split('&') pars.each do |par| pair = par.split('=') @params[ pair[0] ] = pair[1] if pair.length == 2 end end end |
#decode(value) ⇒ Object
URI decode a value
91 92 93 |
# File 'opal/opal-ferro/ferro_router.js.rb', line 91 def decode(value) `decodeURI(#{value})` end |
#get_location ⇒ Object
Internal method to get the new location
75 76 77 |
# File 'opal/opal-ferro/ferro_router.js.rb', line 75 def get_location Native(`new URL(window.location.href)`) end |
#get_matches(path) ⇒ Object
Internal method to match a path to possible routes
131 132 133 134 135 136 137 138 139 140 |
# File 'opal/opal-ferro/ferro_router.js.rb', line 131 def get_matches(path) matches = [] @routes.each_with_index do |route, i| score, pars = score_route(route[:parts], path) matches << [i, score, pars] if score > 0 end matches end |
#go_back ⇒ Object
Navigate back
70 71 72 |
# File 'opal/opal-ferro/ferro_router.js.rb', line 70 def go_back `history.back()` end |
#go_to(url) ⇒ Object
Navigate to url
64 65 66 67 |
# File 'opal/opal-ferro/ferro_router.js.rb', line 64 def go_to(url) push_state(url) navigated end |
#match(path, search) ⇒ Object
Internal method to match a path to the most likely route
113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'opal/opal-ferro/ferro_router.js.rb', line 113 def match(path, search) matches = get_matches(path) if matches.length > 0 match = matches.sort { |m| m[1] }.first @params = match[2] add_search_to_params(search) match[0] else nil end end |
#navigated ⇒ Object
Internal method called when the web browser navigates
96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'opal/opal-ferro/ferro_router.js.rb', line 96 def navigated url = get_location @params = [] idx = match(path_to_parts(decode(url.pathname)), decode(url.search)) if idx @routes[idx][:callback].call(@params) else @page404.call(url.pathname) end end |
#path_to_parts(path) ⇒ Object
Internal method to split a path into components
80 81 82 83 84 85 86 |
# File 'opal/opal-ferro/ferro_router.js.rb', line 80 def path_to_parts(path) path. downcase. split('/'). map { |part| part.empty? ? nil : part.strip }. compact end |
#push_state(url) ⇒ Object
Add a location to the web browsers history
57 58 59 |
# File 'opal/opal-ferro/ferro_router.js.rb', line 57 def push_state(url) `history.pushState(null,null,#{url})` end |
#replace_state(url) ⇒ Object
Replace the current location in the web browsers history
50 51 52 |
# File 'opal/opal-ferro/ferro_router.js.rb', line 50 def replace_state(url) `history.replaceState(null,null,#{url})` end |
#score_route(parts, path) ⇒ Object
Internal method to add a match score
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'opal/opal-ferro/ferro_router.js.rb', line 146 def score_route(parts, path) score = 0 pars = {} if parts.length == path.length parts.each_with_index do |part, i| if part[0] == ':' score += 1 pars["#{part[1..-1]}"] = path[i] elsif part == path[i].downcase score += 2 end end end return score, pars end |
#setup_navigation_listener ⇒ Object
Internal method to set ‘onpopstate’
43 44 45 |
# File 'opal/opal-ferro/ferro_router.js.rb', line 43 def `window.onpopstate = function(e){#{navigated}}` end |