@@ -5,6 +5,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
5
5
6
6
// Builds state properties from definition passed to registerState()
7
7
var stateBuilder = {
8
+
8
9
// Derive parent state from a hierarchical name only if 'parent' is not explicitly defined.
9
10
// state.children = [];
10
11
// if (parent) parent.children.push(state);
@@ -92,28 +93,52 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
92
93
if ( own ) ownParams . push ( p ) ;
93
94
} ) ;
94
95
return ownParams ;
96
+ } ,
97
+
98
+ // Keep a full path from the root down to this state as this is needed for state activation.
99
+ path : function ( state ) {
100
+ return state . parent ? state . parent . path . concat ( state ) : [ ] ; // exclude root from path
101
+ } ,
102
+
103
+ // Speed up $state.contains() as it's used a lot
104
+ includes : function ( state ) {
105
+ var includes = state . parent ? extend ( { } , state . parent . includes ) : { } ;
106
+ includes [ state . name ] = true ;
107
+ return includes ;
95
108
}
96
109
} ;
97
110
98
- function findState ( stateOrName ) {
99
- var state ;
100
- if ( isString ( stateOrName ) ) {
101
- state = states [ stateOrName ] ;
102
- if ( ! state ) throw new Error ( "No such state '" + stateOrName + "'" ) ;
103
- } else {
104
- state = states [ stateOrName . name ] ;
105
- if ( ! state || state !== stateOrName && state . self !== stateOrName )
106
- throw new Error ( "Invalid or unregistered state" ) ;
111
+
112
+ function findState ( stateOrName , base ) {
113
+ var isStr = isString ( stateOrName ) ,
114
+ name = isStr ? stateOrName : stateOrName . name ,
115
+ path = isStr ? name . match ( / ^ ( (?: (?: \^ ) (?: \. ) ? ) { 1 , } ) ( .+ ) / ) : null ;
116
+
117
+ if ( path && path . length ) {
118
+ if ( ! base ) throw new Error ( "No reference point given for path '" + stateOrName + "'" ) ;
119
+ var rel = path [ 1 ] . split ( "." ) , i = 0 , pathLength = rel . length - 1 , current = base ;
120
+
121
+ for ( ; i < pathLength ; i ++ ) {
122
+ if ( rel [ i ] === "^" ) current = current . parent ;
123
+ if ( ! current ) throw new Error ( "Path '" + name + "' not valid for state '" + base . name + "'" ) ;
124
+ }
125
+ name = current . name + "." + path [ 2 ] ;
126
+ }
127
+ var state = states [ name ] ;
128
+
129
+ if ( state && ( isStr || ( ! isStr && ( state === stateOrName || state . self === stateOrName ) ) ) ) {
130
+ return state ;
107
131
}
108
- return state ;
132
+ throw new Error ( isStr ? "No such state '" + name + "'" : "Invalid or unregistered state" ) ;
109
133
}
110
134
135
+
111
136
function registerState ( state ) {
112
137
// Wrap a new object around the state so we can store our private details easily.
113
138
state = inherit ( state , {
114
139
self : state ,
115
140
resolve : state . resolve || { } ,
116
- toString : function ( ) { return this . name ; }
141
+ toString : function ( ) { return this . name ; }
117
142
} ) ;
118
143
119
144
var name = state . name ;
@@ -123,13 +148,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
123
148
for ( var key in stateBuilder ) {
124
149
state [ key ] = stateBuilder [ key ] ( state ) ;
125
150
}
126
-
127
- // Keep a full path from the root down to this state as this is needed for state activation.
128
- state . path = state . parent ? state . parent . path . concat ( state ) : [ ] ; // exclude root from path
129
-
130
- // Speed up $state.contains() as it's used a lot
131
- var includes = state . includes = state . parent ? extend ( { } , state . parent . includes ) : { } ;
132
- includes [ name ] = true ;
151
+ states [ name ] = state ;
133
152
134
153
// Register the state in the global state list and with $urlRouter if necessary.
135
154
if ( ! state [ 'abstract' ] && state . url ) {
@@ -139,10 +158,10 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
139
158
}
140
159
} ] ) ;
141
160
}
142
- states [ name ] = state ;
143
161
return state ;
144
162
}
145
163
164
+
146
165
// Implicit root state that is always active
147
166
root = registerState ( {
148
167
name : '' ,
0 commit comments