@@ -266,7 +266,10 @@ var $RouteProvider = [
266
266
$route : {
267
267
name : expression . name ,
268
268
params : copy ( expression . params ) ,
269
- route : path
269
+ route : path ,
270
+ remove : function ( ) {
271
+ delete routes [ expression . name ] ;
272
+ }
270
273
}
271
274
} ;
272
275
} ;
@@ -836,7 +839,7 @@ angular.module('dotjem.routing').provider('$route', $RouteProvider).value('$rout
836
839
* Handlers for transitions can be specified in a number of ways, where the most simple handler is an injectable `function`.
837
840
* <br/>
838
841
* Here is a basic example:
839
- * <pre>
842
+ * <pre dx-syntax class="brush: js" >
840
843
* angular.module('demo', ['dotjem.routing'])
841
844
* .config(['$stateTransitionProvider', function(stp) {
842
845
* stp
@@ -877,7 +880,7 @@ angular.module('dotjem.routing').provider('$route', $RouteProvider).value('$rout
877
880
* When registering transitions like demonstrated in the example above, this will be maped to the "between" stage.
878
881
* <br/>
879
882
* To target specific stages of a transition use a transition object instead as in the example below:
880
- * <pre>
883
+ * <pre dx-syntax class="brush: js" >
881
884
* angular.module('demo', ['dotjem.routing'])
882
885
* .config(['$stateTransitionProvider', function(stp) {
883
886
* stp
@@ -915,7 +918,7 @@ angular.module('dotjem.routing').provider('$route', $RouteProvider).value('$rout
915
918
* <br/>
916
919
* So if we just use `*` we target all existing states under `root`, and we can define a global handler that gets called on all transitions by using `*` both as destination and source.
917
920
*
918
- * <pre>
921
+ * <pre dx-syntax class="brush: js" >
919
922
* angular.module('demo', ['dotjem.routing'])
920
923
* .config(['$stateTransitionProvider', function(stp) {
921
924
* stp
@@ -927,7 +930,7 @@ angular.module('dotjem.routing').provider('$route', $RouteProvider).value('$rout
927
930
*
928
931
* We can also target all transitions to or from a specific state that way:
929
932
*
930
- * <pre>
933
+ * <pre dx-syntax class="brush: js" >
931
934
* angular.module('demo', ['dotjem.routing'])
932
935
* .config(['$stateTransitionProvider', function(stp) {
933
936
* stp
@@ -944,7 +947,7 @@ angular.module('dotjem.routing').provider('$route', $RouteProvider).value('$rout
944
947
*
945
948
* This was global handlers, but we might also wan't to target any state below a specific state:
946
949
*
947
- * <pre>
950
+ * <pre dx-syntax class="brush: js" >
948
951
* angular.module('demo', ['dotjem.routing'])
949
952
* .config(['$stateTransitionProvider', function(stp) {
950
953
* stp
@@ -963,7 +966,7 @@ angular.module('dotjem.routing').provider('$route', $RouteProvider).value('$rout
963
966
*
964
967
* In addition to using the `*` wildcart to target multiple states, it is also possible to use arrays for a more specific match.
965
968
*
966
- * <pre>
969
+ * <pre dx-syntax class="brush: js" >
967
970
* angular.module('demo', ['dotjem.routing'])
968
971
* .config(['$stateTransitionProvider', function(stp) {
969
972
* stp
@@ -984,7 +987,7 @@ angular.module('dotjem.routing').provider('$route', $RouteProvider).value('$rout
984
987
*
985
988
* Each of the states, wildcards can also be used:
986
989
*
987
- * <pre>
990
+ * <pre dx-syntax class="brush: js" >
988
991
* angular.module('demo', ['dotjem.routing'])
989
992
* .config(['$stateTransitionProvider', function(stp) {
990
993
* stp
@@ -1190,11 +1193,10 @@ function $StateTransitionProvider() {
1190
1193
function ( $q , $inject ) {
1191
1194
var $transition = {
1192
1195
root : root ,
1193
- find : find
1196
+ find : find ,
1197
+ to : noop
1194
1198
} ;
1195
1199
1196
- return $transition ;
1197
-
1198
1200
function find ( from , to ) {
1199
1201
var transitions = findTransitions ( toName ( from ) ) , handlers = extractHandlers ( transitions , toName ( to ) ) ;
1200
1202
@@ -1291,6 +1293,12 @@ function $StateTransitionProvider() {
1291
1293
} while ( index ++ < names . length ) ;
1292
1294
return transitions ;
1293
1295
}
1296
+
1297
+ //var current = $q.when(null);
1298
+ //function to(args: { state; params; updateroute?; }) {
1299
+ // current.then(function () { });
1300
+ //}
1301
+ return $transition ;
1294
1302
} ] ;
1295
1303
}
1296
1304
angular . module ( 'dotjem.routing' ) . provider ( '$stateTransition' , $StateTransitionProvider ) ;
@@ -1305,7 +1313,7 @@ angular.module('dotjem.routing').provider('$stateTransition', $StateTransitionPr
1305
1313
* <br/>
1306
1314
* Here is a very basic example of configuring states.
1307
1315
*
1308
- * <pre>
1316
+ * <pre dx-syntax class="brush: js" >
1309
1317
* angular.module('demo', ['dotjem.routing']).
1310
1318
* config(['$stateProvider', function($stateProvider) {
1311
1319
* $stateProvider
@@ -1435,7 +1443,7 @@ var $StateProvider = [
1435
1443
*
1436
1444
* The following registrations would result in the ilustated hierachy.
1437
1445
*
1438
- * <pre>
1446
+ * <pre dx-syntax class="brush: js" >
1439
1447
* .state('home', {})
1440
1448
* .state('home.recents', {})
1441
1449
* .state('home.all', {})
@@ -1462,19 +1470,89 @@ var $StateProvider = [
1462
1470
* @returns {Object } self
1463
1471
*
1464
1472
* @description
1465
- * Adds a new route definition to the `$route ` service.
1473
+ * Adds a new state definition to the `$state ` service.
1466
1474
*/
1467
- this . state = function ( fullname , state ) {
1475
+ /**
1476
+ * @ngdoc method
1477
+ * @name dotjem.routing.$stateProvider#state
1478
+ * @methodOf dotjem.routing.$stateProvider
1479
+ *
1480
+ * @param {function } Registration function, this is an injectable function and can be used to load state configurations
1481
+ * from the backend, e.g. using the `$http` service.
1482
+ *
1483
+ * The function should at least depend on `$register` which is used in place of the {@link dotjem.routing.$stateProvider#state state} function.
1484
+ *
1485
+ * <pre dx-syntax class="brush: js">
1486
+ * .state(['$register', '$http', function($register, $http) {
1487
+ * return $http.get('/stateConfig').then(function (result) {
1488
+ * // result is delivered as:
1489
+ * // {
1490
+ * // 'state1name': { ...params },
1491
+ * // 'state2name': { ...params }
1492
+ * // }
1493
+ * // in this example.
1494
+ * angular.forEach(result.data, function (state, name) {
1495
+ * $register(name, state);
1496
+ * });
1497
+ * });
1498
+ * }])
1499
+ * </pre>
1500
+ *
1501
+ * Note: The function should return a promise that is resolved when registration is done, so that the state service knows when it can resume normal operation.
1502
+ *
1503
+ * @returns {Object } self
1504
+ */
1505
+ this . state = function ( nameOrFunc , state ) {
1506
+ if ( ! isInjectable ( nameOrFunc ) ) {
1507
+ StateRules . validateName ( nameOrFunc ) ;
1508
+
1509
+ initializers . push ( function ( ) {
1510
+ internalRegisterState ( nameOrFunc , state ) ;
1511
+ return null ;
1512
+ } ) ;
1513
+ } else {
1514
+ initializers . push ( function ( ) {
1515
+ return nameOrFunc ;
1516
+ } ) ;
1517
+ }
1518
+ return this ;
1519
+ } ;
1520
+
1521
+ function registerState ( fullname , state ) {
1468
1522
StateRules . validateName ( fullname ) ;
1469
1523
1524
+ internalRegisterState ( fullname , state ) ;
1525
+ }
1526
+
1527
+ function internalRegisterState ( fullname , state ) {
1470
1528
var parent = browser . lookup ( fullname , 1 ) ;
1471
1529
parent . add ( factory . createState ( fullname , state , parent ) ) ;
1472
- return this ;
1473
- } ;
1530
+ }
1531
+
1532
+ var initializers = [ ] ;
1474
1533
1475
1534
this . $get = [
1476
- '$rootScope' , '$q' , '$inject' , '$route' , '$view' , '$stateTransition' , '$location' , '$scroll' , '$resolve' ,
1477
- function ( $rootScope , $q , $inject , $route , $view , $transition , $location , $scroll , $resolve ) {
1535
+ '$rootScope' , '$q' , '$inject' , '$route' , '$view' , '$stateTransition' , '$location' , '$scroll' , '$resolve' , '$exceptionHandler' ,
1536
+ function ( $rootScope , $q , $inject , $route , $view , $transition , $location , $scroll , $resolve , $exceptionHandler ) {
1537
+ function init ( promise ) {
1538
+ root . clear ( $routeProvider ) ;
1539
+
1540
+ forEach ( initializers , function ( init ) {
1541
+ try {
1542
+ var injectable = init ( ) ;
1543
+ if ( injectable !== null ) {
1544
+ promise = promise . then ( function ( ) {
1545
+ return $inject . invoke ( injectable , injectable , { $register : registerState } ) ;
1546
+ } ) ;
1547
+ }
1548
+ } catch ( error ) {
1549
+ $exceptionHandler ( error ) ;
1550
+ }
1551
+ } ) ;
1552
+ return promise ;
1553
+ }
1554
+ var initPromise = init ( $q . when ( 0 ) ) ;
1555
+
1478
1556
/**
1479
1557
* @ngdoc object
1480
1558
* @name dotjem.routing.$state
@@ -1716,24 +1794,41 @@ var $StateProvider = [
1716
1794
*
1717
1795
* @returns {boolean } true if the stats mathces, otherwise false.
1718
1796
*/
1797
+ /**
1798
+ * @ngdoc method
1799
+ * @name dotjem.routing.$state#reinitialize
1800
+ * @methodOf dotjem.routing.$state
1801
+ *
1802
+ * @description
1803
+ * Clears all states and associated routes and reinitializes the state service.
1804
+ */
1719
1805
var urlbuilder = new StateUrlBuilder ( $route ) ;
1720
1806
1721
1807
var forceReload = null , current = root , $state = {
1722
1808
// NOTE: root should not be used in general, it is exposed for testing purposes.
1723
1809
root : root ,
1724
1810
current : extend ( root . self , { $params : buildParams ( ) } ) ,
1725
1811
params : buildParams ( ) ,
1812
+ reinitialize : function ( ) {
1813
+ return initPromise = init ( initPromise ) ;
1814
+ } ,
1726
1815
goto : function ( state , params ) {
1727
- goto ( {
1728
- state : state ,
1729
- params : buildParams ( params ) ,
1730
- updateroute : true
1816
+ return initPromise . then ( function ( ) {
1817
+ goto ( {
1818
+ state : state ,
1819
+ params : buildParams ( params ) ,
1820
+ updateroute : true
1821
+ } ) ;
1731
1822
} ) ;
1732
1823
} ,
1733
1824
lookup : function ( path ) {
1734
1825
return browser . resolve ( current , path , true ) ;
1735
1826
} ,
1736
- reload : reload ,
1827
+ reload : function ( state ) {
1828
+ return initPromise . then ( function ( ) {
1829
+ reload ( state ) ;
1830
+ } ) ;
1831
+ } ,
1737
1832
url : function ( arg1 , arg2 , arg3 ) {
1738
1833
var state = current ;
1739
1834
if ( arguments . length === 0 ) {
@@ -1779,6 +1874,7 @@ var $StateProvider = [
1779
1874
goto ( { state : root , params : buildParams ( ) } ) ;
1780
1875
}
1781
1876
} ) ;
1877
+
1782
1878
$rootScope . $on ( EVENTS . ROUTE_UPDATE , function ( ) {
1783
1879
var route = $route . current , params = buildParams ( route . params , route . pathParams , route . searchParams ) ;
1784
1880
@@ -1811,15 +1907,22 @@ var $StateProvider = [
1811
1907
var context = new Context ( $state , function ( ) {
1812
1908
} , root ) . complete ( ) ;
1813
1909
var running = context ;
1910
+ var comparer = new StateComparer ( ) ;
1814
1911
1815
1912
function goto ( args ) {
1816
1913
var ctx , scrollTo , useUpdate = false ;
1817
1914
1818
- //$transition.create(args.state, args.params, up)
1819
1915
if ( ! running . ended ) {
1820
1916
running . abort ( ) ;
1821
1917
}
1822
1918
1919
+ //var next = browser.resolve(current, toName(args.state), false);
1920
+ //var path = comparer.path(current, next, $state.params, args.params);
1921
+ //$transition.to(args, function (state) {
1922
+ // $state.params = state.$params;
1923
+ // $state.current = state;
1924
+ //});
1925
+ //$transition.create(args.state, args.params, up)
1823
1926
ctx = running = context . next ( function ( ctx ) {
1824
1927
context = ctx ;
1825
1928
} ) ;
@@ -2891,6 +2994,18 @@ var State = (function () {
2891
2994
return this . fullname === state || this . fullname === rootName + '.' + state ;
2892
2995
} ;
2893
2996
2997
+ State . prototype . clear = function ( route ) {
2998
+ forEach ( this . _children , function ( state ) {
2999
+ state . clear ( route ) ;
3000
+ } ) ;
3001
+
3002
+ if ( this . _route ) {
3003
+ this . _route . remove ( ) ;
3004
+ }
3005
+
3006
+ this . _children = { } ;
3007
+ } ;
3008
+
2894
3009
State . prototype . isActive = function ( state ) {
2895
3010
if ( this . is ( state ) ) {
2896
3011
return true ;
@@ -3072,6 +3187,72 @@ var StateComparer = (function () {
3072
3187
paramChanges : paramChanges
3073
3188
} ;
3074
3189
} ;
3190
+
3191
+ StateComparer . prototype . isSameState = function ( from , to ) {
3192
+ if ( from === to ) {
3193
+ return true ;
3194
+ }
3195
+
3196
+ //Note: If one of them is undefined, note that if both are undefined the above if would have returned.
3197
+ if ( isUndefined ( from ) || isUndefined ( to ) ) {
3198
+ return false ;
3199
+ }
3200
+
3201
+ return to . name === from . name ;
3202
+ } ;
3203
+
3204
+ StateComparer . prototype . isEquals = function ( from , to ) {
3205
+ return this . isSameState ( from , to ) && equals ( to . params , from . params ) ;
3206
+ } ;
3207
+
3208
+ StateComparer . prototype . path = function ( from , to , fromParams , toParams ) {
3209
+ var fromArray = this . toArray ( from , fromParams , false ) , toArray = this . toArray ( to , toParams , true ) , count = Math . max ( fromArray . length , toArray . length ) ;
3210
+
3211
+ var unchanged = [ ] ;
3212
+ var deactivate = [ ] ;
3213
+ var activate = [ ] ;
3214
+ var change = { } ;
3215
+
3216
+ for ( var i = 0 ; i < count ; i ++ ) {
3217
+ var f = fromArray [ i ] , t = toArray [ i ] ;
3218
+ if ( this . isEquals ( f , t ) ) {
3219
+ unchanged . push ( f ) ;
3220
+ } else if ( this . isSameState ( f , t ) ) {
3221
+ deactivate . push ( f ) ;
3222
+ activate . push ( t ) ;
3223
+ } else {
3224
+ deactivate = deactivate . concat ( fromArray . slice ( i , fromArray . length ) ) ;
3225
+ deactivate . reverse ( ) ;
3226
+
3227
+ activate = activate . concat ( toArray . slice ( i , toArray . length ) ) ;
3228
+ break ;
3229
+ }
3230
+ }
3231
+
3232
+ change . changed = deactivate . concat ( activate ) ;
3233
+ change . unchanged = unchanged ;
3234
+
3235
+ return change ;
3236
+ } ;
3237
+
3238
+ StateComparer . prototype . toArray = function ( state , params , activate ) {
3239
+ var states = [ ] , current = state ;
3240
+ do {
3241
+ states . push ( { state : current , name : current . fullname , params : this . extractParams ( params , current ) , activate : activate } ) ;
3242
+ } while ( current = current . parent ) ;
3243
+ states . reverse ( ) ;
3244
+ return states ;
3245
+ } ;
3246
+
3247
+ StateComparer . prototype . extractParams = function ( params , current ) {
3248
+ var paramsObj = { } ;
3249
+ if ( current . route ) {
3250
+ forEach ( current . route . params , function ( param , name ) {
3251
+ paramsObj [ name ] = params [ name ] ;
3252
+ } ) ;
3253
+ }
3254
+ return paramsObj ;
3255
+ } ;
3075
3256
return StateComparer ;
3076
3257
} ) ( ) ;
3077
3258
0 commit comments