comparison geotemco/lib/simile/ajax/scripts/history.js @ 0:b12c99b7c3f0

commit for previous development
author Zoe Hong <zhong@mpiwg-berlin.mpg.de>
date Mon, 19 Jan 2015 17:13:49 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:b12c99b7c3f0
1 /*======================================================================
2 * History
3 *
4 * This is a singleton that keeps track of undoable user actions and
5 * performs undos and redos in response to the browser's Back and
6 * Forward buttons.
7 *
8 * Call addAction(action) to register an undoable user action. action
9 * must have 4 fields:
10 *
11 * perform: an argument-less function that carries out the action
12 * undo: an argument-less function that undos the action
13 * label: a short, user-friendly string describing the action
14 * uiLayer: the UI layer on which the action takes place
15 *
16 * By default, the history keeps track of upto 10 actions. You can
17 * configure this behavior by setting
18 * SimileAjax.History.maxHistoryLength
19 * to a different number.
20 *
21 * An iframe is inserted into the document's body element to track
22 * onload events.
23 *======================================================================
24 */
25
26 SimileAjax.History = {
27 maxHistoryLength: 10,
28 historyFile: "__history__.html",
29 enabled: true,
30
31 _initialized: false,
32 _listeners: new SimileAjax.ListenerQueue(),
33
34 _actions: [],
35 _baseIndex: 0,
36 _currentIndex: 0,
37
38 _plainDocumentTitle: document.title
39 };
40
41 SimileAjax.History.formatHistoryEntryTitle = function(actionLabel) {
42 return SimileAjax.History._plainDocumentTitle + " {" + actionLabel + "}";
43 };
44
45 SimileAjax.History.initialize = function() {
46 if (SimileAjax.History._initialized) {
47 return;
48 }
49
50 if (SimileAjax.History.enabled) {
51 var iframe = document.createElement("iframe");
52 iframe.id = "simile-ajax-history";
53 iframe.style.position = "absolute";
54 iframe.style.width = "10px";
55 iframe.style.height = "10px";
56 iframe.style.top = "0px";
57 iframe.style.left = "0px";
58 iframe.style.visibility = "hidden";
59 iframe.src = SimileAjax.History.historyFile + "?0";
60
61 document.body.appendChild(iframe);
62 SimileAjax.DOM.registerEvent(iframe, "load", SimileAjax.History._handleIFrameOnLoad);
63
64 SimileAjax.History._iframe = iframe;
65 }
66 SimileAjax.History._initialized = true;
67 };
68
69 SimileAjax.History.addListener = function(listener) {
70 SimileAjax.History.initialize();
71
72 SimileAjax.History._listeners.add(listener);
73 };
74
75 SimileAjax.History.removeListener = function(listener) {
76 SimileAjax.History.initialize();
77
78 SimileAjax.History._listeners.remove(listener);
79 };
80
81 SimileAjax.History.addAction = function(action) {
82 SimileAjax.History.initialize();
83
84 SimileAjax.History._listeners.fire("onBeforePerform", [ action ]);
85 window.setTimeout(function() {
86 try {
87 action.perform();
88 SimileAjax.History._listeners.fire("onAfterPerform", [ action ]);
89
90 if (SimileAjax.History.enabled) {
91 SimileAjax.History._actions = SimileAjax.History._actions.slice(
92 0, SimileAjax.History._currentIndex - SimileAjax.History._baseIndex);
93
94 SimileAjax.History._actions.push(action);
95 SimileAjax.History._currentIndex++;
96
97 var diff = SimileAjax.History._actions.length - SimileAjax.History.maxHistoryLength;
98 if (diff > 0) {
99 SimileAjax.History._actions = SimileAjax.History._actions.slice(diff);
100 SimileAjax.History._baseIndex += diff;
101 }
102
103 try {
104 SimileAjax.History._iframe.contentWindow.location.search =
105 "?" + SimileAjax.History._currentIndex;
106 } catch (e) {
107 /*
108 * We can't modify location.search most probably because it's a file:// url.
109 * We'll just going to modify the document's title.
110 */
111 var title = SimileAjax.History.formatHistoryEntryTitle(action.label);
112 document.title = title;
113 }
114 }
115 } catch (e) {
116 SimileAjax.Debug.exception(e, "Error adding action {" + action.label + "} to history");
117 }
118 }, 0);
119 };
120
121 SimileAjax.History.addLengthyAction = function(perform, undo, label) {
122 SimileAjax.History.addAction({
123 perform: perform,
124 undo: undo,
125 label: label,
126 uiLayer: SimileAjax.WindowManager.getBaseLayer(),
127 lengthy: true
128 });
129 };
130
131 SimileAjax.History._handleIFrameOnLoad = function() {
132 /*
133 * This function is invoked when the user herself
134 * navigates backward or forward. We need to adjust
135 * the application's state accordingly.
136 */
137
138 try {
139 var q = SimileAjax.History._iframe.contentWindow.location.search;
140 var c = (q.length == 0) ? 0 : Math.max(0, parseInt(q.substr(1)));
141
142 var finishUp = function() {
143 var diff = c - SimileAjax.History._currentIndex;
144 SimileAjax.History._currentIndex += diff;
145 SimileAjax.History._baseIndex += diff;
146
147 SimileAjax.History._iframe.contentWindow.location.search = "?" + c;
148 };
149
150 if (c < SimileAjax.History._currentIndex) { // need to undo
151 SimileAjax.History._listeners.fire("onBeforeUndoSeveral", []);
152 window.setTimeout(function() {
153 while (SimileAjax.History._currentIndex > c &&
154 SimileAjax.History._currentIndex > SimileAjax.History._baseIndex) {
155
156 SimileAjax.History._currentIndex--;
157
158 var action = SimileAjax.History._actions[SimileAjax.History._currentIndex - SimileAjax.History._baseIndex];
159
160 try {
161 action.undo();
162 } catch (e) {
163 SimileAjax.Debug.exception(e, "History: Failed to undo action {" + action.label + "}");
164 }
165 }
166
167 SimileAjax.History._listeners.fire("onAfterUndoSeveral", []);
168 finishUp();
169 }, 0);
170 } else if (c > SimileAjax.History._currentIndex) { // need to redo
171 SimileAjax.History._listeners.fire("onBeforeRedoSeveral", []);
172 window.setTimeout(function() {
173 while (SimileAjax.History._currentIndex < c &&
174 SimileAjax.History._currentIndex - SimileAjax.History._baseIndex < SimileAjax.History._actions.length) {
175
176 var action = SimileAjax.History._actions[SimileAjax.History._currentIndex - SimileAjax.History._baseIndex];
177
178 try {
179 action.perform();
180 } catch (e) {
181 SimileAjax.Debug.exception(e, "History: Failed to redo action {" + action.label + "}");
182 }
183
184 SimileAjax.History._currentIndex++;
185 }
186
187 SimileAjax.History._listeners.fire("onAfterRedoSeveral", []);
188 finishUp();
189 }, 0);
190 } else {
191 var index = SimileAjax.History._currentIndex - SimileAjax.History._baseIndex - 1;
192 var title = (index >= 0 && index < SimileAjax.History._actions.length) ?
193 SimileAjax.History.formatHistoryEntryTitle(SimileAjax.History._actions[index].label) :
194 SimileAjax.History._plainDocumentTitle;
195
196 SimileAjax.History._iframe.contentWindow.document.title = title;
197 document.title = title;
198 }
199 } catch (e) {
200 // silent
201 }
202 };
203
204 SimileAjax.History.getNextUndoAction = function() {
205 try {
206 var index = SimileAjax.History._currentIndex - SimileAjax.History._baseIndex - 1;
207 return SimileAjax.History._actions[index];
208 } catch (e) {
209 return null;
210 }
211 };
212
213 SimileAjax.History.getNextRedoAction = function() {
214 try {
215 var index = SimileAjax.History._currentIndex - SimileAjax.History._baseIndex;
216 return SimileAjax.History._actions[index];
217 } catch (e) {
218 return null;
219 }
220 };