111 lines
3.7 KiB
JavaScript
111 lines
3.7 KiB
JavaScript
|
define("dojo/store/util/SimpleQueryEngine", ["../../_base/array" /*=====, "../api/Store" =====*/], function(arrayUtil /*=====, Store =====*/){
|
||
|
|
||
|
// module:
|
||
|
// dojo/store/util/SimpleQueryEngine
|
||
|
|
||
|
return function(query, options){
|
||
|
// summary:
|
||
|
// Simple query engine that matches using filter functions, named filter
|
||
|
// functions or objects by name-value on a query object hash
|
||
|
//
|
||
|
// description:
|
||
|
// The SimpleQueryEngine provides a way of getting a QueryResults through
|
||
|
// the use of a simple object hash as a filter. The hash will be used to
|
||
|
// match properties on data objects with the corresponding value given. In
|
||
|
// other words, only exact matches will be returned.
|
||
|
//
|
||
|
// This function can be used as a template for more complex query engines;
|
||
|
// for example, an engine can be created that accepts an object hash that
|
||
|
// contains filtering functions, or a string that gets evaluated, etc.
|
||
|
//
|
||
|
// When creating a new dojo.store, simply set the store's queryEngine
|
||
|
// field as a reference to this function.
|
||
|
//
|
||
|
// query: Object
|
||
|
// An object hash with fields that may match fields of items in the store.
|
||
|
// Values in the hash will be compared by normal == operator, but regular expressions
|
||
|
// or any object that provides a test() method are also supported and can be
|
||
|
// used to match strings by more complex expressions
|
||
|
// (and then the regex's or object's test() method will be used to match values).
|
||
|
//
|
||
|
// options: dojo/store/api/Store.QueryOptions?
|
||
|
// An object that contains optional information such as sort, start, and count.
|
||
|
//
|
||
|
// returns: Function
|
||
|
// A function that caches the passed query under the field "matches". See any
|
||
|
// of the "query" methods on dojo.stores.
|
||
|
//
|
||
|
// example:
|
||
|
// Define a store with a reference to this engine, and set up a query method.
|
||
|
//
|
||
|
// | var myStore = function(options){
|
||
|
// | // ...more properties here
|
||
|
// | this.queryEngine = SimpleQueryEngine;
|
||
|
// | // define our query method
|
||
|
// | this.query = function(query, options){
|
||
|
// | return QueryResults(this.queryEngine(query, options)(this.data));
|
||
|
// | };
|
||
|
// | };
|
||
|
|
||
|
// create our matching query function
|
||
|
switch(typeof query){
|
||
|
default:
|
||
|
throw new Error("Can not query with a " + typeof query);
|
||
|
case "object": case "undefined":
|
||
|
var queryObject = query;
|
||
|
query = function(object){
|
||
|
for(var key in queryObject){
|
||
|
var required = queryObject[key];
|
||
|
if(required && required.test){
|
||
|
// an object can provide a test method, which makes it work with regex
|
||
|
if(!required.test(object[key], object)){
|
||
|
return false;
|
||
|
}
|
||
|
}else if(required != object[key]){
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
};
|
||
|
break;
|
||
|
case "string":
|
||
|
// named query
|
||
|
if(!this[query]){
|
||
|
throw new Error("No filter function " + query + " was found in store");
|
||
|
}
|
||
|
query = this[query];
|
||
|
// fall through
|
||
|
case "function":
|
||
|
// fall through
|
||
|
}
|
||
|
function execute(array){
|
||
|
// execute the whole query, first we filter
|
||
|
var results = arrayUtil.filter(array, query);
|
||
|
// next we sort
|
||
|
var sortSet = options && options.sort;
|
||
|
if(sortSet){
|
||
|
results.sort(typeof sortSet == "function" ? sortSet : function(a, b){
|
||
|
for(var sort, i=0; sort = sortSet[i]; i++){
|
||
|
var aValue = a[sort.attribute];
|
||
|
var bValue = b[sort.attribute];
|
||
|
if (aValue != bValue){
|
||
|
return !!sort.descending == (aValue == null || aValue > bValue) ? -1 : 1;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
});
|
||
|
}
|
||
|
// now we paginate
|
||
|
if(options && (options.start || options.count)){
|
||
|
var total = results.length;
|
||
|
results = results.slice(options.start || 0, (options.start || 0) + (options.count || Infinity));
|
||
|
results.total = total;
|
||
|
}
|
||
|
return results;
|
||
|
}
|
||
|
execute.matches = query;
|
||
|
return execute;
|
||
|
};
|
||
|
|
||
|
});
|