-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpvc-route.html
195 lines (169 loc) · 4.96 KB
/
pvc-route.html
1
2
3
4
5
6
7
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
<link rel="import" href="../polymer/polymer.html">
<!--
Simple but powerful path-based routing for applications.
### Basic Usage
First, you must register your routes using the `register` boolean attribute.
<pvc-route register path="/users/:id" name="user"/>
Once registered, there are two ways to act on routing. First, you can declare
another element (without the `register` attribute) and bind to its `active`
attribute or, alternatively listen for its `enter` and `leave` events:
<pvc-route name="user" active="{{showProfile}}"/>
<pvc-route path="/users/:id" on-enter="{{loadProfile}}" on-leave="{{clearProfile}}"/>
Note that you can "hook" into a route either by its name or its path. Names are
only used for developer-friendly reference, they have no other effect.
@element pvc-route
@blurb Element providing solution to no problem in particular.
@status alpha
@homepage http://divshot.github.io/pvc-route
-->
<polymer-element name="pvc-route" attributes="path name register active">
<script>
(function() {
var _routes = [];
var _routePaths = {};
var _routeNames = {};
var Route = function(path, options) {
options = options || {};
this.path = path;
// thanks to pazguille/path
this.regexp = new RegExp('^' + this.path.replace(/:\w+/g, '([^\\/]+)').replace(/\//g, '\\/') + '$');
this.segments = (this.path.match(/:\w+/g) || []).map(function(seg) {
if (seg.indexOf(':') === 0) { return seg.substr(1); }
});
this.name = options.name;
}
Route.prototype.match = function(p) {
var match = p.match(this.regexp);
if (match) {
var params = {};
for (var i = 1; i < match.length; i++) {
params[this.segments[i-1]] = match[i];
}
return params;
} else {
return false;
}
}
var _recognize = function(path) {
for (i in _routes) {
var matched = _routes[i].match(path);
if (matched) return [_routes[i], matched];
}
return false;
}
var _navigate = function(path, options) {
options = options || {};
if (options.replace) {
history.replaceState({}, '', path);
} else {
history.pushState({}, '', path);
}
if (!options.silent) { _fire(); }
}
var _fire =function() {
console.log("_fire");
var match = _recognize(window.location.pathname);
if (match) {
var evt = new CustomEvent('pvc-route', {detail: {
route: match[0],
params: match[1]
}});
console.log("Dispatching Event", evt);
document.dispatchEvent(evt);
}
};
Polymer('pvc-route', {
/**
* Add to use this element to register a new route to the page routeset.
*
* @attribute register
* @type boolean
* @default false
*/
register: false,
/**
* The segmented description of the route. Use colons to specify variable
* parameters, e.g. `/users/:id`. You **must** specify a path if you are
* registering a new route.
*
* @attribute path
* @type string
*/
path: null,
/**
* A friendly name for this route, for example `user-profile`. You can use
* this to listen to the route instead of re-typing the fully qualified
* path.
*
* @attribute name
* @type string
*/
name: null,
/**
* Becomes `true` when the path matches the current route.
*
* @attribute active
* @type boolean
* @default false
*/
active: false,
ready: function() {
if (this.register) { this.register(); }
if (this.name) {
this.route = _routeNames[this.name];
} else if (this.path) {
this.route = _routePaths[this.path];
}
if (this.route) {
document.addEventListener('pvc-route', this.confirm.bind(this));
} else {
console.warn("Listening for route '" + this.path || this.name + "', which has not been registered.");
}
},
confirm: function(e) {
console.log(e.detail.route, this.route);
if (e.detail.route === this.route) {
if (this.active) { return; }
this.active = true;
this.fire('enter', e.detail);
} else {
if (this.active) {
this.active = false;
this.fire('leave');
}
}
},
register: function() {
var route = new Route(this.path, {name: this.name});
_routes.push(route);
if (this.name) { _routeNames[this.name] = route; }
if (this.path) { _routePaths[this.path] = route; }
},
/**
* Navigate to a new URL using the HTML5 History API. Takes two arguments
*
* @method navigate
* @param boolean path The path to which you want to navigate.
* @param object options Specify `replace` if you don't want to create a history entry. Specify `silent` if you don't want to trigger event handlers.
*/
navigate: function(path, options) {
_navigate(path, options);
},
get routeset() {
return _routes;
}
/**
* Fired when navigation lands on this element's route. The `detail` for this
* event contains a `params` object as well as the `route` object.
*
* @event enter
*/
/**
* Fired when navigation leaves this element's route.
*
* @event leave
*/
});
})();
</script>
</polymer-element>