Project

General

Profile

Bug #36238 » ExtDirect.StateProvider.js

Alexander Wende, 2012-04-18 14:56

 
/***************************************************************
* Copyright notice
*
* (c) 2010-2011 Steffen Kamper <steffen@typo3.org>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the textfile GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/

Ext.ns('TYPO3.state');

/**
* Creates new ExtDirectProvider
* @constructor
* @param {Object} config Configuration object
* @author Jozef Sakalos
* @author Steffen Kamper
*/

TYPO3.state.ExtDirectProvider = function(config) {

this.addEvents(
/**
* @event readsuccess
* Fires after state has been successfully received from server and restored
* @param {HttpProvider} this
*/
'readsuccess',
/**
* @event readfailure
* Fires in the case of an error when attempting to read state from server
* @param {HttpProvider} this
*/
'readfailure',
/**
* @event savesuccess
* Fires after the state has been successfully saved to server
* @param {HttpProvider} this
*/
'savesuccess',
/**
* @event savefailure
* Fires in the case of an error when attempting to save state to the server
* @param {HttpProvider} this
*/
'savefailure'
);

// call parent
TYPO3.state.ExtDirectProvider.superclass.constructor.call(this);

Ext.apply(this, config, {
// defaults
delay: 750, // buffer changes for 750 ms
dirty: false,
started: false,
autoStart: true,
autoRead: true,
key: 'States.General',
logFailure: false,
logSuccess: false,
queue: [],
saveBaseParams: {},
readBaseParams: {},
paramNames:{
key: 'key',
name: 'name',
value: 'value',
data: 'data'
}
});

if (this.autoRead) {
this.readState();
}

this.dt = new Ext.util.DelayedTask(this.submitState, this);
if (this.autoStart) {
this.start();
}
};


Ext.extend(TYPO3.state.ExtDirectProvider, Ext.state.Provider, {

// localizable texts
saveSuccessText: 'Save Success',
saveFailureText: 'Save Failure',
readSuccessText: 'Read Success',
readFailureText: 'Read Failure',
dataErrorText: 'Data Error',



/**
* Initializes state from the passed state object or array.
* Use this with loading page using initial state in TYPO3.settings
*
* @param {Array/Object} state State to initialize state manager with
*/
initState: function(state) {
if (Ext.isArray(state)) {
Ext.each(state, function(item) {
this.state[item.name] = this.decodeValue(item[this.paramNames.value]);
}, this);
} else if (Ext.isObject(state)) {
Ext.iterate(state, function(key, value){
this.state[key] = this.decodeValue(value);
}, this);
} else {
this.state = {};
}
},

/**
* Sets the passed state variable name to the passed value and queues the change
* @param {String} name Name of the state variable
* @param {Mixed} value Value of the state variable
*/
set: function(name, value) {
if (!name) {
return;
}
this.queueChange(name, value);
},


/**
* Starts submitting state changes to server
*/
start: function() {
this.dt.delay(this.delay);
this.started = true;
},


/**
* Stops submitting state changes
*/
stop: function() {
this.dt.cancel();
this.started = false;
},


/**
* private, queues the state change if state has changed
*/
queueChange: function(name, value) {
var o = {};
var i;
var found = false;


var lastValue = this.state[name];
for (i = 0; i < this.queue.length; i++) {
if (this.queue[i].name === name) {
lastValue = this.decodeValue(this.queue[i].value);
}
}
var changed = undefined === lastValue || lastValue !== value;

if (changed) {
o[this.paramNames.name] = name;
o[this.paramNames.value] = this.encodeValue(value);
for (i = 0; i < this.queue.length; i++) {
if (this.queue[i].name === o.name) {
this.queue[i] = o;
found = true;
}
}
if (false === found) {
this.queue.push(o);
}
this.dirty = true;
}
if (this.started) {
this.start();
}
return changed;
},


/**
* private, submits state to server by asynchronous Ajax request
*/
submitState: function() {
if (!this.dirty) {
this.dt.delay(this.delay);
return;
}
this.dt.cancel();

var o = {
scope: this,
success: this.onSaveSuccess,
failure: this.onSaveFailure,
queue: this.queue, //this.clone(this.queue),
params: {}
};

var params = Ext.apply({}, this.saveBaseParams);
params[this.paramNames.key] = this.key;
params[this.paramNames.data] = Ext.encode(o.queue);

Ext.apply(o.params, params);

// be optimistic
this.dirty = false;

TYPO3.ExtDirectStateProvider.ExtDirect.setState(o, function(response, options) {
if (response.success) {
this.onSaveSuccess(response, options);
} else {
this.onSaveFailure(response, options);
}
}, this);
},


/**
* Clears the state variable
* @param {String} name Name of the variable to clear
*/
clear: function(name) {
this.set(name, undefined);
},


/**
* private, save success callback
*/
onSaveSuccess: function(response, options) {
var o = response;
if (!o.success) {
if (this.logFailure) {
this.log(this.saveFailureText, o, response);
}
this.dirty = true;
} else {
Ext.each(response.params.queue, function(item) {
if (!item) {
return;
}
var name = item[this.paramNames.name];
var value = this.decodeValue(item[this.paramNames.value]);

if (value === undefined || value === null) {
TYPO3.state.ExtDirectProvider.superclass.clear.call(this, name);
} else {
// parent sets value and fires event
TYPO3.state.ExtDirectProvider.superclass.set.call(this, name, value);
}
}, this);
if (!this.dirty) {
this.queue = [];
}else {
var i, j, found;
for (i = 0; i < response.params.queue.length; i++) {
found = false;
for (j = 0; j < this.queue.length; j++) {
if (response.params.queue[i].name === this.queue[j].name) {
found = true;
break;
}
}
if (found && this.encodeValue(response.params.queue[i].value) === this.encodeValue(this.queue[j].value)) {
this.queue.remove(this.queue[j]);
}
}
}
if (this.logSuccess) {
this.log(this.saveSuccessText, o, response);
}
this.fireEvent('savesuccess', this);
}
},


/**
* private, save failure callback
*/
onSaveFailure: function(response, options) {
if (true === this.logFailure) {
this.log(this.saveFailureText, response);
}
this.dirty = true;
this.fireEvent('savefailure', this);
},


/**
* private, read state callback
*/
onReadFailure: function(response, options) {
if (this.logFailure) {
this.log(this.readFailureText, response);
}
this.fireEvent('readfailure', this);

},


/**
* private, read success callback
*/
onReadSuccess: function(response, options) {
var o = response, data;
if (!o.success) {
if (this.logFailure) {
this.log(this.readFailureText, o, response);
}
} else {
data = o[this.paramNames.data];
Ext.iterate(data, function(key, value) {
this.state[key] = this.decodeValue(value);
}, this);
this.queue = [];
this.dirty = false;
if (this.logSuccess) {
this.log(this.readSuccessText, data, response);
}
this.fireEvent('readsuccess', this);
}
},


/**
* Reads saved state from server by sending asynchronous Ajax request and processing the response
*/
readState: function() {
var o = {
scope: this,
params:{}
};

var params = Ext.apply({}, this.readBaseParams);
params[this.paramNames.key] = this.key;

Ext.apply(o.params, params);
TYPO3.ExtDirectStateProvider.ExtDirect.getState(o, function(response, options) {
if (response.success) {
this.onReadSuccess(response, options);
} else {
this.onReadFailure(response, options);
}
}, this);
},


/**
* private, logs errors or successes
*/
log: function() {
if (console) {
console.log.apply(console, arguments);
}
},

logState: function() {
if (console) {
console.log(this.state);
}
}

});
(3-3/4)