@@ -148,7 +148,7 @@ function $StickyStateProvider($stateProvider, uirextras_coreProvider) {
148
148
// keep: The number of states being "kept"
149
149
// inactives: Array of all states which will be inactive if the transition is completed.
150
150
// reactivatingStates: Array of all states which will be reactivated if the transition is completed.
151
- // deepestReactivateChildren : Array of inactive children states of the toState, if the toState is being reactivated.
151
+ // inactiveOrphans : Array of inactive states being orphaned by the transition
152
152
// Note: Transitioning directly to an inactive state with inactive children will reactivate the state, but exit all the inactive children.
153
153
// enter: Enter transition type for all added states. This is a sticky array to "toStates" array in $state.transitionTo.
154
154
// exit: Exit transition type for all removed states. This is a sticky array to "fromStates" array in $state.transitionTo.
@@ -217,25 +217,47 @@ function $StickyStateProvider($stateProvider, uirextras_coreProvider) {
217
217
218
218
// Get the currently inactive states (before the transition is processed), mapped by parent state
219
219
var inactivesByAllParents = mapInactivesByImmediateParent ( ) ;
220
-
221
- // If we are transitioning directly to an inactive state, and that state also has inactive children,
222
- // then find those children so that they can be exited.
223
- var deepestReactivateChildren = [ ] ;
224
- if ( deepestReactivate === transition . toState ) {
225
- deepestReactivateChildren = inactivesByAllParents [ deepestReactivate . name ] || [ ] ;
226
- }
227
- // Add them to the list of states being exited.
228
- exitingStates = exitingStates . concat ( deepestReactivateChildren ) ;
229
-
230
- // Find any other inactive children of any of the states being "exited"
231
- var exitingChildren = map ( exitingStates , function ( state ) {
232
- return inactivesByAllParents [ state . name ] || [ ] ;
233
- } ) ;
220
+ var allInactives = Object . keys ( inactiveStates ) . map ( function ( name ) { return inactiveStates [ name ] ; } ) ;
221
+
222
+ function flattenReduce ( memo , list ) { return memo . concat ( list ) ; }
223
+ function uniqReduce ( memo , orphan ) { if ( memo . indexOf ( orphan ) === - 1 ) memo . push ( orphan ) ; return memo ; }
224
+
225
+ function isChildOf ( parent ) { return function ( child ) { return child . parent === parent ; } ; }
226
+ function isDefined ( obj ) { return obj != null ; }
227
+ function notEntered ( state ) { return enteringStates . indexOf ( state ) === - 1 ; }
228
+ function notSticky ( state ) { return ! state . sticky ; }
229
+ function inactiveDescendents ( state ) { return inactivesByAllParents [ state . name ] || [ ] ; }
230
+
231
+ // Find all the "orphaned" states: those states that are currently inactive, but should now be exited.
232
+ //
233
+ // Given:
234
+ // - states A (sticky: true), B, A.foo, A.bar
235
+ // - A.foo is currently inactive
236
+ // - B is currently active
237
+ // Orphan case 1)
238
+ // - Transition to A.bar orphans the inactive state A.foo; it should be exited
239
+ // Orphan case 2)
240
+ // - Transition directly to A orphans the inactive state A.foo; it should be exited
241
+ var orphanedParents = enteringStates
242
+ // For each entering state in the path, find any immediate children states which are currently inactive
243
+ . map ( function ( entering ) { return allInactives . filter ( isChildOf ( entering ) ) ; } )
244
+ // Flatten nested arrays. Now we have an array of inactive states that are children of the ones being entered.
245
+ . reduce ( flattenReduce , [ ] )
246
+ // Consider "orphaned": only those children that are themselves not currently being entered
247
+ . filter ( notEntered )
248
+ // Consider "orphaned": only those children that are not themselves sticky states.
249
+ . filter ( notSticky ) ;
250
+
251
+ // orphanedParents may be root nodes of larger inactive state trees; the whole tree is orphaned.
252
+ // For each parent, find any orphaned children
253
+ var orphanedDescendents = orphanedParents . map ( inactiveDescendents )
254
+ . reduce ( flattenReduce , [ ] )
255
+ . reduce ( uniqReduce , [ ] ) ; // remove any dupes (necessary? not necessary? dunno)
256
+
257
+ var orphans = orphanedParents . concat ( orphanedDescendents ) . reduce ( uniqReduce , [ ] ) ;
234
258
235
- // append each array of children-of-exiting states to "exitingStates" because they will be exited too.
236
- forEach ( exitingChildren , function ( children ) {
237
- exitingStates = exitingStates . concat ( children ) ;
238
- } ) ;
259
+ // Add them to the list of states being exited.
260
+ exitingStates = exitingStates . concat ( orphans ) ;
239
261
240
262
// Now calculate the states that will be inactive if this transition succeeds.
241
263
// We have already pushed the transitionType == "inactivate" states to 'inactives'.
@@ -248,7 +270,7 @@ function $StickyStateProvider($stateProvider, uirextras_coreProvider) {
248
270
249
271
result . inactives = inactives ;
250
272
result . reactivatingStates = reactivatingStates ;
251
- result . deepestReactivateChildren = deepestReactivateChildren ;
273
+ result . inactiveOrphans = orphans ;
252
274
253
275
return result ;
254
276
} ,
0 commit comments