/* Copyright (c) 2013 [Web App Solution, Inc.](mailto:admin@webappsolution.com) FlowMVC 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 3 of the License, or (at your option) any later version. FlowMVC 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. You should have received a copy of the GNU General Public License along with FlowMVC. If not, see <http://www.gnu.org/licenses/>. */ /** * The abstract store classes provides additional base functionality to update records in the store and * force auto syncs without requiring the use of a proxy. Treats the store more like a collection. * * This file is part of WASI Sencha Extensions. */ Ext.define("FlowMVC.mvc.store.AbstractStore", { extend: "Ext.data.Store", statics: { /** * @property {FlowMVC.logger.Logger} logger The logger for the object. * @static */ logger: FlowMVC.logger.Logger.getLogger("FlowMVC.mvc.store.AbstractStore"), /** * @property {String} ERROR_SET_DATA_PARAM_NOT_VALID An error string indicating that the setData() method's parameter * cannot be anything other than null or an array. * @static */ ERROR_SET_DATA_PARAM_NOT_VALID: "The setData() method's 'data' parameter must be an array or null.", /** * @property {String} ERROR_SET_SELECTED_RECORD_PARAM_NOT_VALID An error string indicating that the setSelectedRecord() * method's parameter cannot be anything other than null or an instance of the expected model for this store. * @static */ ERROR_SET_SELECTED_RECORD_PARAM_NOT_VALID: "The setSelectedRecord() method's 'record' parameter must null or " + "be an instance of the expected model for this store.", /** * @property {String} ERROR_SET_UPDATE_PARAM_NOT_VALID An error string indicating that the update() * method's parameter must be not-null and an instance of the expected model for this store. * @static */ ERROR_SET_UPDATE_PARAM_NOT_VALID: "The update() method's 'record' parameter must be not null and " + "be an instance of the expected model for this store." }, /** * @event selectedRecordChange * Fired when a Model instance has been set as the selected record of Store. You should listen * for this event if you have to update a representation of the selected record in this store in your UI. * @param {Ext.data.Store} this The store. * @param {Ext.data.Model} record The Model instance that is set as the selected record. */ /** * @event updatedRecord * Fired when a Model instance has been updated in the Store. You should listen * for this event if you have to update a representation of the selected record in this store in your UI. * @param {Ext.data.Store} this The store. * @param {Ext.data.Model} record The Model instance that was updated. */ /** * @private {Object/Ext.data.Model} _selectedRecord the currently selected record for the store. */ _selectedRecord: null, /** * Sets the selected record on the store and broadcasts an event with type "selectedRecordChange" with a reference * to the store and the selected record. * * @param {Ext.data.Model} record The record to set as selected on this store. */ setSelectedRecord: function(record, autoAdd) { FlowMVC.mvc.store.AbstractStore.logger.debug("setSelectedRecord"); // the record parameter must either be null an instance of the expected model for this store if ( !this.isModel(record) && (record != null) ) { Ext.Error.raise({ msg: FlowMVC.mvc.store.AbstractStore.ERROR_SET_SELECTED_RECORD_PARAM_NOT_VALID }); } // default autoAdd to true // TODO: create util to default values autoAdd = typeof autoAdd !== "undefined" ? autoAdd : true; // if the record isn't in the store and autoAdd is set to true, then add it if( record && autoAdd && (this.getById(record.id) == null) ) { this.add(record); } this._selectedRecord = record; this.fireEvent("selectedRecordChange", this, record); }, /** * Accessor for this store's selected record. * * @return {Object/Ext.data.Model} The selected record for this store. */ getSelectedRecord: function() { FlowMVC.mvc.store.AbstractStore.logger.debug("getSelectedRecord"); return this._selectedRecord; }, /** * Removes all records from the store and makes sure the selected record is null. */ removeAll: function() { FlowMVC.mvc.store.AbstractStore.logger.debug("removeAll"); this._selectedRecord = null; this.callParent(arguments); }, /** * This method exists to create parity between the ExtJS and Touch SDKs, as ExtJS does not have a setData() method. * * @param {Object[]/Ext.data.Model[]} data * Array of Model instances or data objects to load locally. See "Inline data" above for details. */ setData: function(data) { // the data parameter must either be null or an array if (!Ext.isArray(data) && (data != null)) { Ext.Error.raise({ msg: FlowMVC.mvc.store.AbstractStore.ERROR_SET_DATA_PARAM_NOT_VALID }); } // do some quick sencha framework checking as there's no setData() in ExtJS. if (Ext.getVersion("extjs")) { FlowMVC.mvc.store.AbstractStore.logger.info("setData: using 'store.removeAll() and store.add(data)' because ExtJS 4.1 doesn't support store.setData()."); this.removeAll(); if(data) { this.add(data); } else { this.removeAll(); } } else { FlowMVC.mvc.store.AbstractStore.logger.info("setData"); this.callParent(arguments); } }, /** * Update a model object on the store by replacing it with a new model * * @param {Ext.data.Model} model The model to replace existing model in store. * @param {String} property The property to use as the id to find the model to be replaced. */ update: function(model, property) { property = property ? property : "id"; // the record parameter must be non-null and an instance of the expected model for this store if ( (model == null) || (this.isModel(model) == false) ) { Ext.Error.raise({ msg: FlowMVC.mvc.store.AbstractStore.ERROR_SET_UPDATE_PARAM_NOT_VALID }); } if (Ext.getVersion("extjs")) { var index = this.find(property, model.get(property)); if(index < 0) return; this.insert(index, model); this.removeAt(index+1); FlowMVC.mvc.store.AbstractStore.logger.debug("update: updating ExtJS model with " + property); this.fireEvent("updatedRecord", this, model); return model; } else { var value = model.data[property]; var record = this.findRecord(property, value); if(record) { // record.setData(model); record = model; // force the store to update correctly and broadcast refresh events // so views using this store update correctly record.dirty = true; this.sync(); FlowMVC.mvc.store.AbstractStore.logger.debug("update: updating Touch model with " + property); this.fireEvent("updatedRecord", this, record); return model; } } return null; }, /** * Determines if the model parameter is the expected model type for this store. * * @param {Object/Ext.data.Model} model The object being tested to determine if it's the expected model for * this store. * @return {Boolean} A flag indicating if the parameter is the expected model for this store. */ isModel: function(record) { // ExtJS and Touch get to the underlying model differently var modelClass = (Ext.getVersion("extjs")) ? this.model : this._model; var bool = (record instanceof modelClass); return (record instanceof modelClass); } });