@base-framework/base 2.6.0 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/base.min.js +1 -0
  2. package/es5/base.js +2968 -0
  3. package/es5/modules/ajax.js +663 -0
  4. package/es5/modules/animation.js +188 -0
  5. package/es5/modules/animations.js +1080 -0
  6. package/es5/modules/atom.js +65 -0
  7. package/es5/modules/component.js +1310 -0
  8. package/es5/modules/data-binder.js +1131 -0
  9. package/es5/modules/data.js +1808 -0
  10. package/es5/modules/date.js +525 -0
  11. package/es5/modules/form-validator.js +324 -0
  12. package/es5/modules/history.js +126 -0
  13. package/es5/modules/html-builder.js +461 -0
  14. package/es5/modules/layout.js +1679 -0
  15. package/es5/modules/mouse.js +124 -0
  16. package/es5/modules/nav-link.js +123 -0
  17. package/es5/modules/olderversions/animations-ease.js +1095 -0
  18. package/es5/modules/olderversions/animations-update.js +1048 -0
  19. package/es5/modules/olderversions/base-animations.js +636 -0
  20. package/es5/modules/olderversions/base-component-class.js +100 -0
  21. package/es5/modules/olderversions/base-data-binder-1.js +407 -0
  22. package/es5/modules/olderversions/base-data-binder-class.js +358 -0
  23. package/es5/modules/olderversions/base-layout-parser-class.js +172 -0
  24. package/es5/modules/olderversions/base-mode-1.js +777 -0
  25. package/es5/modules/olderversions/base-model-class.js +585 -0
  26. package/es5/modules/olderversions/data-binder/element-binding/base-data-binder-class.js +358 -0
  27. package/es5/modules/olderversions/data-binder/element-binding/base-model-class.js +585 -0
  28. package/es5/modules/olderversions/data-binder/model-binding/base-data-binder-class.js +353 -0
  29. package/es5/modules/olderversions/data-binder/model-binding/base-model-class.js +604 -0
  30. package/es5/modules/olderversions/data-binder-update-watcher.js +640 -0
  31. package/es5/modules/olderversions/data-tracker.js +187 -0
  32. package/es5/modules/olderversions/event-update.js +666 -0
  33. package/es5/modules/olderversions/nav-link.js +119 -0
  34. package/es5/modules/olderversions/router-with-templates-1.js +785 -0
  35. package/es5/modules/olderversions/router-with-templates.js +701 -0
  36. package/es5/modules/prototypes/ajax.js +657 -0
  37. package/es5/modules/prototypes/atom.js +65 -0
  38. package/es5/modules/prototypes/component.js +972 -0
  39. package/es5/modules/prototypes/data-binder.js +1089 -0
  40. package/es5/modules/prototypes/data.js +1290 -0
  41. package/es5/modules/prototypes/html-builder.js +414 -0
  42. package/es5/modules/prototypes/layout.js +879 -0
  43. package/es5/modules/router.js +1680 -0
  44. package/es5/modules/state.js +274 -0
  45. package/es6/.jshintrc +3 -0
  46. package/es6/base.js +41 -0
  47. package/es6/core.js +1 -0
  48. package/es6/data-tracker.js +351 -0
  49. package/es6/events.js +602 -0
  50. package/es6/legacy/es5/base.js +2968 -0
  51. package/es6/legacy/es5/modules/ajax.js +663 -0
  52. package/es6/legacy/es5/modules/animation.js +188 -0
  53. package/es6/legacy/es5/modules/animations.js +1080 -0
  54. package/es6/legacy/es5/modules/atom.js +65 -0
  55. package/es6/legacy/es5/modules/component.js +1310 -0
  56. package/es6/legacy/es5/modules/data-binder.js +1131 -0
  57. package/es6/legacy/es5/modules/data.js +1808 -0
  58. package/es6/legacy/es5/modules/date.js +525 -0
  59. package/es6/legacy/es5/modules/form-validator.js +324 -0
  60. package/es6/legacy/es5/modules/history.js +126 -0
  61. package/es6/legacy/es5/modules/html-builder.js +461 -0
  62. package/es6/legacy/es5/modules/layout.js +1679 -0
  63. package/es6/legacy/es5/modules/mouse.js +124 -0
  64. package/es6/legacy/es5/modules/nav-link.js +123 -0
  65. package/es6/legacy/es5/modules/olderversions/animations-ease.js +1095 -0
  66. package/es6/legacy/es5/modules/olderversions/animations-update.js +1048 -0
  67. package/es6/legacy/es5/modules/olderversions/base-animations.js +636 -0
  68. package/es6/legacy/es5/modules/olderversions/base-component-class.js +100 -0
  69. package/es6/legacy/es5/modules/olderversions/base-data-binder-1.js +407 -0
  70. package/es6/legacy/es5/modules/olderversions/base-data-binder-class.js +358 -0
  71. package/es6/legacy/es5/modules/olderversions/base-layout-parser-class.js +172 -0
  72. package/es6/legacy/es5/modules/olderversions/base-mode-1.js +777 -0
  73. package/es6/legacy/es5/modules/olderversions/base-model-class.js +585 -0
  74. package/es6/legacy/es5/modules/olderversions/data-binder/element-binding/base-data-binder-class.js +358 -0
  75. package/es6/legacy/es5/modules/olderversions/data-binder/element-binding/base-model-class.js +585 -0
  76. package/es6/legacy/es5/modules/olderversions/data-binder/model-binding/base-data-binder-class.js +353 -0
  77. package/es6/legacy/es5/modules/olderversions/data-binder/model-binding/base-model-class.js +604 -0
  78. package/es6/legacy/es5/modules/olderversions/data-binder-update-watcher.js +640 -0
  79. package/es6/legacy/es5/modules/olderversions/data-tracker.js +187 -0
  80. package/es6/legacy/es5/modules/olderversions/event-update.js +666 -0
  81. package/es6/legacy/es5/modules/olderversions/nav-link.js +119 -0
  82. package/es6/legacy/es5/modules/olderversions/router-with-templates-1.js +785 -0
  83. package/es6/legacy/es5/modules/olderversions/router-with-templates.js +701 -0
  84. package/es6/legacy/es5/modules/prototypes/ajax.js +657 -0
  85. package/es6/legacy/es5/modules/prototypes/atom.js +65 -0
  86. package/es6/legacy/es5/modules/prototypes/component.js +972 -0
  87. package/es6/legacy/es5/modules/prototypes/data-binder.js +1089 -0
  88. package/es6/legacy/es5/modules/prototypes/data.js +1290 -0
  89. package/es6/legacy/es5/modules/prototypes/html-builder.js +414 -0
  90. package/es6/legacy/es5/modules/prototypes/layout.js +879 -0
  91. package/es6/legacy/es5/modules/router.js +1680 -0
  92. package/es6/legacy/es5/modules/state.js +274 -0
  93. package/es6/main.js +1331 -0
  94. package/es6/modules/ajax/ajax.js +514 -0
  95. package/es6/modules/animation/animation.js +236 -0
  96. package/es6/modules/animations/animation-controller.js +231 -0
  97. package/es6/modules/animations/animation.js +64 -0
  98. package/es6/modules/animations/attr-movement.js +66 -0
  99. package/es6/modules/animations/css-movement.js +170 -0
  100. package/es6/modules/animations/movement.js +131 -0
  101. package/es6/modules/animations/value.js +187 -0
  102. package/es6/modules/atom/atom.js +54 -0
  103. package/es6/modules/component/component.js +230 -0
  104. package/es6/modules/component/event-helper.js +119 -0
  105. package/es6/modules/component/jot.js +144 -0
  106. package/es6/modules/component/state-helper.js +262 -0
  107. package/es6/modules/component/unit.js +551 -0
  108. package/es6/modules/data/attrs.js +40 -0
  109. package/es6/modules/data/basic-data.js +500 -0
  110. package/es6/modules/data/data-utils.js +29 -0
  111. package/es6/modules/data/data.js +3 -0
  112. package/es6/modules/data/deep-data.js +541 -0
  113. package/es6/modules/data/model-service.js +528 -0
  114. package/es6/modules/data/model.js +133 -0
  115. package/es6/modules/data/simple-data.js +33 -0
  116. package/es6/modules/data-binder/connection-tracker.js +113 -0
  117. package/es6/modules/data-binder/connection.js +16 -0
  118. package/es6/modules/data-binder/data-binder.js +352 -0
  119. package/es6/modules/data-binder/data-pub-sub.js +141 -0
  120. package/es6/modules/data-binder/data-source.js +56 -0
  121. package/es6/modules/data-binder/element-source.js +219 -0
  122. package/es6/modules/data-binder/one-way-connection.js +46 -0
  123. package/es6/modules/data-binder/one-way-source.js +43 -0
  124. package/es6/modules/data-binder/source.js +36 -0
  125. package/es6/modules/data-binder/two-way-connection.js +75 -0
  126. package/es6/modules/data-binder/two-way-source.js +41 -0
  127. package/es6/modules/date/date.js +544 -0
  128. package/es6/modules/history/history.js +89 -0
  129. package/es6/modules/html-builder/html-builder.js +434 -0
  130. package/es6/modules/import/import.js +390 -0
  131. package/es6/modules/layout/layout-builder.js +1269 -0
  132. package/es6/modules/layout/layout-parser.js +134 -0
  133. package/es6/modules/layout/watcher-helper.js +282 -0
  134. package/es6/modules/mouse/mouse.js +114 -0
  135. package/es6/modules/router/component-helper.js +163 -0
  136. package/es6/modules/router/history-controller.js +216 -0
  137. package/es6/modules/router/nav-link.js +124 -0
  138. package/es6/modules/router/route.js +401 -0
  139. package/es6/modules/router/router.js +789 -0
  140. package/es6/modules/router/utils.js +31 -0
  141. package/es6/modules/state/state-target.js +91 -0
  142. package/es6/modules/state/state.js +171 -0
  143. package/es6/package-lock.json +13 -0
  144. package/es6/package.json +28 -0
  145. package/es6/shared/objects.js +99 -0
  146. package/legacy/es5/base.js +2968 -0
  147. package/legacy/es5/modules/ajax.js +663 -0
  148. package/legacy/es5/modules/animation.js +188 -0
  149. package/legacy/es5/modules/animations.js +1080 -0
  150. package/legacy/es5/modules/atom.js +65 -0
  151. package/legacy/es5/modules/component.js +1310 -0
  152. package/legacy/es5/modules/data-binder.js +1131 -0
  153. package/legacy/es5/modules/data.js +1808 -0
  154. package/legacy/es5/modules/date.js +525 -0
  155. package/legacy/es5/modules/form-validator.js +324 -0
  156. package/legacy/es5/modules/history.js +126 -0
  157. package/legacy/es5/modules/html-builder.js +461 -0
  158. package/legacy/es5/modules/layout.js +1679 -0
  159. package/legacy/es5/modules/mouse.js +124 -0
  160. package/legacy/es5/modules/nav-link.js +123 -0
  161. package/legacy/es5/modules/olderversions/animations-ease.js +1095 -0
  162. package/legacy/es5/modules/olderversions/animations-update.js +1048 -0
  163. package/legacy/es5/modules/olderversions/base-animations.js +636 -0
  164. package/legacy/es5/modules/olderversions/base-component-class.js +100 -0
  165. package/legacy/es5/modules/olderversions/base-data-binder-1.js +407 -0
  166. package/legacy/es5/modules/olderversions/base-data-binder-class.js +358 -0
  167. package/legacy/es5/modules/olderversions/base-layout-parser-class.js +172 -0
  168. package/legacy/es5/modules/olderversions/base-mode-1.js +777 -0
  169. package/legacy/es5/modules/olderversions/base-model-class.js +585 -0
  170. package/legacy/es5/modules/olderversions/data-binder/element-binding/base-data-binder-class.js +358 -0
  171. package/legacy/es5/modules/olderversions/data-binder/element-binding/base-model-class.js +585 -0
  172. package/legacy/es5/modules/olderversions/data-binder/model-binding/base-data-binder-class.js +353 -0
  173. package/legacy/es5/modules/olderversions/data-binder/model-binding/base-model-class.js +604 -0
  174. package/legacy/es5/modules/olderversions/data-binder-update-watcher.js +640 -0
  175. package/legacy/es5/modules/olderversions/data-tracker.js +187 -0
  176. package/legacy/es5/modules/olderversions/event-update.js +666 -0
  177. package/legacy/es5/modules/olderversions/nav-link.js +119 -0
  178. package/legacy/es5/modules/olderversions/router-with-templates-1.js +785 -0
  179. package/legacy/es5/modules/olderversions/router-with-templates.js +701 -0
  180. package/legacy/es5/modules/prototypes/ajax.js +657 -0
  181. package/legacy/es5/modules/prototypes/atom.js +65 -0
  182. package/legacy/es5/modules/prototypes/component.js +972 -0
  183. package/legacy/es5/modules/prototypes/data-binder.js +1089 -0
  184. package/legacy/es5/modules/prototypes/data.js +1290 -0
  185. package/legacy/es5/modules/prototypes/html-builder.js +414 -0
  186. package/legacy/es5/modules/prototypes/layout.js +879 -0
  187. package/legacy/es5/modules/router.js +1680 -0
  188. package/legacy/es5/modules/state.js +274 -0
  189. package/package.json +8 -3
  190. package/update +16 -0
