fb8828881abde0e190561dfcd083e104f3cf7fe4
[Packages/TYPO3.CMS.git] / t3lib / js / extjs / ExtDirect.StateProvider.js
1 /***************************************************************
2 * Copyright notice
3 *
4 * (c) 2010-2011 Steffen Kamper <steffen@typo3.org>
5 * All rights reserved
6 *
7 * This script is part of the TYPO3 project. The TYPO3 project is
8 * free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * The GNU General Public License can be found at
14 * http://www.gnu.org/copyleft/gpl.html.
15 * A copy is found in the textfile GPL.txt and important notices to the license
16 * from the author is found in LICENSE.txt distributed with these scripts.
17 *
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26
27 Ext.ns('TYPO3.state');
28
29 /**
30 * Creates new ExtDirectProvider
31 * @constructor
32 * @param {Object} config Configuration object
33 * @author Jozef Sakalos
34 * @author Steffen Kamper
35 */
36
37 TYPO3.state.ExtDirectProvider = function(config) {
38
39 this.addEvents(
40 /**
41 * @event readsuccess
42 * Fires after state has been successfully received from server and restored
43 * @param {HttpProvider} this
44 */
45 'readsuccess',
46 /**
47 * @event readfailure
48 * Fires in the case of an error when attempting to read state from server
49 * @param {HttpProvider} this
50 */
51 'readfailure',
52 /**
53 * @event savesuccess
54 * Fires after the state has been successfully saved to server
55 * @param {HttpProvider} this
56 */
57 'savesuccess',
58 /**
59 * @event savefailure
60 * Fires in the case of an error when attempting to save state to the server
61 * @param {HttpProvider} this
62 */
63 'savefailure'
64 );
65
66 // call parent
67 TYPO3.state.ExtDirectProvider.superclass.constructor.call(this);
68
69 Ext.apply(this, config, {
70 // defaults
71 delay: 750, // buffer changes for 750 ms
72 dirty: false,
73 started: false,
74 autoStart: true,
75 autoRead: true,
76 key: 'States.General',
77 logFailure: false,
78 logSuccess: false,
79 queue: [],
80 saveBaseParams: {},
81 readBaseParams: {},
82 paramNames:{
83 key: 'key',
84 name: 'name',
85 value: 'value',
86 data: 'data'
87 }
88 });
89
90 if (this.autoRead) {
91 this.readState();
92 }
93
94 this.dt = new Ext.util.DelayedTask(this.submitState, this);
95 if (this.autoStart) {
96 this.start();
97 }
98 };
99
100
101 Ext.extend(TYPO3.state.ExtDirectProvider, Ext.state.Provider, {
102
103 // localizable texts
104 saveSuccessText: 'Save Success',
105 saveFailureText: 'Save Failure',
106 readSuccessText: 'Read Success',
107 readFailureText: 'Read Failure',
108 dataErrorText: 'Data Error',
109
110
111
112 /**
113 * Initializes state from the passed state object or array.
114 * Use this with loading page using initial state in TYPO3.settings
115 *
116 * @param {Array/Object} state State to initialize state manager with
117 */
118 initState: function(state) {
119 if (Ext.isArray(state)) {
120 Ext.each(state, function(item) {
121 this.state[item.name] = item[this.paramNames.value];
122 }, this);
123 } else if (Ext.isObject(state)) {
124 Ext.iterate(state, function(key, value){
125 this.state[key] = value;
126 }, this);
127 } else {
128 this.state = {};
129 }
130 },
131
132 /**
133 * Sets the passed state variable name to the passed value and queues the change
134 * @param {String} name Name of the state variable
135 * @param {Mixed} value Value of the state variable
136 */
137 set: function(name, value) {
138 if (!name) {
139 return;
140 }
141 this.queueChange(name, value);
142 },
143
144
145 /**
146 * Starts submitting state changes to server
147 */
148 start: function() {
149 this.dt.delay(this.delay);
150 this.started = true;
151 },
152
153
154 /**
155 * Stops submitting state changes
156 */
157 stop: function() {
158 this.dt.cancel();
159 this.started = false;
160 },
161
162
163 /**
164 * private, queues the state change if state has changed
165 */
166 queueChange: function(name, value) {
167 var o = {};
168 var i;
169 var found = false;
170
171
172 var lastValue = this.state[name];
173 for (i = 0; i < this.queue.length; i++) {
174 if (this.queue[i].name === name) {
175 lastValue = this.queue[i].value;
176 }
177 }
178 var changed = undefined === lastValue || lastValue !== value;
179
180 if (changed) {
181 o[this.paramNames.name] = name;
182 o[this.paramNames.value] = value;
183 for (i = 0; i < this.queue.length; i++) {
184 if (this.queue[i].name === o.name) {
185 this.queue[i] = o;
186 found = true;
187 }
188 }
189 if (false === found) {
190 this.queue.push(o);
191 }
192 this.dirty = true;
193 }
194 if (this.started) {
195 this.start();
196 }
197 return changed;
198 },
199
200
201 /**
202 * private, submits state to server by asynchronous Ajax request
203 */
204 submitState: function() {
205 if (!this.dirty) {
206 this.dt.delay(this.delay);
207 return;
208 }
209 this.dt.cancel();
210
211 var o = {
212 scope: this,
213 success: this.onSaveSuccess,
214 failure: this.onSaveFailure,
215 queue: this.queue, //this.clone(this.queue),
216 params: {}
217 };
218
219 var params = Ext.apply({}, this.saveBaseParams);
220 params[this.paramNames.key] = this.key;
221 params[this.paramNames.data] = Ext.encode(o.queue);
222
223 Ext.apply(o.params, params);
224
225 // be optimistic
226 this.dirty = false;
227
228 TYPO3.ExtDirectStateProvider.ExtDirect.setState(o, function(response, options) {
229 if (response.success) {
230 this.onSaveSuccess(response, options);
231 } else {
232 this.onSaveFailure(response, options);
233 }
234 }, this);
235 },
236
237
238 /**
239 * Clears the state variable
240 * @param {String} name Name of the variable to clear
241 */
242 clear: function(name) {
243 this.set(name, undefined);
244 },
245
246
247 /**
248 * private, save success callback
249 */
250 onSaveSuccess: function(response, options) {
251 var o = response;
252 if (!o.success) {
253 if (this.logFailure) {
254 this.log(this.saveFailureText, o, response);
255 }
256 this.dirty = true;
257 } else {
258 Ext.each(response.params.queue, function(item) {
259 if (!item) {
260 return;
261 }
262 var name = item[this.paramNames.name];
263 var value = item[this.paramNames.value];
264
265 if (value === undefined || value === null) {
266 TYPO3.state.ExtDirectProvider.superclass.clear.call(this, name);
267 } else {
268 // parent sets value and fires event
269 TYPO3.state.ExtDirectProvider.superclass.set.call(this, name, value);
270 }
271 }, this);
272 if (!this.dirty) {
273 this.queue = [];
274 }else {
275 var i, j, found;
276 for (i = 0; i < response.params.queue.length; i++) {
277 found = false;
278 for (j = 0; j < this.queue.length; j++) {
279 if (response.params.queue[i].name === this.queue[j].name) {
280 found = true;
281 break;
282 }
283 }
284 if (found && response.params.queue[i].value === this.queue[j].value) {
285 this.queue.remove(this.queue[j]);
286 }
287 }
288 }
289 if (this.logSuccess) {
290 this.log(this.saveSuccessText, o, response);
291 }
292 this.fireEvent('savesuccess', this);
293 }
294 },
295
296
297 /**
298 * private, save failure callback
299 */
300 onSaveFailure: function(response, options) {
301 if (true === this.logFailure) {
302 this.log(this.saveFailureText, response);
303 }
304 this.dirty = true;
305 this.fireEvent('savefailure', this);
306 },
307
308
309 /**
310 * private, read state callback
311 */
312 onReadFailure: function(response, options) {
313 if (this.logFailure) {
314 this.log(this.readFailureText, response);
315 }
316 this.fireEvent('readfailure', this);
317
318 },
319
320
321 /**
322 * private, read success callback
323 */
324 onReadSuccess: function(response, options) {
325 var o = response, data;
326 if (!o.success) {
327 if (this.logFailure) {
328 this.log(this.readFailureText, o, response);
329 }
330 } else {
331 data = o[this.paramNames.data];
332 Ext.iterate(data, function(key, value) {
333 this.state[key] = value;
334 }, this);
335 this.queue = [];
336 this.dirty = false;
337 if (this.logSuccess) {
338 this.log(this.readSuccessText, data, response);
339 }
340 this.fireEvent('readsuccess', this);
341 }
342 },
343
344
345 /**
346 * Reads saved state from server by sending asynchronous Ajax request and processing the response
347 */
348 readState: function() {
349 var o = {
350 scope: this,
351 params:{}
352 };
353
354 var params = Ext.apply({}, this.readBaseParams);
355 params[this.paramNames.key] = this.key;
356
357 Ext.apply(o.params, params);
358 TYPO3.ExtDirectStateProvider.ExtDirect.getState(o, function(response, options) {
359 if (response.success) {
360 this.onReadSuccess(response, options);
361 } else {
362 this.onReadFailure(response, options);
363 }
364 }, this);
365 },
366
367
368 /**
369 * private, logs errors or successes
370 */
371 log: function() {
372 if (console) {
373 console.log.apply(console, arguments);
374 }
375 },
376
377 logState: function() {
378 if (console) {
379 console.log(this.state);
380 }
381 }
382
383 });