$.extend({ router: { routes: { list: [], current: null, add: function (route, level, callback, context) { var r, keys, i; if (typeof this.list[level] === 'undefined') { this.list[level] = []; } r = { 'route': route, 'level': level, 'callback': function (params) { if (callback !== undefined) { if (context === undefined) { callback(params); } else { callback.call(context, params); } } }, }, i = this.list[level].length; this.list[level][i] = r; }, clean: function (level) { this.list = this.list.slice(0, level); }, cleanAll: function () { this.list = this.list.slice(0, 0); }, search: function (hash) { var stop = false, i, j, regex, result, extracted; i = this.list.length - 1; while ((stop === false) && (i >= 0)) { j = 0; while ((stop === false) && (j < this.list[i].length)) { extracted = $.router.extractKeys(this.list[i][j].route); regex = new RegExp(extracted.regex); if (regex.test(hash.route)) { result = regex.exec(hash.route); stop = true; result.shift(); for (var k = 0; k < result.length; k += 1) { hash[extracted.keys[k]] = result[k]; } this.current = this.list[i][j]; this.list[i][j].callback(hash); } j += 1; } i -= 1; } } }, extractKeys: function (regex) { var re_key = new RegExp(/:(\w+)/), keys = [], result; while (re_key.test(regex)) { result = re_key.exec(regex); keys.push(result[1]); regex = regex.replace(result[0], '([^\/]+)'); } return {'regex': regex, 'keys': keys} }, deserialize: function (params) { var result = {}, p, params = params.split('&'); while (params.length) { p = params.shift().split('='); if (p[0] !== '') { if (p.length === 2) { result[p[0]] = p[1] === 'true' ? true : p[1]; } else { result[p[0]] = true; } } } return result; }, serialize: function (obj) { return $.param(obj); }, parseHash: function (hashTag) { var re = new RegExp(/(?:^#?([a-zA-Z0-9\/_-]+))(?:\?([A-Za-z0-9\/&=_-]+))?/g), groups = re.exec(hashTag), r, params = {}; groups.shift(); // route r = groups[0]; // params if (groups[1] !== undefined) { params = this.deserialize(groups[1]); } return params.length === 0 ? {'route': r} : $.extend({'route': r}, params); }, hashHandler: function () { var hashTag = window.location.href.split('#')[1], hashInfo = $.router.parseHash(hashTag); $.router.routes.search(hashInfo) }, } }); $(window).bind('hashchange', $.router.hashHandler); $(window).bind('load', $.router.hashHandler);