-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathappState.Stack.js
128 lines (99 loc) · 5.08 KB
/
appState.Stack.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/// <reference path="appState.utils.js" />
/// <reference path="appState.StateObject.js" />
(function (appState, undefined) {
appState.Stack = function (enterCB, exitCB) {
///<summary>Constructor for a state/handler stack.</summary>
///<param name="enterCB">A callback called before a new state is entered. Callback receives state and optional data objects.</param>
///<param name="exitCB">A callback called before the active state exits. Callback received the state object being exited.</param>
///<returns type="appState.Stack"/>
//------ Private members
var initCallback = typeof (enterCB) === "function" ? enterCB : undefined;
var exitCallback = typeof (exitCB) === "function" ? exitCB : undefined;
var stateStack = [];
var self = this;
var validateStateObject = function (state) {
///<summary>Ensures that the parameter inherits StateObject or throws an error</summary>
if (!appState.StateObject.prototype.isPrototypeOf(state)) {
throw new Error("appState.Monitor: State does not inherit from appState.StateObject.");
}
}
var peek = function () {
///<summary>Get the top-most(active) state or undefined, if empty.</summary>
///<returns>appState.StateObject</returns>
if (stateStack.length > 0) {
return stateStack[stateStack.length - 1];
}
return undefined;
}
var exitCurrentState = function () {
///<summary>Exits the current active handler, if present.</summary>
var oldHandler = peek();
if (oldHandler) {
if (exitCallback) {
exitCallback(oldHandler);
}
oldHandler.stateExit();
}
}
var enterCurrentState = function (data) {
///<summary>Enters the current active handler, if present</summary>
var currentHandler = peek();
if (currentHandler) {
if (initCallback) {
initCallback(currentHandler, data);
}
currentHandler.stateEnter(currentHandler, data);
}
}
//------ Public members
this.setInitCallback = function (callback) {
///<summary>Set an initializer callback, called before a new state is entered. Receives state being entered and optional data object.</summary>
///<param name="enterCallback">A callback called before a new state is entered. Callback receives state and optional data objects.</param>
initCallback = typeof (callback) === "function" ? callback : undefined;
}
this.currentState = function () {
///<summary>Get the top-most(active) state or undefined, if empty.</summary>
///<returns type="appState.StateObject"/>
return peek();
}
this.pushState = function (state, data) {
///<summary>Push a state into the top of the stack and enter it.</summary>
///<param name="state">A StateObject to be entered.</param>
///<param name="data">An optional data object to be passed to the initCallback and the state's enter callbacks.</param>
validateStateObject(state);
exitCurrentState();
stateStack.push(state);
enterCurrentState(data);
}
this.swapState = function (state, data) {
///<summary>Changes out the current top state with the provided state. The previous state is completely removed from the stack.</summary>
///<param name="state">A StateObject to be entered.</param>
///<param name="data">An optional data object to be passed to the initCallback and the state's enter callbacks.</param>
validateStateObject(state);
exitCurrentState();
stateStack.pop();
stateStack.push(state);
enterCurrentState(data);
}
this.popState = function () {
///<summary>Exits the current top state and enters the next state on the stack, if present.</summary>
exitCurrentState();
stateStack.pop();
enterCurrentState();
}
this.clear = function () {
///<summary>Exits the current top state and clears all remaining states on the stack WITHOUT exiting them.</summary>
exitCurrentState();
stateStack.splice(0, stateStack.length);
}
this.reset = function (state, data) {
///<summary>Exits the current top state and clears all remaining states WITHOUT exiting, then enters the provided state.</summary>
///<param name="state">A StateObject to be entered.</param>
///<param name="data">An optional data object to be passed to the initCallback and the state's enter callbacks.</param>
validateStateObject(state);
self.clear();
stateStack.push(state);
enterCurrentState(data);
}
};
} (window.appState = window.appState || {}));