]>
git.proxmox.com Git - extjs.git/blob - extjs/classic/classic/src/state/Stateful.js
2 * @class Ext.state.Stateful
3 * A mixin for being able to save the state of an object to an underlying
4 * {@link Ext.state.Provider}.
6 Ext
.define('Ext.state.Stateful', {
15 * @cfg {Boolean} stateful
16 * A flag which causes the object to attempt to restore the state of
17 * internal properties from a saved state on startup. The object must have
18 * a {@link #stateId} for state to be managed.
20 * Auto-generated ids are not guaranteed to be stable across page loads and
21 * cannot be relied upon to save and restore the same state for a object.
23 * For state saving to work, the state manager's provider must have been
24 * set to an implementation of {@link Ext.state.Provider} which overrides the
25 * {@link Ext.state.Provider#set set} and {@link Ext.state.Provider#get get}
26 * methods to save and recall name/value pairs. A built-in implementation,
27 * {@link Ext.state.CookieProvider} is available.
29 * To set the state provider for the current page:
31 * Ext.state.Manager.setProvider(new Ext.state.CookieProvider({
32 * expires: new Date(new Date().getTime()+(1000*60*60*24*7)), //7 days from now
35 * A stateful object attempts to save state when one of the events
36 * listed in the {@link #stateEvents} configuration fires.
38 * To save state, a stateful object first serializes its state by
39 * calling *{@link #getState}*.
41 * The Component base class implements {@link #getState} to save its width and height within the state
42 * only if they were initially configured, and have changed from the configured value.
44 * The Panel class saves its collapsed state in addition to that.
46 * The Grid class saves its column state and store state (sorters and filters and grouper) in addition to its superclass state.
48 * If there is more application state to be save, the developer must provide an implementation which
49 * first calls the superclass method to inherit the above behaviour, and then injects new properties
50 * into the returned object.
52 * The value yielded by getState is passed to {@link Ext.state.Manager#set}
53 * which uses the configured {@link Ext.state.Provider} to save the object
54 * keyed by the {@link #stateId}.
56 * During construction, a stateful object attempts to *restore* its state by calling
57 * {@link Ext.state.Manager#get} passing the {@link #stateId}
59 * The resulting object is passed to {@link #applyState}*. The default implementation of
60 * {@link #applyState} simply copies properties into the object, but a developer may
61 * override this to support restoration of more complex application state.
63 * You can perform extra processing on state save and restore by attaching
64 * handlers to the {@link #beforestaterestore}, {@link #staterestore},
65 * {@link #beforestatesave} and {@link #statesave} events.
70 * @cfg {String} stateId
71 * The unique id for this object to use for state management purposes.
73 * See {@link #stateful} for an explanation of saving and restoring state.
77 * @cfg {String[]} stateEvents
78 * An array of events that, when fired, should trigger this object to
79 * save its state. Defaults to none. `stateEvents` may be any type
80 * of event supported by this object, including browser or custom events
81 * (e.g., `['click', 'customerchange']`).
83 * See `{@link #stateful}` for an explanation of saving and
84 * restoring object state.
88 * @cfg {Number} saveDelay
89 * A buffer to be applied if many state events are fired within a short period.
94 * @event beforestaterestore
95 * Fires before the state of the object is restored. Return false from an event handler to stop the restore.
96 * @param {Ext.state.Stateful} this
97 * @param {Object} state The hash of state values returned from the StateProvider. If this
98 * event is not vetoed, then the state object is passed to *`applyState`*. By default,
99 * that simply copies property values into this object. The method maybe overriden to
100 * provide custom state restoration.
104 * @event staterestore
105 * Fires after the state of the object is restored.
106 * @param {Ext.state.Stateful} this
107 * @param {Object} state The hash of state values returned from the StateProvider. This is passed
108 * to *`applyState`*. By default, that simply copies property values into this
109 * object. The method maybe overridden to provide custom state restoration.
113 * @event beforestatesave
114 * Fires before the state of the object is saved to the configured state provider. Return false to stop the save.
115 * @param {Ext.state.Stateful} this
116 * @param {Object} state The hash of state values. This is determined by calling
117 * *`getState()`* on the object. This method must be provided by the
118 * developer to return whatever representation of state is required, by default, Ext.state.Stateful
119 * has a null implementation.
124 * Fires after the state of the object is saved to the configured state provider.
125 * @param {Ext.state.Stateful} this
126 * @param {Object} state The hash of state values. This is determined by calling
127 * *`getState()`* on the object. This method must be provided by the
128 * developer to return whatever representation of state is required, by default, Ext.state.Stateful
129 * has a null implementation.
132 constructor: function() {
135 if (!me
.stateEvents
) {
139 if (me
.stateful
!== false) {
140 me
.addStateEvents(me
.stateEvents
);
146 * Add events that will trigger the state to be saved. If the first argument is an
147 * array, each element of that array is the name of a state event. Otherwise, each
148 * argument passed to this method is the name of a state event.
150 * @param {String/String[]} events The event name or an array of event names.
152 addStateEvents: function (events
) {
154 i
, event
, stateEventsByName
,
157 if (me
.stateful
&& me
.getStateId()) {
158 eventArray
= (typeof events
=== 'string') ? arguments
: events
;
160 stateEventsByName
= me
.stateEventsByName
|| (me
.stateEventsByName
= {});
162 for (i
= eventArray
.length
; i
--; ) {
163 event
= eventArray
[i
];
165 if (event
&& !stateEventsByName
[event
]) {
166 stateEventsByName
[event
] = 1;
167 me
.on(event
, me
.onStateChange
, me
);
174 * This method is called when any of the {@link #stateEvents} are fired.
177 onStateChange: function(){
179 delay
= me
.saveDelay
,
188 statics
= Ext
.state
.Stateful
;
189 runner
= statics
.runner
|| (statics
.runner
= new Ext
.util
.TaskRunner());
191 me
.stateTask
= runner
.newTask({
200 me
.stateTask
.start();
207 * Saves the state of the object to the persistence store.
209 saveState: function() {
211 id
= me
.stateful
&& me
.getStateId(),
212 hasListeners
= me
.hasListeners
,
220 state
= me
.getState() || {}; //pass along for custom interactions
223 * Gather state from those plugins that implement a getState method
225 plugins
= me
.getPlugins() || [];
226 for (i
= 0, len
= plugins
.length
; i
< len
; i
++) {
228 if (plugin
&& plugin
.getState
) {
229 pluginState
= plugin
.getState(state
);
230 if (pluginState
&& !state
[plugin
.ptype
]) { //first duplicate plugin wins
231 state
[plugin
.ptype
] = pluginState
;
236 if (!hasListeners
.beforestatesave
|| me
.fireEvent('beforestatesave', me
, state
) !== false) {
237 Ext
.state
.Manager
.set(id
, state
);
238 if (hasListeners
.statesave
) {
239 me
.fireEvent('statesave', me
, state
);
246 * Gets the current state of the object. By default this function returns null,
247 * it should be overridden in subclasses to implement methods for getting the state.
248 * @return {Object} The current state
250 getState: function(){
255 * Applies the state to the object. This should be overridden in subclasses to do
256 * more complex state operations. By default it applies the state properties onto
257 * the current object.
258 * @param {Object} state The state
260 applyState: function(state
) {
262 Ext
.apply(this, state
);
267 * Gets the state id for this object.
268 * @return {String} The 'stateId' or the implicit 'id' specified by component configuration.
271 getStateId: function() {
273 return me
.stateId
|| (me
.autoGenId
? null : me
.id
);
277 * Initializes the state of the object upon construction.
280 initState: function(){
282 id
= me
.stateful
&& me
.getStateId(),
283 hasListeners
= me
.hasListeners
,
292 combinedState
= Ext
.state
.Manager
.get(id
);
294 state
= Ext
.apply({}, combinedState
);
295 if (!hasListeners
.beforestaterestore
|| me
.fireEvent('beforestaterestore', me
, combinedState
) !== false) {
297 //Notify all plugins FIRST (if interested) in new state
298 plugins
= me
.getPlugins() || [];
299 for (i
= 0, len
= plugins
.length
; i
< len
; i
++) {
302 pluginType
= plugin
.ptype
;
303 if (plugin
.applyState
) {
304 plugin
.applyState(state
[pluginType
], combinedState
);
306 delete state
[pluginType
]; //clean to prevent unwanted props on the component in final phase
310 me
.applyState(state
);
311 if (hasListeners
.staterestore
) {
312 me
.fireEvent('staterestore', me
, combinedState
);
320 * Conditionally saves a single property from this object to the given state object.
321 * The idea is to only save state which has changed from the initial state so that
322 * current software settings do not override future software settings. Only those
323 * values that are user-changed state should be saved.
325 * @param {String} propName The name of the property to save.
326 * @param {Object} state The state object in to which to save the property.
327 * @param {String} stateName (optional) The name to use for the property in state.
328 * @return {Boolean} True if the property was saved, false if not.
330 savePropToState: function (propName
, state
, stateName
) {
332 value
= me
[propName
],
333 config
= me
.initialConfig
;
335 if (me
.hasOwnProperty(propName
)) {
336 if (!config
|| config
[propName
] !== value
) {
338 state
[stateName
|| propName
] = value
;
347 * Gathers additional named properties of the instance and adds their current values
348 * to the passed state object.
349 * @param {String/String[]} propNames The name (or array of names) of the property to save.
350 * @param {Object} state The state object in to which to save the property values.
351 * @return {Object} state
353 savePropsToState: function (propNames
, state
) {
357 if (typeof propNames
=== 'string') {
358 me
.savePropToState(propNames
, state
);
360 for (i
= 0, n
= propNames
.length
; i
< n
; ++i
) {
361 me
.savePropToState(propNames
[i
], state
);
369 * Destroys this stateful object.