Skip to content
This repository was archived by the owner on Sep 20, 2020. It is now read-only.

Commit 72a6ce5

Browse files
author
christhielen
committed
fix(sticky): Exit all orphaned inactive states.
closes #217
1 parent 41c0d7f commit 72a6ce5

File tree

2 files changed

+44
-22
lines changed

2 files changed

+44
-22
lines changed

src/sticky.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,9 +433,9 @@ angular.module("ct.ui.router.extras.sticky").config(
433433

434434
// We may transition directly to an inactivated state, reactivating it. In this case, we should
435435
// exit all of that state's inactivated children.
436-
var inactiveOrphans = stickyTransitions.deepestReactivateChildren;
436+
var inactiveOrphans = stickyTransitions.inactiveOrphans;
437437
// Add surrogate exited states for all orphaned descendants of the Deepest Reactivated State
438-
surrogateFromPath = surrogateFromPath.concat(map(stickyTransitions.deepestReactivateChildren, function (exiting) {
438+
surrogateFromPath = surrogateFromPath.concat(map(stickyTransitions.inactiveOrphans, function (exiting) {
439439
return stateExitedSurrogate(exiting);
440440
}));
441441
exited = exited.concat(inactiveOrphans);

src/stickyProvider.js

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ function $StickyStateProvider($stateProvider, uirextras_coreProvider) {
148148
// keep: The number of states being "kept"
149149
// inactives: Array of all states which will be inactive if the transition is completed.
150150
// 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
152152
// Note: Transitioning directly to an inactive state with inactive children will reactivate the state, but exit all the inactive children.
153153
// enter: Enter transition type for all added states. This is a sticky array to "toStates" array in $state.transitionTo.
154154
// 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) {
217217

218218
// Get the currently inactive states (before the transition is processed), mapped by parent state
219219
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, []);
234258

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);
239261

240262
// Now calculate the states that will be inactive if this transition succeeds.
241263
// We have already pushed the transitionType == "inactivate" states to 'inactives'.
@@ -248,7 +270,7 @@ function $StickyStateProvider($stateProvider, uirextras_coreProvider) {
248270

249271
result.inactives = inactives;
250272
result.reactivatingStates = reactivatingStates;
251-
result.deepestReactivateChildren = deepestReactivateChildren;
273+
result.inactiveOrphans = orphans;
252274

253275
return result;
254276
},

0 commit comments

Comments
 (0)