Commit 265e7e0d authored by Tristan Cavelier's avatar Tristan Cavelier

complex queries: doc string added, jslint pass, improved

parent a9ae8a4c
// XXX /*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global newClass: true, Query: true, query_class_dict: true,
_export: true, QueryFactory: true */
/**
* The ComplexQuery inherits from Query, and compares one or several metadata
* values.
*
* @class ComplexQuery
* @param {Object} [spec={}] The specifications
* @param {String} [spec.operator="AND"] The compare method to use
* @param {String} spec.key The metadata key
* @param {String} spec.value The value of the metadata to compare
* @param {String} [spec.wildcard_character="%"] The wildcard character
*/
var ComplexQuery = newClass(Query, function (spec) { var ComplexQuery = newClass(Query, function (spec) {
/** /**
...@@ -10,26 +24,40 @@ var ComplexQuery = newClass(Query, function (spec) { ...@@ -10,26 +24,40 @@ var ComplexQuery = newClass(Query, function (spec) {
*/ */
this.operator = spec.operator || "AND"; this.operator = spec.operator || "AND";
/**
* The sub Query list which are used to query an item.
*
* @property query_list
* @type Array
* @default []
*/
this.query_list = spec.query_list || []; this.query_list = spec.query_list || [];
this.query_list = this.query_list.map(QueryFactory.create);
// XXX /**
this.match = function () { * #crossLink "Query/match:method"
todo */
this.match = function (item, wildcard_character) {
return this[this.operator](item, wildcard_character);
}; };
// XXX /**
* #crossLink "Query/toString:method"
*/
this.toString = function () { this.toString = function () {
var str_list = ["("]; var str_list = ["("], this_operator = this.operator;
this.query_list.forEach(function (query) { this.query_list.forEach(function (query) {
str_list.push(query.toString()); str_list.push(query.toString());
str_list.push(this.operator); str_list.push(this_operator);
}); });
str_list.pop(); // remove last operator str_list.pop(); // remove last operator
str_list.push(")"); str_list.push(")");
retrun str_list.join(" "); return str_list.join(" ");
}; };
// XXX /**
* #crossLink "Query/serialized:method"
*/
this.serialized = function () { this.serialized = function () {
var s = { var s = {
"type": "complex", "type": "complex",
...@@ -42,8 +70,16 @@ var ComplexQuery = newClass(Query, function (spec) { ...@@ -42,8 +70,16 @@ var ComplexQuery = newClass(Query, function (spec) {
return s; return s;
}; };
// XXX /**
this["AND"] = function (item, wildcard_character) { * Comparison operator, test if all sub queries match the
* item value
*
* @method AND
* @param {Object} item The item to match
* @param {String} wildcard_character The wildcard character
* @return {Boolean} true if all match, false otherwise
*/
this.AND = function (item, wildcard_character) {
var i; var i;
for (i = 0; i < this.query_list.length; i += 1) { for (i = 0; i < this.query_list.length; i += 1) {
if (!this.query_list[i].match(item, wildcard_character)) { if (!this.query_list[i].match(item, wildcard_character)) {
...@@ -53,8 +89,16 @@ var ComplexQuery = newClass(Query, function (spec) { ...@@ -53,8 +89,16 @@ var ComplexQuery = newClass(Query, function (spec) {
return true; return true;
}; };
// XXX /**
this["OR"] = function (item, wildcard_character) { * Comparison operator, test if one of the sub queries matches the
* item value
*
* @method OR
* @param {Object} item The item to match
* @param {String} wildcard_character The wildcard character
* @return {Boolean} true if one match, false otherwise
*/
this.OR = function (item, wildcard_character) {
var i; var i;
for (i = 0; i < this.query_list.length; i += 1) { for (i = 0; i < this.query_list.length; i += 1) {
if (this.query_list[i].match(item, wildcard_character)) { if (this.query_list[i].match(item, wildcard_character)) {
...@@ -64,8 +108,16 @@ var ComplexQuery = newClass(Query, function (spec) { ...@@ -64,8 +108,16 @@ var ComplexQuery = newClass(Query, function (spec) {
return false; return false;
}; };
// XXX /**
this["NOT"] = function (item, wildcard_character) { * Comparison operator, test if the sub query does not match the
* item value
*
* @method NOT
* @param {Object} item The item to match
* @param {String} wildcard_character The wildcard character
* @return {Boolean} true if one match, false otherwise
*/
this.NOT = function (item, wildcard_character) {
return !this.query_list[0].match(item, wildcard_character); return !this.query_list[0].match(item, wildcard_character);
}; };
}); });
......
return result; return result;
} } // parseStringToObject
}; // parseStringToQuery
...@@ -37,7 +37,7 @@ boolean_expression ...@@ -37,7 +37,7 @@ boolean_expression
expression expression
: LEFT_PARENTHESE search_text RIGHT_PARENTHESE [* %% = %2; *] : LEFT_PARENTHESE search_text RIGHT_PARENTHESE [* %% = %2; *]
| COLUMN expression [* simpleQuerySetId(%2,%1.split(':').slice(0,-1).join(':')); %% = %2; *] | COLUMN expression [* simpleQuerySetKey(%2,%1.split(':').slice(0,-1).join(':')); %% = %2; *]
| value [* %% = %1; *] | value [* %% = %1; *]
; ;
...@@ -53,59 +53,60 @@ string ...@@ -53,59 +53,60 @@ string
[* [*
var arrayExtend = function () { var arrayExtend = function () {
var j,i,newlist=[],listoflists = arguments; var j, i, newlist = [], list_list = arguments;
for (j=0; j<listoflists.length; ++j) { for (j = 0; j < list_list.length; j += 1) {
for (i=0; i<listoflists[j].length; ++i) { for (i = 0; i < list_list[j].length; i += 1) {
newlist.push(listoflists[j][i]); newlist.push(list_list[j][i]);
}
} }
return newlist; }
}; return newlist;
var mkSimpleQuery = function (id,value,operator) {
return {type:'simple',operator:'=',id:id,value:value}; }, mkSimpleQuery = function (key, value, operator) {
}; return {"type": "simple", "operator": "=", "key": key, "value": value};
var mkNotQuery = function (query) {
if (query.operator === 'NOT') { }, mkNotQuery = function (query) {
return query.query_list[0]; if (query.operator === "NOT") {
} return query.query_list[0];
return {type:'complex',operator:'NOT',query_list:[query]}; }
}; return {"type": "complex", "operator": "NOT", "query_list": [query]};
var mkComplexQuery = function (operator,query_list) {
var i,query_list2 = []; }, mkComplexQuery = function (operator, query_list) {
for (i=0; i<query_list.length; ++i) { var i, query_list2 = [];
if (query_list[i].operator === operator) { for (i = 0; i < query_list.length; i += 1) {
query_list2 = arrayExtend(query_list2,query_list[i].query_list); if (query_list[i].operator === operator) {
} else { query_list2 = arrayExtend(query_list2, query_list[i].query_list);
query_list2.push(query_list[i]); } else {
} query_list2.push(query_list[i]);
}
return {type:'complex',operator:operator,query_list:query_list2};
};
var simpleQuerySetId = function (query, id) {
var i;
if (query.type === 'complex') {
for (i = 0; i < query.query_list.length; ++i) {
simpleQuerySetId (query.query_list[i],id);
}
return true;
}
if (query.type === 'simple' && !query.id) {
query.id = id;
return true;
} }
return false; }
}; return {type:"complex",operator:operator,query_list:query_list2};
var error_offsets = [];
var error_lookaheads = []; }, simpleQuerySetKey = function (query, key) {
var error_count = 0; var i;
var result; if (query.type === "complex") {
if ( ( error_count = __##PREFIX##parse( string, error_offsets, error_lookaheads ) ) > 0 ) { for (i = 0; i < query.query_list.length; ++i) {
var i; simpleQuerySetKey (query.query_list[i],key);
for (i = 0; i < error_count; ++i) {
throw new Error ( "Parse error near \"" +
string.substr ( error_offsets[i] ) +
"\", expecting \"" +
error_lookaheads[i].join() + "\"" );
} }
return true;
}
if (query.type === "simple" && !query.key) {
query.key = key;
return true;
}
return false;
},
error_offsets = [],
error_lookaheads = [],
error_count = 0,
result;
if ((error_count = __##PREFIX##parse(string, error_offsets, error_lookaheads)) > 0) {
var i;
for (i = 0; i < error_count; i += 1) {
throw new Error("Parse error near \"" +
string.substr(error_offsets[i]) +
"\", expecting \"" +
error_lookaheads[i].join() + "\"");
}
} }
*] *]
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global newClass: true, sortFunction: true, parseStringToObject: true,
_export: true */
/** /**
* The query to use to filter a list of objects. * The query to use to filter a list of objects.
* This is an abstract class. * This is an abstract class.
...@@ -5,7 +9,7 @@ ...@@ -5,7 +9,7 @@
* @class Query * @class Query
* @constructor * @constructor
*/ */
var Query = newClass(function(spec) { var Query = newClass(function (spec) {
/** /**
* The wildcard character used to extend comparison action * The wildcard character used to extend comparison action
...@@ -29,9 +33,9 @@ var Query = newClass(function(spec) { ...@@ -29,9 +33,9 @@ var Query = newClass(function(spec) {
* index and second is the length. * index and second is the length.
*/ */
this.exec = function (item_list, option) { this.exec = function (item_list, option) {
var i; var i = 0;
for (i = 0; i < item_list.length;) { while (i < item_list.length) {
if (!this.match(item, option.wildcard_character)) { if (!this.match(item_list[i], option.wildcard_character)) {
item_list.splice(i, 1); item_list.splice(i, 1);
} else { } else {
i += 1; i += 1;
...@@ -41,10 +45,10 @@ var Query = newClass(function(spec) { ...@@ -41,10 +45,10 @@ var Query = newClass(function(spec) {
Query.sortOn(option.sort_on, item_list); Query.sortOn(option.sort_on, item_list);
} }
if (option.limit) { if (option.limit) {
new_item_list = item_list.slice( item_list.splice(0, option.limit[0]);
option.limit[0], if (option.limit[1]) {
option.limit[1] + option.limit[0] + 1 item_list.splice(option.limit[1]);
); }
} }
if (option.select_list) { if (option.select_list) {
Query.filterListSelect(option.select_list, item_list); Query.filterListSelect(option.select_list, item_list);
...@@ -53,19 +57,21 @@ var Query = newClass(function(spec) { ...@@ -53,19 +57,21 @@ var Query = newClass(function(spec) {
/** /**
* Test if an item matches this query * Test if an item matches this query
*
* @method match * @method match
* @param {Object} item The object to test * @param {Object} item The object to test
* @return {Boolean} true if match, false otherwise * @return {Boolean} true if match, false otherwise
*/ */
this.match = function (item, wildcard_character) {}; this.match = null; // function (item, wildcard_character) {};
/** /**
* Convert this query to a parsable string. * Convert this query to a parsable string.
*
* @method toString * @method toString
* @return {String} The string version of this query * @return {String} The string version of this query
*/ */
this.toString = function () {}; this.toString = null; // function () {};
/** /**
* Convert this query to an jsonable object in order to be remake thanks to * Convert this query to an jsonable object in order to be remake thanks to
...@@ -74,9 +80,17 @@ var Query = newClass(function(spec) { ...@@ -74,9 +80,17 @@ var Query = newClass(function(spec) {
* @method serialized * @method serialized
* @return {Object} The jsonable object * @return {Object} The jsonable object
*/ */
this.serialized = function () {}; this.serialized = null; // function () {};
}, {"static_methods": { }, {"static_methods": {
// XXX
/**
* Filter a list of items, modifying them to select only wanted keys.
*
* @method filterListSelect
* @param {Array} select_option Key list to keep
* @param {Array} list The item list to filter
*/
"filterListSelect": function (select_option, list) { "filterListSelect": function (select_option, list) {
list.forEach(function (item, index) { list.forEach(function (item, index) {
var new_item = {}; var new_item = {};
...@@ -86,204 +100,33 @@ var Query = newClass(function(spec) { ...@@ -86,204 +100,33 @@ var Query = newClass(function(spec) {
list[index] = new_item; list[index] = new_item;
}); });
}, },
// XXX
/**
* Sort a list of items, according to keys and directions.
*
* @method sortOn
* @param {Array} sort_on_option List of couples [key, direction]
* @param {Array} list The item list to sort
*/
"sortOn": function (sort_on_option, list) { "sortOn": function (sort_on_option, list) {
var sort_index; var sort_index;
for (sort_index = sort_on_option.length - 1; sort_index >= 0; for (sort_index = sort_on_option.length - 1; sort_index >= 0;
sort_index += 1) { sort_index -= 1) {
list.sort(sortFunction( list.sort(sortFunction(
sort_on_option[sort_index][0], sort_on_option[sort_index][0],
sort_on_option[sort_index][1] sort_on_option[sort_index][1]
)); ));
} }
}, },
"parseStringToQuery": parseStringToQuery
/**
* Parse a text request to a json query object tree
*
* @method parseStringToObject
* @param {String} string The string to parse
* @return {Object} The json query tree
*/
"parseStringToObject": parseStringToObject
}}); }});
_export("Query", Query); _export("Query", Query);
function query(query, object_list) {
var wildcard_character = typeof query.wildcard_character === "string" ?
query.wildcard_character : "%",
// A list of methods according to operators
operator_actions = {
"=": function (value1, value2) {
value1 = value1.toString();
return value1.match(convertToRegexp(
value2, wildcard_character
)) || false && true;
},
'!=': function (value1, value2) {
value1 = value1.toString();
return !(value1.match(convertToRegexp(
value2, wildcard_character
)));
},
'<': function (value1, value2) { return value1 < value2; },
'<=': function (value1, value2) { return value1 <= value2; },
'>': function (value1, value2) { return value1 > value2; },
'>=': function (value1, value2) { return value1 >= value2; },
'AND': function (item, query_list) {
var i;
for (i=0; i<query_list.length; ++i) {
if (! itemMatchesQuery (item, query_list[i])) {
return false;
}
}
return true;
},
'OR': function (item, query_list) {
var i;
for (i=0; i<query_list.length; ++i) {
if (itemMatchesQuery (item, query_list[i])) {
return true;
}
}
return false;
},
'NOT': function (item, query_list) {
return !itemMatchesQuery(item, query_list[0]);
}
},
convertToRegexp = function (string) {
return subString('^' + string.replace(
new RegExp(
'([\\{\\}\\(\\)\\^\\$\\&\\.\\*\\?\\\/\\+\\|\\[\\]\\-\\\\])'.
replace(wildcard_character ?
"\\" + wildcard_character : undefined, ""),
"g"
),
"\\$1"
) + '$',(wildcard_character||undefined), '.*');
},
subString = function (string, substring, newsubstring) {
var res = '', i = 0;
if (substring === undefined) {
return string;
}
while (true) {
var tmp = string.indexOf(substring, i);
if (tmp === -1) {
break;
}
for (; i < tmp; i += 1) {
res += string[i];
}
res += newsubstring;
i += substring.length;
}
for (; i < string.length; i += 1) {
res += string[i];
}
return res;
},
itemMatchesQuery = function (item, query_object) {
var i;
if (query_object.type === 'complex') {
return operator_actions[query_object.operator](
item, query_object.query_list
);
} else {
if (query_object.id) {
if (typeof item[query_object.id] !== 'undefined') {
return operator_actions[query_object.operator](
item[query_object.id], query_object.value
);
} else {
return false;
}
} else {
return true;
}
}
},
select = function (list, select_list) {
var i;
if (select_list.length === 0) {
return;
}
for (i=0; i<list.length; ++i) {
var list_value = {}, k;
for (k=0; k<select_list.length; ++k) {
list_value[select_list[k]] =
list[i][select_list[k]];
}
list[i] = list_value;
}
},
sortFunction = function (key, asc) {
if (asc === 'descending') {
return function (a,b) {
return a[key] < b[key] ? 1 : a[key] > b[key] ? -1 : 0;
};
}
return function (a,b) {
return a[key] > b[key] ? 1 : a[key] < b[key] ? -1 : 0;
};
},
mergeList = function (list, list_to_merge, index) {
var i,j;
for (i = index,j = 0; i < list_to_merge.length + index; ++i, ++j) {
list[i] = list_to_merge[j];
}
},
sort = function (list, sort_list) {
var i, tmp, key, asc, sortAndMerge = function() {
sort(tmp,sort_list.slice(1));
mergeList(list,tmp,i-tmp.length);
tmp = [list[i]];
};
if (list.length < 2) {
return;
}
if (sort_list.length === 0) {
return;
}
key = sort_list[0][0];
asc = sort_list[0][1];
list.sort (sortFunction (key,asc));
tmp = [list[0]];
for (i = 1; i < list.length; ++i) {
if (tmp[0][key] === list[i][key]) {
tmp.push(list[i]);
} else {
sortAndMerge();
}
}
sortAndMerge();
},
limit = function (list, limit_list) {
var i;
if (typeof limit_list[0] !== 'undefined') {
if (typeof limit_list[1] !== 'undefined') {
if (list.length > limit_list[1] + limit_list[0]) {
list.length = limit_list[1] + limit_list[0];
}
list.splice(0,limit_list[0]);
} else {
list.length = limit_list[0];
}
}
},
////////////////////////////////////////////////////////////
result_list = [], result_list_tmp = [], j;
object_list = object_list || [];
if (query.query === undefined) {
result_list = object_list;
} else {
for (j=0; j<object_list.length; ++j) {
if ( itemMatchesQuery (
object_list[j], scope.ComplexQueries.parse (query.query)
)) {
result_list.push(object_list[j]);
}
}
}
if (query.filter) {
select(result_list,query.filter.select_list || []);
sort(result_list,query.filter.sort_on || []);
limit(result_list,query.filter.limit || []);
}
return result_list;
}
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */ /*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global _export: true, ComplexQuery: true, SimpleQuery: true, /*global _export: true, ComplexQuery: true, SimpleQuery: true,
newClass: true, newClass: true */
sortFunction: true, convertSearchTextToRegExp: true */
// XXX // XXX
var query_class_dict = {}, query_factory = {}; var query_class_dict = {}, QueryFactory;
newClass.apply(query_factory, [{ QueryFactory = newClass({
"secure_methods": true "secure_methods": true,
}, function () { "static_methods": {
// XXX // XXX
this.create = function (object) { "create": function (object) {
if (typeof object.type === "string" && if (typeof object.type === "string" &&
query_class_dict[object.type]) { query_class_dict[object.type]) {
return new query_class_dict[object.type](object); return new query_class_dict[object.type](object);
}
return null;
} }
return null; }
}; }, function () {});
}]); // end QueryFactory
_export("factory", query_factory); _export("QueryFactory", QueryFactory);
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global newClass: true, Query: true, convertSearchTextToRegExp: true,
query_class_dict: true, _export: true */
/** /**
* The SimpleQuery inherits from Query, and compares one metadata value * The SimpleQuery inherits from Query, and compares one metadata value
* *
...@@ -38,7 +42,7 @@ var SimpleQuery = newClass(Query, function (spec) { ...@@ -38,7 +42,7 @@ var SimpleQuery = newClass(Query, function (spec) {
* #crossLink "Query/match:method" * #crossLink "Query/match:method"
*/ */
this.match = function (item, wildcard_character) { this.match = function (item, wildcard_character) {
this[this.operator](item[this.key], this.value, wildcard_character); return this[this.operator](item[this.key], this.value, wildcard_character);
}; };
/** /**
...@@ -61,7 +65,15 @@ var SimpleQuery = newClass(Query, function (spec) { ...@@ -61,7 +65,15 @@ var SimpleQuery = newClass(Query, function (spec) {
}; };
}; };
// XXX /**
* Comparison operator, test if this query value matches the item value
*
* @method =
* @param {String} object_value The value to compare
* @param {String} comparison_value The comparison value
* @param {String} wildcard_character The wildcard_character
* @return {Boolean} true if match, false otherwise
*/
this["="] = function (object_value, comparison_value, this["="] = function (object_value, comparison_value,
wildcard_character) { wildcard_character) {
return convertSearchTextToRegExp( return convertSearchTextToRegExp(
...@@ -70,31 +82,70 @@ var SimpleQuery = newClass(Query, function (spec) { ...@@ -70,31 +82,70 @@ var SimpleQuery = newClass(Query, function (spec) {
).test(object_value.toString()); ).test(object_value.toString());
}; };
// XXX /**
* Comparison operator, test if this query value does not match the item value
*
* @method !=
* @param {String} object_value The value to compare
* @param {String} comparison_value The comparison value
* @param {String} wildcard_character The wildcard_character
* @return {Boolean} true if not match, false otherwise
*/
this["!="] = function (object_value, comparison_value, this["!="] = function (object_value, comparison_value,
wildcard_character) { wildcard_character) {
return !convertSearchTextToRegExp( return !convertSearchTextToRegExp(
comparison_value.toString(), comparison_value.toString(),
wildcard_character || this.wildcard_character wildcard_character || this.wildcard_character
).test(object_value.toString()); ).test(object_value.toString());
}; };
// XXX /**
* Comparison operator, test if this query value is lower than the item value
*
* @method <
* @param {Number, String} object_value The value to compare
* @param {Number, String} comparison_value The comparison value
* @return {Boolean} true if lower, false otherwise
*/
this["<"] = function (object_value, comparison_value) { this["<"] = function (object_value, comparison_value) {
return object_value < comparison_value; return object_value < comparison_value;
}; };
// XXX /**
* Comparison operator, test if this query value is equal or lower than the
* item value
*
* @method <=
* @param {Number, String} object_value The value to compare
* @param {Number, String} comparison_value The comparison value
* @return {Boolean} true if equal or lower, false otherwise
*/
this["<="] = function (object_value, comparison_value) { this["<="] = function (object_value, comparison_value) {
return object_value <= comparison_value; return object_value <= comparison_value;
}; };
// XXX /**
* Comparison operator, test if this query value is greater than the item
* value
*
* @method >
* @param {Number, String} object_value The value to compare
* @param {Number, String} comparison_value The comparison value
* @return {Boolean} true if greater, false otherwise
*/
this[">"] = function (object_value, comparison_value) { this[">"] = function (object_value, comparison_value) {
return object_value > comparison_value; return object_value > comparison_value;
}; };
// XXX /**
* Comparison operator, test if this query value is equal or greater than the
* item value
*
* @method >=
* @param {Number, String} object_value The value to compare
* @param {Number, String} comparison_value The comparison value
* @return {Boolean} true if equal or greater, false otherwise
*/
this[">="] = function (object_value, comparison_value) { this[">="] = function (object_value, comparison_value) {
return object_value >= comparison_value; return object_value >= comparison_value;
}; };
......
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */ /*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global _export: true */ /*global _export: true */
#!/usr/bin/env node
// keywords: js, javascript, new class creator, generator
/** /**
* Create a class, manage inheritance, static methods, * Create a class, manage inheritance, static methods,
* protected attributes and can hide methods or/and secure methods * protected attributes and can hide methods or/and secure methods
* *
* @method newClass * @method newClass
* @param {Class} Class Classes to inherit from (0..n) * @param {Class} Class Classes to inherit from (0..n). The last class
* parameter will inherit from the previous one, and so on
* @param {Object} option Class option (0..n) * @param {Object} option Class option (0..n)
* @param {Boolean} [option.secure_methods=false] Make methods not configurable * @param {Boolean} [option.secure_methods=false] Make methods not configurable
* and not writable * and not writable
* @param {Boolean} [option.hide_methods=false] Make methods not enumerable * @param {Boolean} [option.hide_methods=false] Make methods not enumerable
* @param {Object} [option.static_methods={}] Add static methods * @param {Object} [option.static_methods={}] Object of static methods
* @param {Function} constructor The new class constructor * @param {Function} constructor The new class constructor
* @return {Class} The new class * @return {Class} The new class
*/ */
...@@ -29,7 +26,7 @@ function newClass() { ...@@ -29,7 +26,7 @@ function newClass() {
option = option || {}; option = option || {};
for (k in arguments[j]) { for (k in arguments[j]) {
if (arguments[j].hasOwnProperty(k)) { if (arguments[j].hasOwnProperty(k)) {
option[j] = arguments[j][k]; option[k] = arguments[j][k];
} }
} }
} }
...@@ -65,7 +62,9 @@ function newClass() { ...@@ -65,7 +62,9 @@ function newClass() {
postCreate(this); postCreate(this);
return this; return this;
}; };
for (j in (option.static_methods || {})) { option = option || {};
option.static_methods = option.static_methods || {};
for (j in option.static_methods) {
if (option.static_methods.hasOwnProperty(j)) { if (option.static_methods.hasOwnProperty(j)) {
new_class[j] = option.static_methods[j]; new_class[j] = option.static_methods[j];
} }
...@@ -76,16 +75,16 @@ function newClass() { ...@@ -76,16 +75,16 @@ function newClass() {
/** /**
* Escapes regexp special chars from a string. * Escapes regexp special chars from a string.
* @method regexpEscapeString * @method stringEscapeRegexpCharacters
* @param {String} string The string to escape * @param {String} string The string to escape
* @return {String} The escaped string * @return {String} The escaped string
*/ */
function regexpEscapeString(string) { function stringEscapeRegexpCharacters(string) {
if (typeof string === "string") { if (typeof string === "string") {
return string.replace(/([\\\.\$\[\]\(\)\{\}\^\?\*\+\-])/g, "\\$1"); return string.replace(/([\\\.\$\[\]\(\)\{\}\^\?\*\+\-])/g, "\\$1");
} }
} }
_export("regexpEscapeString", regexpEscapeString); _export("stringEscapeRegexpCharacters", stringEscapeRegexpCharacters);
/** /**
* Convert a search text to a regexp. * Convert a search text to a regexp.
...@@ -95,8 +94,8 @@ _export("regexpEscapeString", regexpEscapeString); ...@@ -95,8 +94,8 @@ _export("regexpEscapeString", regexpEscapeString);
* @return {RegExp} The search text regexp * @return {RegExp} The search text regexp
*/ */
function convertSearchTextToRegExp(string, wildcard_character) { function convertSearchTextToRegExp(string, wildcard_character) {
return new RegExp("^" + regexpEscapeString(string).replace( return new RegExp("^" + stringEscapeRegexpCharacters(string).replace(
regexpEscapeString(wildcard_character), stringEscapeRegexpCharacters(wildcard_character),
'.*' '.*'
) + "$"); ) + "$");
} }
...@@ -105,11 +104,11 @@ _export("convertSearchTextToRegExp", convertSearchTextToRegExp); ...@@ -105,11 +104,11 @@ _export("convertSearchTextToRegExp", convertSearchTextToRegExp);
// XXX // XXX
function sortFunction(key, way) { function sortFunction(key, way) {
if (way === 'descending') { if (way === 'descending') {
return function (a,b) { return function (a, b) {
return a[key] < b[key] ? 1 : a[key] > b[key] ? -1 : 0; return a[key] < b[key] ? 1 : a[key] > b[key] ? -1 : 0;
}; };
} }
return function (a,b) { return function (a, b) {
return a[key] > b[key] ? 1 : a[key] < b[key] ? -1 : 0; return a[key] > b[key] ? 1 : a[key] < b[key] ? -1 : 0;
}; };
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment