+ * Query the cached records in this Store using a filtering function. The specified function
+ * will be called with each record in this Store. If the function returns <tt>true</tt> the record is
+ * included in the results.
+ * @param {Function} fn The function to be called. It will be passed the following parameters:<ul>
+ * <li><b>record</b> : Ext.data.Model<p class="sub-desc">The {@link Ext.data.Model record}
+ * to test for filtering. Access field values using {@link Ext.data.Model#get}.</p></li>
+ * <li><b>id</b> : Object<p class="sub-desc">The ID of the Record passed.</p></li>
+ * </ul>
+ * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to this Store.
+ * @return {Ext.util.MixedCollection} Returns an Ext.util.MixedCollection of the matched records
+ **/
+ queryBy: function(fn, scope) {
+ var me = this,
+ data = me.snapshot || me.data;
+ return data.filterBy(fn, scope || me);
+ },
+
+ /**
+ * Loads an array of data straight into the Store.
+ *
+ * Using this method is great if the data is in the correct format already (e.g. it doesn't need to be
+ * processed by a reader). If your data requires processing to decode the data structure, use a
+ * {@link Ext.data.proxy.Memory MemoryProxy} instead.
+ *
+ * @param {Ext.data.Model[]/Object[]} data Array of data to load. Any non-model instances will be cast
+ * into model instances.
+ * @param {Boolean} [append=false] True to add the records to the existing records in the store, false
+ * to remove the old ones first.
+ */
+ loadData: function(data, append) {
+ var model = this.model,
+ length = data.length,
+ newData = [],
+ i,
+ record;
+
+ //make sure each data element is an Ext.data.Model instance
+ for (i = 0; i < length; i++) {
+ record = data[i];
+
+ if (!(record instanceof Ext.data.Model)) {
+ record = Ext.ModelManager.create(record, model);
+ }
+ newData.push(record);
+ }
+
+ this.loadRecords(newData, {addRecords: append});
+ },
+
+
+ /**
+ * Loads data via the bound Proxy's reader
+ *
+ * Use this method if you are attempting to load data and want to utilize the configured data reader.
+ *
+ * @param {Object[]} data The full JSON object you'd like to load into the Data store.
+ * @param {Boolean} [append=false] True to add the records to the existing records in the store, false
+ * to remove the old ones first.
+ */
+ loadRawData : function(data, append) {
+ var me = this,
+ result = me.proxy.reader.read(data),
+ records = result.records;
+
+ if (result.success) {
+ me.loadRecords(records, { addRecords: append });
+ me.fireEvent('load', me, records, true);
+ }
+ },
+
+
+ /**
+ * Loads an array of {@link Ext.data.Model model} instances into the store, fires the datachanged event. This should only usually
+ * be called internally when loading from the {@link Ext.data.proxy.Proxy Proxy}, when adding records manually use {@link #add} instead
+ * @param {Ext.data.Model[]} records The array of records to load
+ * @param {Object} options {addRecords: true} to add these records to the existing records, false to remove the Store's existing records first
+ */
+ loadRecords: function(records, options) {
+ var me = this,
+ i = 0,
+ length = records.length;
+
+ options = options || {};
+
+
+ if (!options.addRecords) {
+ delete me.snapshot;
+ me.clearData();
+ }
+
+ me.data.addAll(records);
+
+ //FIXME: this is not a good solution. Ed Spencer is totally responsible for this and should be forced to fix it immediately.
+ for (; i < length; i++) {
+ if (options.start !== undefined) {
+ records[i].index = options.start + i;
+
+ }
+ records[i].join(me);
+ }
+
+ /*
+ * this rather inelegant suspension and resumption of events is required because both the filter and sort functions
+ * fire an additional datachanged event, which is not wanted. Ideally we would do this a different way. The first
+ * datachanged event is fired by the call to this.add, above.
+ */
+ me.suspendEvents();
+
+ if (me.filterOnLoad && !me.remoteFilter) {
+ me.filter();
+ }
+
+ if (me.sortOnLoad && !me.remoteSort) {
+ me.sort();
+ }
+
+ me.resumeEvents();
+ me.fireEvent('datachanged', me, records);
+ },
+
+ // PAGING METHODS
+ /**
+ * Loads a given 'page' of data by setting the start and limit values appropriately. Internally this just causes a normal
+ * load operation, passing in calculated 'start' and 'limit' params
+ * @param {Number} page The number of the page to load
+ * @param {Object} options See options for {@link #load}