-
Notifications
You must be signed in to change notification settings - Fork 3k
/
Copy pathurlRouter.js
117 lines (100 loc) · 3.79 KB
/
urlRouter.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
$UrlRouterProvider.$inject = ['$urlMatcherFactoryProvider'];
function $UrlRouterProvider( $urlMatcherFactory) {
var rules = [],
otherwise = null;
// Returns a string that is a prefix of all strings matching the RegExp
function regExpPrefix(re) {
var prefix = /^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(re.source);
return (prefix != null) ? prefix[1].replace(/\\(.)/g, "$1") : '';
}
// Interpolates matched values into a String.replace()-style pattern
function interpolate(pattern, match) {
return pattern.replace(/\$(\$|\d{1,2})/, function (m, what) {
return match[what === '$' ? 0 : Number(what)];
});
}
this.rule =
function (rule) {
if (!isFunction(rule)) throw new Error("'rule' must be a function");
rules.push(rule);
return this;
};
this.otherwise =
function (rule) {
if (isString(rule)) {
var redirect = rule;
rule = function () { return redirect; };
}
else if (!isFunction(rule)) throw new Error("'rule' must be a function");
otherwise = rule;
return this;
};
function handleIfMatch($injector, handler, match) {
if (!match) return false;
var result = $injector.invoke(handler, handler, { $match: match });
return isDefined(result) ? result : true;
}
this.when =
function (what, handler) {
var redirect, handlerIsString = isString(handler);
if (isString(what)) what = $urlMatcherFactory.compile(what);
if (!handlerIsString && !isFunction(handler) && !isArray(handler))
throw new Error("invalid 'handler' in when()");
var strategies = {
matcher: function (what, handler) {
if (handlerIsString) {
redirect = $urlMatcherFactory.compile(handler);
handler = ['$match', function ($match) { return redirect.format($match); }];
}
return extend(function ($injector, $location) {
return handleIfMatch($injector, handler, what.exec($location.path(), $location.search()));
}, {
prefix: isString(what.prefix) ? what.prefix : ''
});
},
regex: function (what, handler) {
if (what.global || what.sticky) throw new Error("when() RegExp must not be global or sticky");
if (handlerIsString) {
redirect = handler;
handler = ['$match', function ($match) { return interpolate(redirect, $match); }];
}
return extend(function ($injector, $location) {
return handleIfMatch($injector, handler, what.exec($location.path()));
}, {
prefix: regExpPrefix(what)
});
}
};
var check = { matcher: $urlMatcherFactory.isMatcher(what), regex: what instanceof RegExp };
for (var n in check) {
if (check[n]) {
return this.rule(strategies[n](what, handler));
}
}
throw new Error("invalid 'what' in when()");
};
this.$get =
[ '$location', '$rootScope', '$injector',
function ($location, $rootScope, $injector) {
// TODO: Optimize groups of rules with non-empty prefix into some sort of decision tree
function update() {
function check(rule) {
var handled = rule($injector, $location);
if (handled) {
if (isString(handled)) $location.replace().url(handled);
return true;
}
return false;
}
var n=rules.length, i;
for (i=0; i<n; i++) {
if (check(rules[i])) return;
}
// always check otherwise last to allow dynamic updates to the set of rules
if (otherwise) check(otherwise);
}
$rootScope.$on('$locationChangeSuccess', update);
return {};
}];
}
angular.module('ui.router.router').provider('$urlRouter', $UrlRouterProvider);