172 lines
5.5 KiB
JavaScript
172 lines
5.5 KiB
JavaScript
define(['yua'], function(){
|
||
|
||
function Router(){
|
||
this.table = {get: []};
|
||
this.errorFn = null;
|
||
this.history = null;
|
||
this.hash = '';
|
||
this.started = false;
|
||
this.init = {};
|
||
}
|
||
|
||
var defaultOptions = {
|
||
prefix: /^(#!|#)[\/]?/, //hash前缀正则
|
||
historyOpen: true, //是否开启hash历史
|
||
allowReload: true //连续点击同一个链接是否重新加载
|
||
};
|
||
var isMouseUp = true;
|
||
|
||
var ruleRegExp = /(:id)|(\{id\})|(\{id:([A-z\d\,\[\]\{\}\-\+\*\?\!:\^\$]*)\})/g;
|
||
|
||
Router.prototype = {
|
||
error: function(callback){
|
||
this.errorFn = callback;
|
||
},
|
||
config: function(opts){
|
||
if(this.started)
|
||
return console.error('Router config has been set');
|
||
|
||
this.started = true;
|
||
if(!opts.allowReload)
|
||
opts.historyOpen = true;
|
||
this.init = yua.mix({}, defaultOptions, opts);
|
||
},
|
||
_getRegExp: function(rule, opts){
|
||
var re = rule.replace(ruleRegExp, function(m, p1, p2, p3, p4){
|
||
var w = '([\\w.-]';
|
||
if(p1 || p2){
|
||
return w + '+)';
|
||
}else{
|
||
if(!/^\{[\d\,]+\}$/.test(p4)){
|
||
w = '(';
|
||
}
|
||
return w + p4 + ')';
|
||
}
|
||
})
|
||
re = re.replace(/(([^\\])([\/]+))/g, '$2\\/').replace(/(([^\\])([\.]+))/g, '$2\\.').replace(/(([^\\])([\-]+))/g, '$2\\-').replace(/(\(.*)(\\[\-]+)(.*\))/g, '$1-$3');
|
||
re = '^' + re + '$';
|
||
opts.regexp = new RegExp(re)
|
||
return opts;
|
||
},
|
||
_add: function(method, rule, callback){
|
||
if(!this.started)
|
||
this.config({});
|
||
|
||
var table = this.table[method.toLowerCase()];
|
||
if (rule.charAt(0) !== "/") {
|
||
console.error('char "/" must be in front of router rule');
|
||
return;
|
||
}
|
||
rule = rule.replace(/^[\/]+|[\/]+$|\s+/g, '');
|
||
var opts = {};
|
||
opts.rule = rule;
|
||
opts.callback = callback;
|
||
yua.Array.ensure(table, this._getRegExp(rule, opts));
|
||
},
|
||
_route: function(method, hash){
|
||
var hash = hash.trim();
|
||
var table = this.table[method];
|
||
var init = this.init;
|
||
|
||
if(!init.allowReload && hash === this.history)
|
||
return;
|
||
|
||
if(init.historyOpen){
|
||
this.history = hash;
|
||
if(yua.ls)
|
||
yua.ls('lastHash', hash);
|
||
}
|
||
|
||
for(var i = 0, obj; obj = table[i++];){
|
||
var args = hash.match(obj.regexp);
|
||
if(args){
|
||
args.shift();
|
||
return obj.callback.apply(obj, args)
|
||
}
|
||
}
|
||
this.errorFn && this.errorFn(hash);
|
||
},
|
||
on: function(rule, callback){
|
||
var _this = this
|
||
if(Array.isArray(rule)){
|
||
rule.forEach(function(it){
|
||
_this._add('get', it, callback);
|
||
})
|
||
}else{
|
||
this._add('get', rule, callback);
|
||
}
|
||
}
|
||
}
|
||
|
||
yua.bind(window, 'load', function(){
|
||
if(!yua.router.started)
|
||
return;
|
||
var prefix = yua.router.init.prefix;
|
||
var hash = location.hash;
|
||
hash = hash.replace(prefix, "").trim();
|
||
yua.router._route('get', hash);
|
||
});
|
||
|
||
|
||
if('onhashchange' in window){
|
||
window.addEventListener('hashchange', function(event){
|
||
if(!isMouseUp)
|
||
return;
|
||
var prefix = yua.router.init.prefix;
|
||
var hash = location.hash.replace(prefix, "").trim();
|
||
yua.router._route('get', hash)
|
||
})
|
||
}
|
||
|
||
//劫持页面上所有点击事件,如果事件源来自链接或其内部,
|
||
//并且它不会跳出本页,并且以"#/"或"#!/"开头,那么触发updateLocation方法
|
||
yua.bind(document, "mousedown", function(event){
|
||
var defaultPrevented = "defaultPrevented" in event ? event['defaultPrevented'] : event.returnValue === false
|
||
if (defaultPrevented || event.ctrlKey || event.metaKey || event.which === 2)
|
||
return
|
||
var target = event.target
|
||
while (target.nodeName !== "A") {
|
||
target = target.parentNode
|
||
if (!target || target.tagName === "BODY") {
|
||
return
|
||
}
|
||
}
|
||
|
||
if (targetIsThisWindow(target.target)){
|
||
if(!yua.router.started)
|
||
return;
|
||
var href = target.getAttribute("href") || target.getAttribute("xlink:href"),
|
||
prefix = yua.router.init.prefix;
|
||
|
||
if (href === null || !prefix.test(href))
|
||
return
|
||
|
||
yua.router.hash = href.replace(prefix, "").trim();
|
||
event.preventDefault();
|
||
location.hash = href;
|
||
isMouseUp = false;
|
||
}
|
||
})
|
||
|
||
yua.bind(document, "mouseup", function(){
|
||
if(!isMouseUp){
|
||
yua.router._route('get', yua.router.hash);
|
||
isMouseUp = true;
|
||
}
|
||
|
||
})
|
||
|
||
|
||
//判定A标签的target属性是否指向自身
|
||
//thanks https://github.com/quirkey/sammy/blob/master/lib/sammy.js#L219
|
||
function targetIsThisWindow(targetWindow) {
|
||
if (!targetWindow || targetWindow === window.name || targetWindow === '_self' || (targetWindow === 'top' && window == window.top)) {
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
|
||
yua.ui.router = '0.0.1'
|
||
|
||
return yua.router = new Router;
|
||
}) |
JavaScript
95.2%
CSS
4.8%