Skip to content
This repository was archived by the owner on Sep 20, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions src/core.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
var mod_core = angular.module("ct.ui.router.extras.core", [ "ui.router" ]);

var internalStates = {}, stateRegisteredCallbacks = [];
mod_core.config([ '$stateProvider', '$injector', function ($stateProvider, $injector) {
mod_core.config([ '$stateProvider', '$injector', 'uirextras_coreProvider', function ($stateProvider, $injector, uirextras_coreProvider) {
// Decorate any state attribute in order to get access to the internal state representation.
$stateProvider.decorator('parent', function (state, parentFn) {
// Capture each internal UI-Router state representations as opposed to the user-defined state object.
// The internal state is, e.g., the state returned by $state.$current as opposed to $state.current
internalStates[state.self.name] = state;
var core = uirextras_coreProvider.$get();
core.internalStates[state.self.name] = state;
// Add an accessor for the internal state from the user defined state
state.self.$$state = function () {
return internalStates[state.self.name];
return core.internalStates[state.self.name];
};

angular.forEach(stateRegisteredCallbacks, function(callback) { callback(state); });
angular.forEach(core.stateRegisteredCallbacks, function(callback) { callback(state); });
return parentFn(state);
});
}]);
Expand Down Expand Up @@ -140,11 +140,31 @@ function inherit(parent, extra) {
return extend(new (extend(function () { }, {prototype: parent}))(), extra);
}

function onStateRegistered(callback) { stateRegisteredCallbacks.push(callback); }

mod_core.provider("uirextras_core", function() {
var core = {
var stateRegisteredCallbacks = [];
function onStateRegistered(callback) { stateRegisteredCallbacks.push(callback); }
var _StickyState; // internal reference to $stickyStateProvider
var internalStates = {}; // Map { statename -> InternalStateObj } holds internal representation of all states
var root; // Root state, internal representation
var pendingTransitions = []; // One transition may supersede another. This holds references to all pending transitions
var pendingRestore; // The restore function from the superseded transition
var inactivePseudoState; // This pseudo state holds all the inactive states' locals (resolved state data, such as views etc)
var reactivatingLocals = { }; // This is a prent locals to the inactivePseudoState locals, used to hold locals for states being reactivated
var versionHeuristics = { // Heuristics used to guess the current UI-Router Version
hasParamSet: false
};
var core = {
nr: Math.round(Math.random()*1000),
internalStates: internalStates,
stateRegisteredCallbacks: stateRegisteredCallbacks,
_StickyState: _StickyState,
root: root,
pendingTransitions: pendingTransitions,
pendingRestore: pendingRestore,
inactivePseudoState: inactivePseudoState,
reactivatingLocals: reactivatingLocals,
versionHeuristics: versionHeuristics,
onStateRegistered: onStateRegistered,
forEach: forEach,
extend: extend,
Expand Down
2 changes: 1 addition & 1 deletion src/future.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

_futureStateProvider.$inject = [ '$stateProvider', '$urlRouterProvider', '$urlMatcherFactoryProvider', 'uirextras_coreProvider' ];
function _futureStateProvider($stateProvider, $urlRouterProvider, $urlMatcherFactory, uirextras_coreProvider) {
var core = uirextras_coreProvider;
var core = uirextras_coreProvider.$get();
var internalStates = core.internalStates;
var stateFactories = {}, futureStates = {};
var lazyloadInProgress = false, resolveFunctions = [], initPromise, initDone = false;
Expand Down
102 changes: 47 additions & 55 deletions src/sticky.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,57 +56,49 @@


// ------------------------ Sticky State module-level variables -----------------------------------------------
var _StickyState; // internal reference to $stickyStateProvider
var internalStates = {}; // Map { statename -> InternalStateObj } holds internal representation of all states
var root, // Root state, internal representation
pendingTransitions = [], // One transition may supersede another. This holds references to all pending transitions
pendingRestore, // The restore function from the superseded transition
inactivePseudoState, // This pseudo state holds all the inactive states' locals (resolved state data, such as views etc)
reactivatingLocals = { }, // This is a prent locals to the inactivePseudoState locals, used to hold locals for states being reactivated
versionHeuristics = { // Heuristics used to guess the current UI-Router Version
hasParamSet: false
};

// Creates a blank surrogate state
function SurrogateState(type) {
function SurrogateState(core, type) {
return {
resolve: { },
locals: {
globals: root && root.locals && root.locals.globals
globals: core.root && core.root.locals && core.root.locals.globals
},
views: { },
self: { },
params: { },
ownParams: ( versionHeuristics.hasParamSet ? { $$equals: function() { return true; } } : []),
ownParams: ( core.versionHeuristics.hasParamSet ? { $$equals: function() { return true; } } : []),
surrogateType: type
};
}

// ------------------------ Sticky State registration and initialization code ----------------------------------
// Grab a copy of the $stickyState service for use by the transition management code
angular.module("ct.ui.router.extras.sticky").run(["$stickyState", function ($stickyState) {
_StickyState = $stickyState;
angular.module("ct.ui.router.extras.sticky").run(["$stickyState", "uirextras_core", function ($stickyState, uirextras_core) {
var core = uirextras_core;
core._StickyState = $stickyState;
}]);

angular.module("ct.ui.router.extras.sticky").config(
[ "$provide", "$stateProvider", '$stickyStateProvider', '$urlMatcherFactoryProvider', 'uirextras_coreProvider',
function ($provide, $stateProvider, $stickyStateProvider, $urlMatcherFactoryProvider, uirextras_coreProvider) {
var core = uirextras_coreProvider;
var core = uirextras_coreProvider.$get();
var internalStates = core.internalStates;
var inherit = core.inherit;
var inheritParams = core.inheritParams;
var forEach = core.forEach;
var map = core.map;
var filterObj = core.filterObj;

versionHeuristics.hasParamSet = !!$urlMatcherFactoryProvider.ParamSet;
core.versionHeuristics.hasParamSet = !!$urlMatcherFactoryProvider.ParamSet;
// inactivePseudoState (__inactives) holds all the inactive locals which includes resolved states data, i.e., views, scope, etc
inactivePseudoState = angular.extend(new SurrogateState("__inactives"), { self: { name: '__inactives' } });
core.inactivePseudoState = angular.extend(new SurrogateState(core, "__inactives"), { self: { name: '__inactives' } });
// Reset other module scoped variables. This is to primarily to flush any previous state during karma runs.
root = pendingRestore = undefined;
pendingTransitions = [];
//FIXME
core.root = core.pendingRestore = undefined;
core.pendingTransitions = [];

uirextras_coreProvider.onStateRegistered(function(state) {
core.onStateRegistered(function(state) {
// Register the ones marked as "sticky"
if (state.self.sticky === true) {
$stickyStateProvider.registerStickyState(state.self);
Expand All @@ -117,16 +109,16 @@ angular.module("ct.ui.router.extras.sticky").config(
// Decorate the $state service, so we can decorate the $state.transitionTo() function with sticky state stuff.
$provide.decorator("$state", ['$delegate', '$log', '$q', function ($state, $log, $q) {
// Note: this code gets run only on the first state that is decorated
root = $state.$current;
internalStates[""] = root;
root.parent = inactivePseudoState; // Make inactivePsuedoState the parent of root. "wat"
inactivePseudoState.parent = undefined; // Make inactivePsuedoState the real root.
core.root = $state.$current;
internalStates[""] = core.root;
core.root.parent = core.inactivePseudoState; // Make inactivePsuedoState the parent of root. "wat"
core.inactivePseudoState.parent = undefined; // Make inactivePsuedoState the real root.
// Add another locals bucket, as a parent to inactivatePseudoState locals.
// This is for temporary storage of locals of states being reactivated while a transition is pending
// This is necessary in some cases where $viewContentLoading is triggered before the $state.$current is updated to the toState.
inactivePseudoState.locals = inherit(reactivatingLocals, inactivePseudoState.locals);
root.locals = inherit(inactivePseudoState.locals, root.locals); // make root locals extend the __inactives locals.
delete inactivePseudoState.locals.globals;
core.inactivePseudoState.locals = inherit(core.reactivatingLocals, core.inactivePseudoState.locals);
core.root.locals = inherit(core.inactivePseudoState.locals, core.root.locals); // make root locals extend the __inactives locals.
delete core.inactivePseudoState.locals.globals;

// Hold on to the real $state.transitionTo in a module-scope variable.
$state_transitionTo = $state.transitionTo;
Expand All @@ -137,11 +129,11 @@ angular.module("ct.ui.router.extras.sticky").config(
// TODO: Move this to module.run?
// TODO: I'd rather have root.locals prototypally inherit from inactivePseudoState.locals
// Link root.locals and inactives.locals. Do this at runtime, after root.locals has been set.
if (!inactivePseudoState.locals)
inactivePseudoState.locals = root.locals;
var idx = pendingTransitions.length;
if (pendingRestore) {
pendingRestore();
if (!core.inactivePseudoState.locals)
core.inactivePseudoState.locals = core.root.locals;
var idx = core.pendingTransitions.length;
if (core.pendingRestore) {
core.pendingRestore();
if (DEBUG) {
$log.debug("Restored paths from pending transition");
}
Expand Down Expand Up @@ -179,8 +171,8 @@ angular.module("ct.ui.router.extras.sticky").config(
// method to be re-entrant (for example, when superceding a transition, i.e., redirect). The decorated
// transitionTo checks right away if there is a pending transition in progress and restores the paths
// if so using pendingRestore.
pendingRestore = null;
pendingTransitions.splice(idx, 1); // Remove this transition from the list
core.pendingRestore = null;
core.pendingTransitions.splice(idx, 1); // Remove this transition from the list
};

// All decorated transitions have their toState.path and fromState.path replaced. Surrogate states also make
Expand All @@ -200,13 +192,13 @@ angular.module("ct.ui.router.extras.sticky").config(


function stateReactivatedSurrogatePhase1(state) {
var surrogate = angular.extend(new SurrogateState("reactivate_phase1"), { locals: state.locals });
var surrogate = angular.extend(new SurrogateState(core, "reactivate_phase1"), { locals: state.locals });
surrogate.self = angular.extend({}, state.self);
return surrogate;
}

function stateReactivatedSurrogatePhase2(state) {
var surrogate = angular.extend(new SurrogateState("reactivate_phase2"), state);
var surrogate = angular.extend(new SurrogateState(core, "reactivate_phase2"), state);
var oldOnEnter = surrogate.self.onEnter;
surrogate.resolve = {}; // Don't re-resolve when reactivating states (fixes issue #22)
// TODO: Not 100% sure if this is necessary. I think resolveState will load the views if I don't do this.
Expand All @@ -215,7 +207,7 @@ angular.module("ct.ui.router.extras.sticky").config(
// ui-router sets locals on the surrogate to a blank locals (because we gave it nothing to resolve)
// Re-set it back to the already loaded state.locals here.
surrogate.locals = state.locals;
_StickyState.stateReactivated(state);
core._StickyState.stateReactivated(state);
};
restore.addRestoreFunction(function () {
state.self.onEnter = oldOnEnter;
Expand All @@ -224,11 +216,11 @@ angular.module("ct.ui.router.extras.sticky").config(
}

function stateInactivatedSurrogate(state) {
var surrogate = new SurrogateState("inactivate");
var surrogate = new SurrogateState(core, "inactivate");
surrogate.self = state.self;
var oldOnExit = state.self.onExit;
surrogate.self.onExit = function () {
_StickyState.stateInactivated(state);
core._StickyState.stateInactivated(state);
};
restore.addRestoreFunction(function () {
state.self.onExit = oldOnExit;
Expand All @@ -239,7 +231,7 @@ angular.module("ct.ui.router.extras.sticky").config(
function stateEnteredSurrogate(state, toParams) {
var oldOnEnter = state.self.onEnter;
state.self.onEnter = function () {
_StickyState.stateEntering(state, toParams, oldOnEnter);
core._StickyState.stateEntering(state, toParams, oldOnEnter);
};
restore.addRestoreFunction(function () {
state.self.onEnter = oldOnEnter;
Expand All @@ -252,7 +244,7 @@ angular.module("ct.ui.router.extras.sticky").config(
function stateUpdateParamsSurrogate(state, toParams) {
var oldOnEnter = state.self.onEnter;
state.self.onEnter = function () {
_StickyState.stateEntering(state, toParams, oldOnEnter, true);
core._StickyState.stateEntering(state, toParams, oldOnEnter, true);
};
restore.addRestoreFunction(function () {
state.self.onEnter = oldOnEnter;
Expand All @@ -264,7 +256,7 @@ angular.module("ct.ui.router.extras.sticky").config(
function stateExitedSurrogate(state) {
var oldOnExit = state.self.onExit;
state.self.onExit = function () {
_StickyState.stateExiting(state, exited, oldOnExit);
core._StickyState.stateExiting(state, exited, oldOnExit);
};
restore.addRestoreFunction(function () {
state.self.onExit = oldOnExit;
Expand Down Expand Up @@ -299,8 +291,8 @@ angular.module("ct.ui.router.extras.sticky").config(
reloadStateTree: reloadStateTree
};

pendingTransitions.push(currentTransition); // TODO: See if a list of pending transitions is necessary.
pendingRestore = restore;
core.pendingTransitions.push(currentTransition); // TODO: See if a list of pending transitions is necessary.
core.pendingRestore = restore;

// If we're reloading from a state and below, temporarily add a param to the top of the state tree
// being reloaded, and add a param value to the transition. This will cause the "has params changed
Expand All @@ -310,7 +302,7 @@ angular.module("ct.ui.router.extras.sticky").config(
var params = reloadStateTree.$$state().params;
var ownParams = reloadStateTree.$$state().ownParams;

if (versionHeuristics.hasParamSet) {
if (core.versionHeuristics.hasParamSet) {
var tempParam = new $urlMatcherFactoryProvider.Param('$$uirouterextrasreload');
params.$$uirouterextrasreload = ownParams.$$uirouterextrasreload = tempParam;
restore.restoreFunctions.push(function() {
Expand All @@ -333,7 +325,7 @@ angular.module("ct.ui.router.extras.sticky").config(
// 2) what types of exit transitions will occur for each "exited" path element
// 3) what types of enter transitions will occur for each "entered" path element
// 4) which states will be inactive if the transition succeeds.
stickyTransitions = _StickyState.processTransition(currentTransition);
stickyTransitions = core._StickyState.processTransition(currentTransition);

if (DEBUG) debugTransition($log, currentTransition, stickyTransitions);

Expand All @@ -342,8 +334,8 @@ angular.module("ct.ui.router.extras.sticky").config(
var surrogateFromPath = fromState.path.slice(0, stickyTransitions.keep);

// Clear out and reload inactivePseudoState.locals each time transitionTo is called
angular.forEach(inactivePseudoState.locals, function (local, name) {
if (name.indexOf("@") != -1) delete inactivePseudoState.locals[name];
angular.forEach(core.inactivePseudoState.locals, function (local, name) {
if (name.indexOf("@") != -1) delete core.inactivePseudoState.locals[name];
});

var saveViewsToLocals = function (targetObj) {
Expand All @@ -358,7 +350,7 @@ angular.module("ct.ui.router.extras.sticky").config(
// __inactives pseudostate's .locals. This allows the ui-view directive to access them and
// render the inactive views.
forEach(stickyTransitions.inactives, function(state) {
forEach(state.locals, saveViewsToLocals(inactivePseudoState.locals))
forEach(state.locals, saveViewsToLocals(core.inactivePseudoState.locals))
});

// For each state that will be reactivated during the transition, place its view-locals on a separate
Expand All @@ -373,13 +365,13 @@ angular.module("ct.ui.router.extras.sticky").config(
// - Because the transition is not completed, $state.$current is set to the from state, and
// the ui-view for a reactivated state cannot find its previous locals.
forEach(stickyTransitions.reactivatingStates, function(state) {
forEach(state.locals, saveViewsToLocals(reactivatingLocals));
forEach(state.locals, saveViewsToLocals(core.reactivatingLocals));
});

// When the transition is complete, remove the copies of the view locals from reactivatingLocals.
restore.addRestoreFunction(function clearReactivatingLocals() {
forEach(reactivatingLocals, function (val, viewname) {
delete reactivatingLocals[viewname];
forEach(core.reactivatingLocals, function (val, viewname) {
delete core.reactivatingLocals[viewname];
})
});

Expand Down Expand Up @@ -503,7 +495,7 @@ angular.module("ct.ui.router.extras.sticky").config(
angular.toJson(currentTransition.toParams);

$log.debug(" Current transition: ", transitionMessage);
$log.debug("Before transition, inactives are: : ", map(_StickyState.getInactiveStates(), function (s) {
$log.debug("Before transition, inactives are: : ", map(core._StickyState.getInactiveStates(), function (s) {
return s.self.name;
}));
$log.debug("After transition, inactives will be: ", inactiveLogVar);
Expand All @@ -512,7 +504,7 @@ angular.module("ct.ui.router.extras.sticky").config(
}

function debugViewsAfterSuccess($log, currentState, $state) {
$log.debug("Current state: " + currentState.self.name + ", inactive states: ", map(_StickyState.getInactiveStates(), function (s) {
$log.debug("Current state: " + currentState.self.name + ", inactive states: ", map(core._StickyState.getInactiveStates(), function (s) {
return s.self.name;
}));

Expand Down
Loading