From 32b59ff372e8b714c041b4314cbcc87c7ce662da Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Thu, 19 Sep 2013 23:48:11 -0500 Subject: [PATCH] Basic route stuff working --- hacking/RouteController.js | 60 ++++++++++++++++++++++++++------- hacking/RouteController.unit.js | 14 ++++++++ hacking/route.html | 9 ++++- 3 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 hacking/RouteController.unit.js diff --git a/hacking/RouteController.js b/hacking/RouteController.js index 3437f6714b..c20f12c0a4 100644 --- a/hacking/RouteController.js +++ b/hacking/RouteController.js @@ -2,6 +2,11 @@ * Adapted from Backbone.js */ (function(window, document, ionic) { + var optionalParam = /\((.*?)\)/g; + var namedParam = /(\(\?)?:\w+/g; + var splatParam = /\*\w+/g; + var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g; + // Cached regex for stripping a leading hash/slash and trailing space. var routeStripper = /^[#\/]|\s+$/g; @@ -15,6 +20,7 @@ this.options = options; this.root = this.options.root || '/'; + this.root = ('/' + this.root + '/').replace(rootStripper, '/'); this.handlers = []; @@ -25,17 +31,51 @@ }; RouteViewController.prototype = { + when: function(route, callback) { + var _this = this; + + route = this._routeToRegExp(route); + + this.handlers.unshift({ + route: route, + callback: function(fragment) { + var args = _this._extractParameters(route, fragment); + callback && callback.apply(_this, args); + } + }); + }, + + // Convert a route string into a regular expression, suitable for matching + // against the current location hash. + _routeToRegExp: function(route) { + route = route.replace(escapeRegExp, '\\$&') + .replace(optionalParam, '(?:$1)?') + .replace(namedParam, function(match, optional){ + return optional ? match : '([^\/]+)'; + }) + .replace(splatParam, '(.*?)'); + return new RegExp('^' + route + '$'); + }, + + // Given a route, and a URL fragment that it matches, return the array of + // extracted decoded parameters. Empty or unmatched parameters will be + // treated as `null` to normalize cross-browser behavior. + _extractParameters: function(route, fragment) { + var params = route.exec(fragment).slice(1); + var extracted = []; + for(var i = 0; i < params.length; i++) { + if(param) { + extracted.push(decodeURIComponent(param)); + } + } + }, _bindEvents: function() { var _this = this; window.addEventListener('popstate', function(event) { - console.log("POP STATE", event, window.location, window.location.hash); _this.checkUrl(event); }); - window.addEventListener('pushstate', function(event) { - console.log("PUSH STATE", event, window.location); - }); }, checkUrl: function(e) { var current = this.getFragment(); @@ -44,15 +84,11 @@ }, getFragment: function(fragment, forcePushState) { if (fragment == null) { - if (this._hasPushState || !this._wantsHashChange || forcePushState) { - fragment = this.location.pathname; - var root = this.root.replace(this.trailingSlash, ''); - if (!fragment.indexOf(root)) fragment = fragment.substr(root.length); - } else { - fragment = this.getHash(); - } + fragment = this.location.pathname; + var root = this.root.replace(this.trailingSlash, ''); + if (!fragment.indexOf(root)) fragment = fragment.substr(root.length); } - return fragment.replace(this.routeStripper, ''); + return fragment.replace(routeStripper, ''); }, getHash: function(window) { var match = (window || this).location.href.match(/#(.*)$/); diff --git a/hacking/RouteController.unit.js b/hacking/RouteController.unit.js new file mode 100644 index 0000000000..cd687809e0 --- /dev/null +++ b/hacking/RouteController.unit.js @@ -0,0 +1,14 @@ +describe('RouteController', function() { + + beforeEach(function() { + }); + + it('Should init', function() { + var rc = new RouteViewController({ + root: 'hacking/route.html'; + }); + rc.when('/', function() { + console.log('Loaded'); + }); + }); +}); diff --git a/hacking/route.html b/hacking/route.html index 965cbab6f9..10527c0f00 100644 --- a/hacking/route.html +++ b/hacking/route.html @@ -15,13 +15,20 @@
- Cats + Cats