@@ -0,0 +1,785 @@
1
+ /* base framework module */
2
+ /*
3
+ router module
4
+ */
5
+ (function()
6
+ {
7
+ "use strict";
8
+
9
+ var utils =
10
+ {
11
+ /* this will remove the begining and ending slashes on a url.
12
+ @param (string) uri = the uri to remove
13
+ @return (string) the uri */
14
+ removeSlashes: function(uri)
15
+ {
16
+ if(typeof uri === 'string')
17
+ {
18
+ var pattern = /(^\/|\/$)/g;
19
+ uri = uri.toString().replace(pattern, '');
20
+ }
21
+
22
+ return uri;
23
+ }
24
+ };
25
+
26
+ var routerNumber = 0;
27
+
28
+ /*
29
+ router
30
+
31
+ this will add client side routing to allow routes to be
32
+ setup and the router to navigate and activate the routes
33
+ that match the uri.
34
+
35
+ @param (string) baseURI = the root of the router uri
36
+ @param (string) title = the root title
37
+ */
38
+ var Router = function(baseURI, title)
39
+ {
40
+ this.version = '1.0.2';
41
+
42
+ /* this is the root of the uri for the routing object
43
+ and the base title */
44
+ this.baseURI = baseURI || '/';
45
+ this.title = (typeof title !== 'undefined')? title : '';
46
+ this.number = routerNumber++;
47
+
48
+ /* this will be used to accessour history object */
49
+ this.history = null;
50
+ /* this will store each route added to the
51
+ router. */
52
+ this.routes = [];
53
+ /* this will setup the router and check
54
+ to add the history support */
55
+ this.setup();
56
+ };
57
+
58
+ Router.prototype =
59
+ {
60
+ constructor: Router,
61
+
62
+ /* this will setup our route history */
63
+ setupHistory: function()
64
+ {
65
+ this.history = new RouteHistory(this);
66
+ this.history.setup();
67
+ },
68
+
69
+ /* this will add a route to the router.
70
+ @param (string) uri = the route uri
71
+ @param (string) template = the template name
72
+ @param [(function)] callBack = the call back function
73
+ @param [(string)] title = the route title
74
+ @param [(string)] id = the route id
75
+ @return (object) reference to the object */
76
+ add: function(uri, template, callBack, title, id)
77
+ {
78
+ if(typeof uri === 'string')
79
+ {
80
+ /* we need to format the uri */
81
+ uri = this.formatURI(uri);
82
+
83
+ var route = new Route(uri, template, callBack, title, id);
84
+ this.routes.push(route);
85
+ }
86
+ return this;
87
+ },
88
+
89
+ formatURI: function(uri)
90
+ {
91
+ /* we need to format the uri and setup the uri query
92
+ reg exp that is used to check the route */
93
+ uri = utils.removeSlashes(uri);
94
+ return this.createURI(uri);
95
+ },
96
+
97
+ /* this will create a uri with the base path and
98
+ the route uri.
99
+ @param (string) uri = the uri
100
+ @return (string) the uri */
101
+ createURI: function(uri)
102
+ {
103
+ var pathURI = '';
104
+ if(this.baseURI !== '/')
105
+ {
106
+ pathURI += this.baseURI;
107
+ }
108
+ pathURI += ((pathURI[pathURI.length - 1] !== '/')? '/' : '') + utils.removeSlashes(uri);
109
+
110
+ return pathURI;
111
+ },
112
+
113
+ /* this will get a route by the route settings.
114
+ @param (string) uri = the route uri
115
+ @param (string) template = the template name
116
+ @param [(function)] callBack = the call back function
117
+ @return (mixed) the routeobject or false on error */
118
+ getRoute: function(uri, template, callBack)
119
+ {
120
+ var routes = this.routes,
121
+ length = routes.length;
122
+ if(length)
123
+ {
124
+ for(var i = 0; i < length; i++)
125
+ {
126
+ var route = routes[i];
127
+ if(route.uri === uri && route.template === template && route.callBack === callBack)
128
+ {
129
+ return route;
130
+ }
131
+ }
132
+ }
133
+ return false;
134
+ },
135
+
136
+ /* this will remove a route from the router by the route settings.
137
+ @param (string) uri = the route uri
138
+ @param (string) template = the template name
139
+ @param [(function)] callBack = the call back function
140
+ @return (object) reference to the object */
141
+ remove: function(uri, template, callBack)
142
+ {
143
+ uri = this.formatURI(uri);
144
+
145
+ var route = this.getRoute(uri, template, callBack);
146
+ if(route)
147
+ {
148
+ var routes = this.routes;
149
+ var index = base.inArray(routes, route);
150
+ if(index > -1)
151
+ {
152
+ routes.splice(index, 1);
153
+ }
154
+ }
155
+ return this;
156
+ },
157
+
158
+ /* this will setup the history object
159
+ @return (object) reference to the object */
160
+ setup: function()
161
+ {
162
+ this.setupHistory();
163
+
164
+ /* this will route to the first url entered
165
+ when the router loads. this will fix the issue
166
+ that stopped the first endpoint from being
167
+ added to the history */
168
+ var endPoint = this.getEndPoint() || '/';
169
+ this.navigate(endPoint, null, true);
170
+ return this;
171
+ },
172
+
173
+ /* this will reset the router
174
+ @return (object) reference to the object */
175
+ reset: function()
176
+ {
177
+ this.routes = [];
178
+ return this;
179
+ },
180
+
181
+ /* this will activate any active routes
182
+ @return (object) reference to the object */
183
+ activate: function()
184
+ {
185
+ this.checkActiveRoutes();
186
+ return this;
187
+ },
188
+
189
+ /* this will navigate the router to the uri.
190
+ @param (string) uri = the relative uri
191
+ @param [(object)] data = a data object that will
192
+ be added to the history state object
193
+ @param [(bool)] replace = settrue to replace state
194
+ @return (object) a reference to the router object */
195
+ navigate: function(uri, data, replace)
196
+ {
197
+ uri = this.createURI(uri);
198
+ this.history.addState(uri, data, replace);
199
+ this.activate();
200
+ return this;
201
+ },
202
+
203
+ /* this will update the window title with the route title.
204
+ @param (object) route = a route that has a title
205
+ @return (object) a reference to the router object */
206
+ updateTitle: function(route)
207
+ {
208
+ if(route && route.title)
209
+ {
210
+ var title = route.title,
211
+ parent = this;
212
+
213
+ var getTitle = function(title)
214
+ {
215
+ /* this will uppercase each word in a string
216
+ @param (string) str = the string to uppercase
217
+ @return (string) the uppercase string */
218
+ var toTitleCase = function(str)
219
+ {
220
+ var pattern = /\w\S*/;
221
+ return str.replace(pattern, function(txt)
222
+ {
223
+ return txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase();
224
+ });
225
+ };
226
+
227
+ /* this will replace the params in the title
228
+ @param (string) str = the route title
229
+ @return (string) the title string */
230
+ var replaceParams = function(str)
231
+ {
232
+ if(str.indexOf(':') > -1)
233
+ {
234
+ var params = route.params;
235
+ for(var prop in params)
236
+ {
237
+ if(params.hasOwnProperty(prop))
238
+ {
239
+ var param = params[prop];
240
+ var pattern = new RegExp(':' + prop, 'gi');
241
+ str = str.replace(pattern, param);
242
+ }
243
+ }
244
+ }
245
+ return str;
246
+ };
247
+
248
+ if(title)
249
+ {
250
+ /* we want to replace any params in the title
251
+ and uppercase the title */
252
+ title = replaceParams(title);
253
+ var pattern = /-/g;
254
+ title = toTitleCase(title.replace(pattern, ' '));
255
+
256
+ /* we want to check to add the base title to the
257
+ to the end of the title */
258
+ if(parent.title != '')
259
+ {
260
+ title += " - " + parent.title;
261
+ }
262
+ }
263
+ return title;
264
+ };
265
+
266
+ document.title = getTitle(title);
267
+ }
268
+ return this;
269
+ },
270
+
271
+ /* this will get all active routes from a path.
272
+ @param [(string)] path = the path or the current
273
+ url path will be used
274
+ @return (array) an array of active routes */
275
+ checkActiveRoutes: function(path)
276
+ {
277
+ var active = [],
278
+ routes = this.routes,
279
+ length = routes.length;
280
+ if(length)
281
+ {
282
+ path = path || this.getPath();
283
+
284
+ var route,
285
+ check;
286
+
287
+ for(var i = 0; i < length; i++)
288
+ {
289
+ route = routes[i];
290
+ if(typeof route !== 'undefined')
291
+ {
292
+ check = this.check(route, path);
293
+ if(check !== false)
294
+ {
295
+ active[active.length] = route;
296
+ }
297
+ else
298
+ {
299
+ route.deactivate();
300
+ }
301
+ }
302
+ }
303
+ }
304
+ return active;
305
+ },
306
+
307
+ /* this will check to select a route if it the route uri
308
+ matches the path.
309
+ @param (object) route = the route
310
+ @param [(string)] path = the path. if left null the
311
+ active path will beused
312
+ @return (bool) true or false if active */
313
+ check: function(route, path)
314
+ {
315
+ var matched = false;
316
+
317
+ /* we want to check to use the supplied uri or get the
318
+ current uri if not setup */
319
+ path = path || this.getPath();
320
+
321
+ /* we want to check if the route uri matches the path uri */
322
+ var validURI = this.match(route, path);
323
+ if(validURI)
324
+ {
325
+ matched = true;
326
+ this.select(route);
327
+ }
328
+ return matched;
329
+ },
330
+
331
+ /* this will match a route if it the route uri
332
+ matches the path.
333
+ @param (object) route = the route
334
+ @param [(string)] path = the path. if left null the
335
+ active path will beused
336
+ @return (bool) true or false if active */
337
+ match: function(route, path)
338
+ {
339
+ /* we want to check if the route has been
340
+ deleted from the routes */
341
+ if(!route)
342
+ {
343
+ return false;
344
+ }
345
+
346
+ var matched = false;
347
+
348
+ /* we want to check to use the supplied uri or get the
349
+ current uri if not setup */
350
+ path = path || this.getPath();
351
+ var validURI = path.match(route.uriQuery);
352
+ if(validURI)
353
+ {
354
+ matched = true;
355
+
356
+ /* this will remove the first match from the
357
+ the params */
358
+ if(validURI && typeof validURI === 'object')
359
+ {
360
+ validURI.shift();
361
+ matched = validURI;
362
+ }
363
+
364
+ /* this will get the uri params of the route
365
+ and if set will save them to the route */
366
+ route.updateParams(validURI);
367
+ }
368
+ return matched;
369
+ },
370
+
371
+ /* this will get the param names from the route uri.
372
+ @param (object) route = the route object */
373
+ select: function(route)
374
+ {
375
+ if(route)
376
+ {
377
+ route.select();
378
+
379
+ this.updateTitle(route);
380
+ }
381
+ },
382
+
383
+ /* this will return the set endpoint not including the
384
+ base uri.
385
+ @return (string) the last endpoint */
386
+ getEndPoint: function()
387
+ {
388
+ var path = this.getPath();
389
+ return path.replace(this.baseURI, '');
390
+ },
391
+
392
+ /* this will get the location pathname.
393
+ @return (string) the location pathname */
394
+ getPath: function()
395
+ {
396
+ /* we want to get the window location path */
397
+ return window.location.pathname;
398
+ }
399
+ };
400
+
401
+ /*
402
+ RouteHistory
403
+
404
+ this will setup the history controller for
405
+ a router.
406
+
407
+ @param (object) router
408
+ */
409
+ var RouteHistory = function(router)
410
+ {
411
+ this.router = router;
412
+
413
+ /* this will check if the history api is supported
414
+ and enabled */
415
+ this.enabled = false;
416
+ this.locationId = 'base-app-router-' + router.number;
417
+ this.callBack = null;
418
+ this.callBackLink = null;
419
+ };
420
+
421
+ RouteHistory.prototype =
422
+ {
423
+ constructor: RouteHistory,
424
+
425
+ /* this will check to add history support is
426
+ the browser supports it */
427
+ setup: function()
428
+ {
429
+ /* we want to check if history is enabled */
430
+ this.enabled = base.history.isSupported();
431
+
432
+ /* we want to check to add the history event listener
433
+ that will check the popsate events and select the
434
+ nav option by the history state object */
435
+ if(this.enabled === true)
436
+ {
437
+ this.callBackLink = base.bind(this, this.checkLink);
438
+ this.callBack = base.bind(this, this.checkHistoryState);
439
+ this.addEvent();
440
+ }
441
+ return this;
442
+ },
443
+
444
+ checkLink: function(evt)
445
+ {
446
+ var target = evt.target || evt.srcElement;
447
+ var nodeName = target.nodeName.toLowerCase();
448
+ if(nodeName !== 'a')
449
+ {
450
+ /* this will check to get the parent to check
451
+ if the child is contained in a link */
452
+ target = target.parentNode;
453
+ if(target === null)
454
+ {
455
+ return true;
456
+ }
457
+
458
+ nodeName = target.nodeName.toLowerCase();
459
+ if(nodeName !== 'a')
460
+ {
461
+ return true;
462
+ }
463
+ }
464
+
465
+ if(!base.data(target, 'cancel-route'))
466
+ {
467
+ var href = target.getAttribute('href');
468
+ if(typeof href !== 'undefined')
469
+ {
470
+ var router = this.router;
471
+ var path = href.replace(router.baseURI, '');
472
+ router.navigate(path);
473
+
474
+ evt.preventDefault();
475
+ evt.stopPropagation();
476
+ return false;
477
+ }
478
+ }
479
+ },
480
+
481
+ /* this will add an event history listener that will
482
+ trigger when the window history is changed */
483
+ addEvent: function()
484
+ {
485
+ base.on('click', document, this.callBackLink);
486
+ base.on('popstate', window, this.callBack);
487
+ return this;
488
+ },
489
+
490
+ removeEvent: function()
491
+ {
492
+ base.off('click', document, this.callBackLink);
493
+ base.off('popstate', window, this.callBack);
494
+ return this;
495
+ },
496
+
497
+ checkHistoryState: function(evt)
498
+ {
499
+ /* we want to check if the event has a state and if the
500
+ state location is from the background */
501
+ var state = evt.state;
502
+ if(state && state.location === this.locationId)
503
+ {
504
+ evt.preventDefault();
505
+ evt.stopPropagation();
506
+
507
+ this.router.checkActiveRoutes(state.uri);
508
+ }
509
+ },
510
+
511
+ createStateObject: function(uri, data)
512
+ {
513
+ var stateObj = {
514
+ location: this.locationId,
515
+ uri: uri
516
+ };
517
+
518
+ if(data && typeof data === 'object')
519
+ {
520
+ stateObj = base.extendObject(stateObj, data);
521
+ }
522
+
523
+ return stateObj;
524
+ },
525
+
526
+ addState: function(uri, data, replace)
527
+ {
528
+ if(this.enabled === true)
529
+ {
530
+ var history = window.history,
531
+ lastState = history.state;
532
+
533
+ /* we want to check if the object is not already
534
+ the last saved state */
535
+ if(!lastState || lastState.uri !== uri)
536
+ {
537
+ var stateObj = this.createStateObject(uri, data);
538
+
539
+ /* this will check to push state or
540
+ replace state */
541
+ replace = replace === true? true : false;
542
+ var method = (replace === false)? 'pushState' : 'replaceState';
543
+ history[method](stateObj, null, uri);
544
+ }
545
+ }
546
+
547
+ return this;
548
+ }
549
+ };
550
+
551
+ var routeCount = 0;
552
+
553
+ /*
554
+ Route
555
+
556
+ @param (string) uri = the route uri
557
+ @param (string) template = the template name
558
+ @param [(function)] callBack = the call back function
559
+ @param [(string)] title = the route title
560
+ @param [(string)] id = the route id
561
+ */
562
+ var Route = function(uri, template, callBack, title, id)
563
+ {
564
+ this.id = id || 'bs-rte-' + routeCount++;
565
+ this.uri = uri;
566
+
567
+ /* route reg ex */
568
+ var uriMatch = this.setupUriMatch(uri);
569
+ this.uriQuery = new RegExp('^' + uriMatch);
570
+
571
+ /* params */
572
+ this.paramKeys = this.setupParamKeys(uri);
573
+ this.params = null;
574
+
575
+ /* this will setup the template and route component
576
+ if one has been set */
577
+ this.template = template;
578
+ this.setupRouteComponent();
579
+
580
+ this.callBack = callBack;
581
+ this.title = title;
582
+ };
583
+
584
+ Route.prototype =
585
+ {
586
+ constructor: Route,
587
+
588
+ /* this will setup the route uri string to be used in
589
+ a regexp match.
590
+ @param (string) uri = the route uri
591
+ @return (string) the uri to be used in a regexp match */
592
+ setupUriMatch: function(uri)
593
+ {
594
+ var uriQuery = "";
595
+ if(uri)
596
+ {
597
+ /* we want to setup the wild card and param
598
+ checks to be modified to the route uri string */
599
+ var allowAll = /(\*)/g,
600
+ param = /(:[^\/]*)/g,
601
+ optionalParams = /(\?\/+\*?)/g,
602
+ optionalSlash = /(\/):[^\/]*?\?/g,
603
+ filter = /\//g;
604
+ uriQuery = uri.replace(filter, "\/").replace(allowAll, '.*');
605
+
606
+ /* this will setup for optional slashes before the optional params */
607
+ uriQuery = uriQuery.replace(optionalSlash, function(str)
608
+ {
609
+ var pattern = /\//g;
610
+ return str.replace(pattern, '\/*');
611
+ });
612
+
613
+ /* this will setup for optional params and params
614
+ and stop at the last slash or query start */
615
+ uriQuery = uriQuery.replace(optionalParams, '?\/*').replace(param, '([^\/|?]*)');
616
+ }
617
+
618
+ /* we want to set and string end if the wild card is not set */
619
+ uriQuery += (uri[uri.length - 1] === '*')? '' : '$';
620
+ return uriQuery;
621
+ },
622
+
623
+ setupParamKeys: function(uri)
624
+ {
625
+ var params = [];
626
+ if(uri)
627
+ {
628
+ var pattern = /:(.[^\/]*)/g,
629
+ matches = uri.match(pattern);
630
+ if(matches)
631
+ {
632
+ for(var i = 0, maxLength = matches.length; i < maxLength; i++)
633
+ {
634
+ var param = matches[i];
635
+ if(param)
636
+ {
637
+ pattern = /(:|\?)/g;
638
+ var filter = /\*/g;
639
+ /* we need to remove the colon, question mark, or asterisk
640
+ from the key name */
641
+ param = param.replace(pattern, '').replace(filter, '');
642
+ params.push(param);
643
+ }
644
+ }
645
+ }
646
+ }
647
+ return params;
648
+ },
649
+
650
+ deactivate: function()
651
+ {
652
+ var component = this.component;
653
+ if(component)
654
+ {
655
+ component.remove();
656
+ }
657
+ },
658
+
659
+ setupRouteComponent: function()
660
+ {
661
+ var template = this.template;
662
+ this.component = typeof template === 'string'? new RouteComponent(template) : null;
663
+ },
664
+
665
+ select: function()
666
+ {
667
+ var params = this.params;
668
+ var callBack = this.callBack;
669
+ if(typeof callBack === 'function')
670
+ {
671
+ callBack(params);
672
+ }
673
+
674
+ var component = this.component;
675
+ if(component)
676
+ {
677
+ component.focus(params);
678
+ }
679
+ },
680
+
681
+ updateParams: function(values)
682
+ {
683
+ /* this will get the uri params of the route
684
+ and if set will save them to the route */
685
+ return (this.params = this.getParams(values));
686
+ },
687
+
688
+ /* this will get the param names from the route uri.
689
+ @param (array) values = the path param values
690
+ @return (mixed) an empty object or an object with key
691
+ and values of the params */
692
+ getParams: function(values)
693
+ {
694
+ var keys = this.paramKeys,
695
+ params = {};
696
+
697
+ if(values && typeof values === 'object')
698
+ {
699
+ /* we want to add the value to each key */
700
+ if(keys)
701
+ {
702
+ for(var i = 0, maxL = keys.length; i < maxL; i++)
703
+ {
704
+ var key = keys[i];
705
+ if(typeof key !== 'undefined')
706
+ {
707
+ params[key] = values[i];
708
+ }
709
+ }
710
+ }
711
+ }
712
+ return params;
713
+ }
714
+ };
715
+
716
+ var RouteComponent = function(template)
717
+ {
718
+ this.component = null;
719
+ this.setup = false;
720
+ this.template = template;
721
+ };
722
+
723
+ RouteComponent.prototype =
724
+ {
725
+ constructor: RouteComponent,
726
+
727
+ focus: function(params)
728
+ {
729
+ /* this will check to setup the component if
730
+ the component has notbeen setup */
731
+ if(this.setup === false && this.component === null)
732
+ {
733
+ this.create();
734
+ }
735
+
736
+ this.update(params);
737
+ },
738
+
739
+ /* this will create and setup a component
740
+ from a route template.
741
+ @param (object) route */
742
+ create: function()
743
+ {
744
+ this.setup = true;
745
+
746
+ var template = window[this.template];
747
+ if(template)
748
+ {
749
+ var comp = this.component = new template();
750
+ comp.setup();
751
+ }
752
+ },
753
+
754
+ /* this will remove a route component */
755
+ remove: function()
756
+ {
757
+ if(this.setup === true)
758
+ {
759
+ this.setup = false;
760
+
761
+ var component = this.component;
762
+ if(component)
763
+ {
764
+ if(typeof component.destroy === 'function')
765
+ {
766
+ component.destroy();
767
+ }
768
+ this.component = null;
769
+ }
770
+ }
771
+ },
772
+
773
+ update: function(params)
774
+ {
775
+ var component = this.component;
776
+ if(component && typeof component.update === 'function')
777
+ {
778
+ component.update(params);
779
+ }
780
+ }
781
+ };
782
+
783
+ base.extend.router = Router;
784
+
785
+ })();