Created
February 15, 2012 16:01
-
-
Save draeton/1836916 to your computer and use it in GitHub Desktop.
Deeplinking?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* http://jsbin.com/opibuk/13/edit | |
*/ | |
(function (window) { | |
"use strict"; | |
// shortcuts | |
var location = window.location; | |
var setInterval = window.setInterval; | |
var clearInterval = window.clearInterval; | |
// native onhashchange event check | |
var _native = window.hasOwnProperty("onhashchange"); | |
// no operation | |
var _noop = function () {}; | |
// holds previous method | |
var _onhashchange = null; | |
// interval reference for non-native browsers | |
var _interval = null; | |
// default routes | |
var _default = { | |
"default": { | |
test: null, | |
callback: _noop, | |
context: window | |
} | |
}; | |
// holds all module routes | |
var _routes = _default; | |
// type check | |
var isArray = function (obj) { | |
return Object.prototype.toString.call(obj) === "[object Array]"; | |
}; | |
/** | |
* each | |
* | |
* Apply a callback to each item in an object | |
* | |
* @param {Object} obj | |
* @param {Function} callback | |
*/ | |
var each = function (obj, callback) { | |
var i; | |
var l; | |
var ret; | |
if (isArray(obj)) { | |
for (i = 0, l = obj.length; i < l; i++) { | |
ret = callback.call(obj, i, obj[i]); | |
if (ret === false) { | |
return; | |
} | |
} | |
} else { | |
for (i in obj) { | |
if (obj.hasOwnProperty(i)) { | |
ret = callback.call(obj, i, obj[i]); | |
if (ret === false) { | |
return; | |
} | |
} | |
} | |
} | |
}; | |
/** | |
* routeToTest | |
* | |
* Convert a route string to a regular expression for matching | |
* | |
* @param {String} route | |
* @return {RegExp} | |
*/ | |
var routeToTest = function (route) { | |
var prefix = "^#!"; | |
var suffix = "$"; | |
var test; | |
route = route.replace(/\:\w+/gi, function () { | |
return "([^/]+)"; | |
}); | |
route = route.replace(/\:\*/, function () { | |
return "(.+)"; | |
}); | |
test = new RegExp(prefix + route + suffix); | |
return test; | |
}; | |
/** | |
* addRoute | |
* | |
* Add a single route to the _routes object | |
* | |
* @param {String} route | |
* @param {Function} callback | |
* @param {Object} context | |
*/ | |
var addRoute = function (route, callback, context) { | |
var test = routeToTest(route); | |
_routes[route] = { | |
test: test, | |
callback: callback || _noop, | |
context: context || window | |
}; | |
}; | |
/** | |
* removeRoute | |
* | |
* Remove a single route from the _routes object | |
* | |
* @param {String} route | |
*/ | |
var removeRoute = function (route) { | |
delete _routes[route]; | |
}; | |
/** | |
* clearRoutes | |
* | |
* Clear all routes from the _routes object | |
*/ | |
var clearRoutes = function () { | |
_routes = _default; | |
}; | |
/** | |
* matchRoutes | |
* | |
* Return an array of routes that match a hash | |
* | |
* @param {String} hash | |
* @return {Array} | |
*/ | |
var matchRoutes = function (hash) { | |
var matched = []; | |
each(_routes, function (i, route) { | |
var matches = hash.match(route.test); | |
if (matches) { | |
matched.push({ | |
hash: hash, | |
args: matches.slice(1), | |
callback: route.callback, | |
context: route.context | |
}); | |
} | |
}); | |
// choose default if no match | |
if (!matched.length) { | |
matched.push({ | |
hash: hash, | |
args: [], | |
callback: _routes["default"].callback, | |
context: _routes["default"].context | |
}); | |
} | |
return matched; | |
}; | |
/** | |
* deeplink | |
* | |
* When the hash changes, check for matched routes and call | |
* callbacks | |
*/ | |
var deeplink = function () { | |
var routes = matchRoutes(location.hash); | |
each(routes, function (i, route) { | |
var args = [route.hash].concat(route.args); | |
var callback = route.callback; | |
var context = route.context; | |
callback.apply(context, args); | |
}); | |
}; | |
/** | |
* start | |
* | |
* Set up the hashchange listener to call the deeplink | |
* function. Also, call the deeplink function | |
*/ | |
var start = function () { | |
var current = location.hash; | |
if (_native) { | |
_onhashchange = window.onhashchange; | |
window.onhashchange = deeplink; | |
} else { | |
_interval = setInterval(function () { | |
if (current !== location.hash) { | |
current = location.hash; | |
deeplink(); | |
} | |
}, 100); | |
} | |
deeplink(); | |
}; | |
/** | |
* stop | |
* | |
* Remove the hashchange listener for the deeplink | |
* function | |
*/ | |
var stop = function () { | |
if (_native) { | |
window.onhashchange = _onhashchange; | |
} else { | |
clearInterval(_interval); | |
} | |
}; | |
// add global | |
window.Deeplink = { | |
addRoute: addRoute, | |
removeRoute: removeRoute, | |
clearRoutes: clearRoutes, | |
start: start, | |
stop: stop | |
}; | |
}(window)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (window) { | |
"use strict"; | |
var console = window.console; | |
var location = window.location; | |
var Deeplink = window.Deeplink; | |
var setTimeout = window.setTimeout; | |
// test deeplinking | |
Deeplink.addRoute("default", function (hash) { | |
console.log("test route 0 reached", hash); | |
}); | |
Deeplink.addRoute("/test1/:one/:two", function (hash, one, two) { | |
console.log("test route 1 reached", hash, one, two); | |
}); | |
Deeplink.addRoute("/test2/:*", function (hash, suffix) { | |
console.log("test route 2 reached", hash, suffix); | |
}); | |
Deeplink.start(); | |
setTimeout(function () { | |
location.hash = "#!/test1/apple/banana"; | |
}, 0); | |
setTimeout(function () { | |
location.hash = "#!/test2/ford/lincoln/mercury"; | |
}, 200); | |
setTimeout(function () { | |
location.hash = "#!/test0/no/match"; | |
}, 400); | |
}(window)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment