1 <!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-data.proxy.WebStorage-method-constructor'><span id='Ext-data.proxy.WebStorage'>/**
2 </span></span> * @author Ed Spencer
3 * @class Ext.data.proxy.WebStorage
4 * @extends Ext.data.proxy.Client
6 * <p>WebStorageProxy is simply a superclass for the {@link Ext.data.proxy.LocalStorage localStorage} and
7 * {@link Ext.data.proxy.SessionStorage sessionStorage} proxies. It uses the new HTML5 key/value client-side storage
8 * objects to save {@link Ext.data.Model model instances} for offline use.</p>
11 * Creates the proxy, throws an error if local storage is not supported in the current browser
12 * @param {Object} config Optional config object
14 Ext.define('Ext.data.proxy.WebStorage', {
15 extend: 'Ext.data.proxy.Client',
16 alternateClassName: 'Ext.data.WebStorageProxy',
18 <span id='Ext-data.proxy.WebStorage-cfg-id'> /**
19 </span> * @cfg {String} id The unique ID used as the key in which all record data are stored in the local storage object
23 <span id='Ext-data.proxy.WebStorage-method-constructor'> /**
26 constructor: function(config) {
27 this.callParent(arguments);
29 <span id='Ext-data.proxy.WebStorage-property-cache'> /**
30 </span> * Cached map of records already retrieved by this Proxy - ensures that the same instance is always retrieved
37 if (this.getStorageObject() === undefined) {
38 Ext.Error.raise("Local Storage is not supported in this browser, please use another type of data proxy");
42 //if an id is not given, try to use the store's id instead
43 this.id = this.id || (this.store ? this.store.storeId : undefined);
46 if (this.id === undefined) {
47 Ext.Error.raise("No unique id was provided to the local storage proxy. See Ext.data.proxy.LocalStorage documentation for details");
55 create: function(operation, callback, scope) {
56 var records = operation.records,
57 length = records.length,
61 operation.setStarted();
63 for (i = 0; i < length; i++) {
67 record.phantom = false;
68 id = this.getNextId();
73 this.setRecord(record, id);
79 operation.setCompleted();
80 operation.setSuccessful();
82 if (typeof callback == 'function') {
83 callback.call(scope || this, operation);
88 read: function(operation, callback, scope) {
89 //TODO: respect sorters, filters, start and limit options on the Operation
94 i, recordData, record;
96 //read a single record
98 record = this.getRecord(operation.id);
101 records.push(record);
102 operation.setSuccessful();
105 for (i = 0; i < length; i++) {
106 records.push(this.getRecord(ids[i]));
108 operation.setSuccessful();
111 operation.setCompleted();
113 operation.resultSet = Ext.create('Ext.data.ResultSet', {
115 total : records.length,
119 if (typeof callback == 'function') {
120 callback.call(scope || this, operation);
125 update: function(operation, callback, scope) {
126 var records = operation.records,
127 length = records.length,
131 operation.setStarted();
133 for (i = 0; i < length; i++) {
135 this.setRecord(record);
137 //we need to update the set of ids here because it's possible that a non-phantom record was added
138 //to this proxy - in which case the record's id would never have been added via the normal 'create' call
140 if (id !== undefined && Ext.Array.indexOf(ids, id) == -1) {
146 operation.setCompleted();
147 operation.setSuccessful();
149 if (typeof callback == 'function') {
150 callback.call(scope || this, operation);
155 destroy: function(operation, callback, scope) {
156 var records = operation.records,
157 length = records.length,
160 //newIds is a copy of ids, from which we remove the destroyed records
161 newIds = [].concat(ids),
164 for (i = 0; i < length; i++) {
165 Ext.Array.remove(newIds, records[i].getId());
166 this.removeRecord(records[i], false);
171 operation.setCompleted();
172 operation.setSuccessful();
174 if (typeof callback == 'function') {
175 callback.call(scope || this, operation);
179 <span id='Ext-data.proxy.WebStorage-method-getRecord'> /**
181 * Fetches a model instance from the Proxy by ID. Runs each field's decode function (if present) to decode the data
182 * @param {String} id The record's unique ID
183 * @return {Ext.data.Model} The model instance
185 getRecord: function(id) {
186 if (this.cache[id] === undefined) {
187 var rawData = Ext.decode(this.getStorageObject().getItem(this.getRecordKey(id))),
190 fields = Model.prototype.fields.items,
191 length = fields.length,
192 i, field, name, record;
194 for (i = 0; i < length; i++) {
198 if (typeof field.decode == 'function') {
199 data[name] = field.decode(rawData[name]);
201 data[name] = rawData[name];
205 record = new Model(data, id);
206 record.phantom = false;
208 this.cache[id] = record;
211 return this.cache[id];
214 <span id='Ext-data.proxy.WebStorage-method-setRecord'> /**
215 </span> * Saves the given record in the Proxy. Runs each field's encode function (if present) to encode the data
216 * @param {Ext.data.Model} record The model instance
217 * @param {String} id The id to save the record under (defaults to the value of the record's getId() function)
219 setRecord: function(record, id) {
227 rawData = record.data,
230 fields = model.prototype.fields.items,
231 length = fields.length,
233 field, name, obj, key;
235 for (; i < length; i++) {
239 if (typeof field.encode == 'function') {
240 data[name] = field.encode(rawData[name], record);
242 data[name] = rawData[name];
246 obj = me.getStorageObject();
247 key = me.getRecordKey(id);
249 //keep the cache up to date
250 me.cache[id] = record;
252 //iPad bug requires that we remove the item before setting it
254 obj.setItem(key, Ext.encode(data));
257 <span id='Ext-data.proxy.WebStorage-method-removeRecord'> /**
259 * Physically removes a given record from the local storage. Used internally by {@link #destroy}, which you should
260 * use instead because it updates the list of currently-stored record ids
261 * @param {String|Number|Ext.data.Model} id The id of the record to remove, or an Ext.data.Model instance
263 removeRecord: function(id, updateIds) {
271 if (updateIds !== false) {
273 Ext.Array.remove(ids, id);
277 me.getStorageObject().removeItem(me.getRecordKey(id));
280 <span id='Ext-data.proxy.WebStorage-method-getRecordKey'> /**
282 * Given the id of a record, returns a unique string based on that id and the id of this proxy. This is used when
283 * storing data in the local storage object and should prevent naming collisions.
284 * @param {String|Number|Ext.data.Model} id The record id, or a Model instance
285 * @return {String} The unique key for this record
287 getRecordKey: function(id) {
292 return Ext.String.format("{0}-{1}", this.id, id);
295 <span id='Ext-data.proxy.WebStorage-method-getRecordCounterKey'> /**
297 * Returns the unique key used to store the current record counter for this proxy. This is used internally when
298 * realizing models (creating them when they used to be phantoms), in order to give each model instance a unique id.
299 * @return {String} The counter key
301 getRecordCounterKey: function() {
302 return Ext.String.format("{0}-counter", this.id);
305 <span id='Ext-data.proxy.WebStorage-method-getIds'> /**
307 * Returns the array of record IDs stored in this Proxy
308 * @return {Array} The record IDs. Each is cast as a Number
311 var ids = (this.getStorageObject().getItem(this.id) || "").split(","),
315 if (length == 1 && ids[0] === "") {
318 for (i = 0; i < length; i++) {
319 ids[i] = parseInt(ids[i], 10);
326 <span id='Ext-data.proxy.WebStorage-method-setIds'> /**
328 * Saves the array of ids representing the set of all records in the Proxy
329 * @param {Array} ids The ids to set
331 setIds: function(ids) {
332 var obj = this.getStorageObject(),
333 str = ids.join(",");
335 obj.removeItem(this.id);
337 if (!Ext.isEmpty(str)) {
338 obj.setItem(this.id, str);
342 <span id='Ext-data.proxy.WebStorage-method-getNextId'> /**
344 * Returns the next numerical ID that can be used when realizing a model instance (see getRecordCounterKey). Increments
346 * @return {Number} The id
348 getNextId: function() {
349 var obj = this.getStorageObject(),
350 key = this.getRecordCounterKey(),
351 last = obj.getItem(key),
356 last = ids[ids.length - 1] || 0;
359 id = parseInt(last, 10) + 1;
360 obj.setItem(key, id);
365 <span id='Ext-data.proxy.WebStorage-method-initialize'> /**
367 * Sets up the Proxy by claiming the key in the storage object that corresponds to the unique id of this Proxy. Called
368 * automatically by the constructor, this should not need to be called again unless {@link #clear} has been called.
370 initialize: function() {
371 var storageObject = this.getStorageObject();
372 storageObject.setItem(this.id, storageObject.getItem(this.id) || "");
375 <span id='Ext-data.proxy.WebStorage-method-clear'> /**
376 </span> * Destroys all records stored in the proxy and removes all keys and values used to support the proxy from the storage object
379 var obj = this.getStorageObject(),
384 //remove all the records
385 for (i = 0; i < len; i++) {
386 this.removeRecord(ids[i]);
389 //remove the supporting objects
390 obj.removeItem(this.getRecordCounterKey());
391 obj.removeItem(this.id);
394 <span id='Ext-data.proxy.WebStorage-method-getStorageObject'> /**
396 * Abstract function which should return the storage object that data will be saved to. This must be implemented
398 * @return {Object} The storage object
400 getStorageObject: function() {
402 Ext.Error.raise("The getStorageObject function has not been defined in your Ext.data.proxy.WebStorage subclass");
405 });</pre></pre></body></html>