Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Xueyun Qian
erp5
Commits
60cc9e35
Commit
60cc9e35
authored
Dec 04, 2015
by
Romain Courteaud
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[erp5_web_renderjs_ui] Update to jIO 3.6.0
This should speed up IndexedDB.allDocs usage
parent
de8f8942
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
1176 additions
and
1097 deletions
+1176
-1097
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_appcache.xml
...TemplateItem/web_page_module/rjs_gadget_erp5_appcache.xml
+3
-3
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_jio_js.xml
...thTemplateItem/web_page_module/rjs_gadget_erp5_jio_js.xml
+8
-7
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_page_history_js.xml
...eItem/web_page_module/rjs_gadget_erp5_page_history_js.xml
+6
-6
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_jio_js.xml
...nderjs_ui/PathTemplateItem/web_page_module/rjs_jio_js.xml
+1159
-1081
No files found.
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_appcache.xml
View file @
60cc9e35
...
...
@@ -102,7 +102,7 @@
<value>
<string
encoding=
"cdata"
>
<![CDATA[
CACHE MANIFEST\n
# generated on
Mon, 30 Nov
2015 10:00:00 +0000\n
# generated on
Fri, 04 Dec
2015 10:00:00 +0000\n
# XXX + fonts\n
# images/ajax-loader.gif\n
CACHE:\n
...
...
@@ -342,7 +342,7 @@ NETWORK:\n
</item>
<item>
<key>
<string>
serial
</string>
</key>
<value>
<string>
947.
22631.16141.50329
</string>
</value>
<value>
<string>
947.
36771.24081.57838
</string>
</value>
</item>
<item>
<key>
<string>
state
</string>
</key>
...
...
@@ -360,7 +360,7 @@ NETWORK:\n
</tuple>
<state>
<tuple>
<float>
144
8650222.45
</float>
<float>
144
9236184.22
</float>
<string>
UTC
</string>
</tuple>
</state>
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_jio_js.xml
View file @
60cc9e35
...
...
@@ -101,13 +101,14 @@
<key>
<string>
text_content
</string>
</key>
<value>
<string
encoding=
"cdata"
>
<![CDATA[
/*global window, rJS, RSVP, UriTemplate, URI,
objectToSearchText
, SimpleQuery, ComplexQuery, jIO */\n
/*global window, rJS, RSVP, UriTemplate, URI,
Query
, SimpleQuery, ComplexQuery, jIO */\n
/*jslint indent: 2, maxerr: 3, nomen: true */\n
(function (window, rJS, RSVP, UriTemplate, URI,
objectToSearchText
, SimpleQuery, ComplexQuery, jIO) {\n
(function (window, rJS, RSVP, UriTemplate, URI,
Query
, SimpleQuery, ComplexQuery, jIO) {\n
"use strict";\n
\n
function wrapJioCall(gadget, method_name, argument_list) {\n
var storage = gadget.state_parameter_dict.jio_storage;\n
\n
return storage[method_name].apply(storage, argument_list)\n
.push(undefined, function (error) {\n
if ((error.target !== undefined) && (error.target.status === 401)) {\n
...
...
@@ -218,14 +219,14 @@
if (result_list) {\n
local_roles = result_list;\n
parsed_query.query_list.splice(i, 1);\n
query = objectToSearchText(parsed_query);\n
query =
Query.
objectToSearchText(parsed_query);\n
i = parsed_query.query_list.length;\n
} else {\n
result_list = isMultipleLocalRoles(sub_query);\n
if (result_list) {\n
local_roles = result_list;\n
parsed_query.query_list.splice(i, 1);\n
query = objectToSearchText(parsed_query);\n
query =
Query.
objectToSearchText(parsed_query);\n
i = parsed_query.query_list.length;\n
}\n
}\n
...
...
@@ -280,7 +281,7 @@
return wrapJioCall(this, \'putAttachment\', [id, name, JSON.stringify(json)]);\n
});\n
\n
}(window, rJS, RSVP, UriTemplate, URI,
objectToSearchText
, SimpleQuery, ComplexQuery, jIO));
}(window, rJS, RSVP, UriTemplate, URI,
Query
, SimpleQuery, ComplexQuery, jIO));
]]>
</string>
</value>
</item>
...
...
@@ -417,7 +418,7 @@
</item>
<item>
<key>
<string>
serial
</string>
</key>
<value>
<string>
947.
15020.24457.52667
</string>
</value>
<value>
<string>
947.
36789.31946.17646
</string>
</value>
</item>
<item>
<key>
<string>
state
</string>
</key>
...
...
@@ -435,7 +436,7 @@
</tuple>
<state>
<tuple>
<float>
144
8016802.0
</float>
<float>
144
9236578.55
</float>
<string>
UTC
</string>
</tuple>
</state>
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_page_history_js.xml
View file @
60cc9e35
...
...
@@ -101,9 +101,9 @@
<key>
<string>
text_content
</string>
</key>
<value>
<string
encoding=
"cdata"
>
<![CDATA[
/*global window, rJS, RSVP, Handlebars, SimpleQuery, ComplexQuery,
objectToSearchText
*/\n
/*global window, rJS, RSVP, Handlebars, SimpleQuery, ComplexQuery,
Query
*/\n
/*jslint nomen: true, indent: 2, maxerr: 3 */\n
(function (window, rJS, RSVP, Handlebars, SimpleQuery, ComplexQuery,
objectToSearchText
) {\n
(function (window, rJS, RSVP, Handlebars, SimpleQuery, ComplexQuery,
Query
) {\n
"use strict";\n
\n
/////////////////////////////////////////////////////////////////\n
...
...
@@ -165,7 +165,7 @@
};\n
}\n
return gadget.jio_allDocs({\n
query: objectToSearchText(new ComplexQuery({operator: \'OR\', query_list: query_list})),\n
query:
Query.
objectToSearchText(new ComplexQuery({operator: \'OR\', query_list: query_list})),\n
select_list: ["title", "portal_type"],\n
limit: id_list.length\n
});\n
...
...
@@ -212,7 +212,7 @@
my_translated_html;\n
});\n
});\n
}(window, rJS, RSVP, Handlebars, SimpleQuery, ComplexQuery,
objectToSearchText
));
}(window, rJS, RSVP, Handlebars, SimpleQuery, ComplexQuery,
Query
));
]]>
</string>
</value>
</item>
...
...
@@ -349,7 +349,7 @@
</item>
<item>
<key>
<string>
serial
</string>
</key>
<value>
<string>
947.22
112.65196.42461
</string>
</value>
<value>
<string>
947.22
494.14742.48810
</string>
</value>
</item>
<item>
<key>
<string>
state
</string>
</key>
...
...
@@ -367,7 +367,7 @@
</tuple>
<state>
<tuple>
<float>
144
8442387.23
</float>
<float>
144
9229724.79
</float>
<string>
UTC
</string>
</tuple>
</state>
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_jio_js.xml
View file @
60cc9e35
...
...
@@ -3998,229 +3998,6 @@ if (typeof define === \'function\' && define.amd) {\n
makeGlobal();\n
}\n
}).call(this);\n
;/*jslint
indent:
2,
maxlen:
80,
sloppy:
true
*/\n
\n
var
query_class_dict =
{};\n
;/*jslint
indent:
2,
maxlen:
80,
sloppy:
true,
nomen:
true
*/\n
/*global
parseStringToObject:
true,
emptyFunction:
true,
sortOn:
true,
limit:\n
true,
select:
true,
window,
stringEscapeRegexpCharacters:
true,\n
deepClone,
RSVP*/\n
\n
/**\n
*
The
query
to
use
to
filter
a
list
of
objects.\n
*
This
is
an
abstract
class.\n
*\n
*
@class
Query\n
*
@constructor\n
*/\n
function
Query()
{\n
\n
/**\n
*
Called
before
parsing
the
query.
Must
be
overridden!\n
*\n
*
@method
onParseStart\n
*
@param
{Object}
object
The
object
shared
in
the
parse
process\n
*
@param
{Object}
option
Some
option
gave
in
parse()\n
*/\n
this.onParseStart =
emptyFunction;\n
\n
/**\n
*
Called
when
parsing
a
simple
query.
Must
be
overridden!\n
*\n
*
@method
onParseSimpleQuery\n
*
@param
{Object}
object
The
object
shared
in
the
parse
process\n
*
@param
{Object}
option
Some
option
gave
in
parse()\n
*/\n
this.onParseSimpleQuery =
emptyFunction;\n
\n
/**\n
*
Called
when
parsing
a
complex
query.
Must
be
overridden!\n
*\n
*
@method
onParseComplexQuery\n
*
@param
{Object}
object
The
object
shared
in
the
parse
process\n
*
@param
{Object}
option
Some
option
gave
in
parse()\n
*/\n
this.onParseComplexQuery =
emptyFunction;\n
\n
/**\n
*
Called
after
parsing
the
query.
Must
be
overridden!\n
*\n
*
@method
onParseEnd\n
*
@param
{Object}
object
The
object
shared
in
the
parse
process\n
*
@param
{Object}
option
Some
option
gave
in
parse()\n
*/\n
this.onParseEnd =
emptyFunction;\n
\n
}\n
\n
/**\n
*
Filter
the
item
list
with
matching
item
only\n
*\n
*
@method
exec\n
*
@param
{Array}
item_list
The
list
of
object\n
*
@param
{Object}
[option]
Some
operation
option\n
*
@param
{Array}
[option.select_list]
A
object
keys
to
retrieve\n
*
@param
{Array}
[option.sort_on]
Couples
of
object
keys
and
"ascending"\n
*
or
"descending"\n
*
@param
{Array}
[option.limit]
Couple
of
integer,
first
is
an
index
and\n
*
second
is
the
length.\n
*/\n
Query.prototype.exec =
function
(item_list,
option)
{\n
var
i,
promises =
[];\n
if
(!Array.isArray(item_list))
{\n
throw
new
TypeError("Query().exec():
Argument
1
is
not
of
type
\'array\'");\n
}\n
if
(
option =
==
undefined)
{\n
option =
{};\n
}\n
if
(typeof
option
!==
\'object\')
{\n
throw
new
TypeError("Query().exec():
"
+\n
"Optional
argument
2
is
not
of
type
\'object\'");\n
}\n
for
(
i =
0;
i
<
item_list.length;
i
+=
1)
{\n
if
(!item_list[i])
{\n
promises.push(RSVP.resolve(false));\n
}
else
{\n
promises.push(this.match(item_list[i]));\n
}\n
}\n
return
new
RSVP.Queue()\n
.push(function
()
{\n
return
RSVP.all(promises);\n
})\n
.push(function
(answers)
{\n
var
j;\n
for
(
j =
answers.length
-
1;
j
>
= 0; j -= 1) {\n
if (!answers[j]) {\n
item_list.splice(j, 1);\n
}\n
}\n
if (option.sort_on) {\n
return sortOn(option.sort_on, item_list);\n
}\n
})\n
.push(function () {\n
if (option.limit) {\n
return limit(option.limit, item_list);\n
}\n
})\n
.push(function () {\n
return select(option.select_list || [], item_list);\n
})\n
.push(function () {\n
return item_list;\n
});\n
};\n
\n
/**\n
* Test if an item matches this query\n
*\n
* @method match\n
* @param {Object} item The object to test\n
* @return {Boolean} true if match, false otherwise\n
*/\n
Query.prototype.match = function () {\n
return RSVP.resolve(true);\n
};\n
\n
\n
/**\n
* Browse the Query in deep calling parser method in each step.\n
*\n
* `onParseStart` is called first, on end `onParseEnd` is called.\n
* It starts from the simple queries at the bottom of the tree calling the\n
* parser method `onParseSimpleQuery`, and go up calling the\n
* `onParseComplexQuery` method.\n
*\n
* @method parse\n
* @param {Object} option Any options you want (except \'parsed\')\n
* @return {Any} The parse result\n
*/\n
Query.prototype.parse = function (option) {\n
var that = this,\n
object;\n
/**\n
* The recursive parser.\n
*\n
* @param {Object} object The object shared in the parse process\n
* @param {Object} options Some options usable in the parseMethods\n
* @return {Any} The parser result\n
*/\n
function recParse(object, option) {\n
var query = object.parsed,\n
queue = new RSVP.Queue(),\n
i;\n
\n
function enqueue(j) {\n
queue\n
.push(function () {\n
object.parsed = query.query_list[j];\n
return recParse(object, option);\n
})\n
.push(function () {\n
query.query_list[j] = object.parsed;\n
});\n
}\n
\n
if (query.type === "complex") {\n
\n
\n
for (i = 0; i
< query.query_list.length
;
i
+=
1)
{\n
enqueue(i);\n
}\n
\n
return
queue\n
.push(function
()
{\n
object.parsed =
query;\n
return
that.onParseComplexQuery(object,
option);\n
});\n
\n
}\n
if
(
query.type =
==
"simple")
{\n
return
that.onParseSimpleQuery(object,
option);\n
}\n
}\n
object =
{\n
parsed:
JSON.parse(JSON.stringify(that.serialized()))\n
};\n
return
new
RSVP.Queue()\n
.push(function
()
{\n
return
that.onParseStart(object,
option);\n
})\n
.push(function
()
{\n
return
recParse(object,
option);\n
})\n
.push(function
()
{\n
return
that.onParseEnd(object,
option);\n
})\n
.push(function
()
{\n
return
object.parsed;\n
});\n
\n
};\n
\n
/**\n
*
Convert
this
query
to
a
parsable
string.\n
*\n
*
@method
toString\n
*
@return
{String}
The
string
version
of
this
query\n
*/\n
Query.prototype.toString =
function
()
{\n
return
"";\n
};\n
\n
/**\n
*
Convert
this
query
to
an
jsonable
object
in
order
to
be
remake
thanks
to\n
*
QueryFactory
class.\n
*\n
*
@method
serialized\n
*
@return
{Object}
The
jsonable
object\n
*/\n
Query.prototype.serialized =
function
()
{\n
return
undefined;\n
};\n
\n
window.Query =
Query;\n
;/**\n
*
Parse
a
text
request
to
a
json
query
object
tree\n
*\n
...
...
@@ -4924,896 +4701,1010 @@ if ((error_count = __NODEJS_parse(string, error_offsets, error_lookaheads)) > 0)
;
return
result;\n
}
//
parseStringToObject\n
\n
Query.parseStringToObject =
parseStringToObject;
\n
;/*jslint
indent:
2,
maxlen:
80,
sloppy:
true,
nomen:
true
*/\n
/*global
Query:
true,
query_class_dict:
true,
inherits:
true,
\n
window,
QueryFactory,
RSVP
*/
\n
;/*global
RSVP,
window,
parseStringToObject*/
\n
/*jslint
nomen:
true,
maxlen:
90
*/\n
(function
(RSVP,
window,
parseStringToObject)
{
\n
"use
strict";
\n
\n
/**\n
*
The
ComplexQuery
inherits
from
Query,
and
compares
one
or
several
metadata\n
*
values.\n
*\n
*
@class
ComplexQuery\n
*
@extends
Query\n
*
@param
{Object}
[
spec=
{}]
The
specifications\n
*
@param
{String}
[
spec.operator=
"AND"
]
The
compare
method
to
use\n
*
@param
{String}
spec.key
The
metadata
key\n
*
@param
{String}
spec.value
The
value
of
the
metadata
to
compare\n
*/\n
function
ComplexQuery(spec,
key_schema)
{\n
Query.call(this);\n
var
query_class_dict =
{},\n
regexp_escape =
/[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g,\n
regexp_percent =
/%/g,\n
regexp_underscore =
/_/g,\n
regexp_operator =
/^(?:AND|OR|NOT)$/i,\n
regexp_comparaison =
/^(?:!?=|<=?|
>
=?)$/i;\n
\n
/**\n
*
Logical
operator
to
use
to
compare
object
values\n
* Convert metadata values to array of strings. ex:\n
*\n
* "a" -> ["a"],\n
* {"content": "a"} -> ["a"]\n
*\n
*
@attribute
operator\n
*
@type
String\n
*
@default
"AND"\n
*
@optional\n
* @param {Any} value The metadata value\n
* @return {Array} The value in string array format\n
*/\n
this.operator =
spec.operator;\n
function metadataValueToStringArray(value) {\n
var i, new_value = [];\n
if (value === undefined) {\n
return undefined;\n
}\n
if (!Array.isArray(value)) {\n
value = [value];\n
}\n
for (i = 0; i
< value.length
;
i
+=
1)
{\n
if
(typeof
value[i]
===
\'object\')
{\n
new_value[i]
=
value[i].content;\n
}
else
{\n
new_value[i]
=
value[i];\n
}\n
}\n
return
new_value;\n
}\n
\n
/**\n
*
The
sub
Query
list
which
are
used
to
query
an
item.
\n
*
A
sort
function
to
sort
items
by
key
\n
*\n
*
@attribute
query_list\n
*
@type
Array\n
*
@default
[]\n
*
@optional\n
*
@param
{String}
key
The
key
to
sort
on\n
*
@param
{String}
[
way=
"ascending"
]
\'ascending\'
or
\'descending\'\n
*
@return
{Function}
The
sort
function\n
*/\n
this.query_list =
spec.query_list
||
[];\n
/*jslint
unparam:
true*/\n
this.query_list =
this.query_list.map(\n
//
decorate
the
map
to
avoid
sending
the
index
as
key_schema
argument\n
function
(o,
i)
{
return
QueryFactory.create(o,
key_schema);
}\n
);\n
/*jslint
unparam:
false*/\n
\n
}\n
inherits(ComplexQuery,
Query);\n
\n
ComplexQuery.prototype.operator =
"AND"
;\n
ComplexQuery.prototype.type =
"complex"
;\n
\n
/**\n
*
#crossLink
"Query/match:method"\n
*/\n
ComplexQuery.prototype.match =
function
(item)
{\n
var
operator =
this.operator;\n
if
(!(/^(?:AND|OR|NOT)$/i.test(operator)))
{\n
operator =
"AND"
;\n
function
sortFunction(key,
way)
{\n
var
result;\n
if
(
way =
==
\'descending\')
{\n
result =
1;\n
}
else
if
(
way =
==
\'ascending\')
{\n
result =
-1;\n
}
else
{\n
throw
new
TypeError("Query.sortFunction():
"
+\n
"Argument
2
must
be
\'ascending\'
or
\'descending\'");\n
}\n
return
function
(a,
b)
{\n
//
this
comparison
is
5
times
faster
than
json
comparison\n
var
i,
l;\n
a =
metadataValueToStringArray(a[key])
||
[];\n
b =
metadataValueToStringArray(b[key])
||
[];\n
l =
a.length
>
b.length ? a.length : b.length;\n
for (i = 0; i
< l
;
i
+=
1)
{\n
if
(a[i]
===
undefined)
{\n
return
result;\n
}\n
if
(b[i]
===
undefined)
{\n
return
-result;\n
}\n
if
(a[i]
>
b[i]) {\n
return -result;\n
}\n
if (a[i]
< b
[i])
{\n
return
result;\n
}\n
}\n
return
0;\n
};\n
}\n
return
this[operator.toUpperCase()](item);\n
};\n
\n
/**\n
*
#crossLink
"Query/toString:method"\n
*/\n
ComplexQuery.prototype.toString =
function
()
{\n
var
str_list =
[],
this_operator =
this.operator;\n
if
(
this.operator =
==
"NOT")
{\n
str_list.push("NOT
(");\n
str_list.push(this.query_list[0].toString());\n
str_list.push(")");\n
return
str_list.join("
");\n
/**\n
*
Sort
a
list
of
items,
according
to
keys
and
directions.\n
*\n
*
@param
{Array}
sort_on_option
List
of
couples
[key,
direction]\n
*
@param
{Array}
list
The
item
list
to
sort\n
*
@return
{Array}
The
filtered
list\n
*/\n
function
sortOn(sort_on_option,
list)
{\n
var
sort_index;\n
if
(!Array.isArray(sort_on_option))
{\n
throw
new
TypeError("jioquery.sortOn():
"
+\n
"Argument
1
is
not
of
type
\'array\'");\n
}\n
for
(
sort_index =
sort_on_option.length
-
1;
sort_index
>
= 0;\n
sort_index -= 1) {\n
list.sort(sortFunction(\n
sort_on_option[sort_index][0],\n
sort_on_option[sort_index][1]\n
));\n
}\n
return list;\n
}\n
this.query_list.forEach(function
(query)
{\n
str_list.push("(");\n
str_list.push(query.toString());\n
str_list.push(")");\n
str_list.push(this_operator);\n
});\n
str_list.length
-=
1;\n
return
str_list.join("
");\n
};\n
\n
/**\n
*
#crossLink
"Query/serialized:method"\n
*/\n
ComplexQuery.prototype.serialized =
function
()
{\n
var
s =
{\n
"type":
"complex",\n
"operator":
this.operator,\n
"query_list":
[]\n
};\n
this.query_list.forEach(function
(query)
{\n
s.query_list.push(\n
typeof
query.toJSON =
==
"function"
?
query.toJSON()
:
query\n
);\n
});\n
return
s;\n
};\n
ComplexQuery.prototype.toJSON =
ComplexQuery.prototype.serialized;\n
\n
/**\n
*
Comparison
operator,
test
if
all
sub
queries
match
the\n
*
item
value\n
*\n
*
@method
AND\n
*
@param
{Object}
item
The
item
to
match\n
*
@return
{Boolean}
true
if
all
match,
false
otherwise\n
*/\n
ComplexQuery.prototype.AND =
function
(item)
{\n
var
queue =
new
RSVP.Queue(),\n
context =
this,\n
i =
0;\n
\n
function
executeNextIfNotFalse(result)
{\n
if
(
result =
==
false)
{\n
//
No
need
to
evaluate
the
other
elements,
as
one
is
false\n
return
result;\n
/**\n
* Limit a list of items, according to index and length.\n
*\n
* @param {Array} limit_option A couple [from, length]\n
* @param {Array} list The item list to limit\n
* @return {Array} The filtered list\n
*/\n
function limit(limit_option, list) {\n
if (!Array.isArray(limit_option)) {\n
throw new TypeError("jioquery.limit(): " +\n
"Argument 1 is not of type \'array\'");\n
}\n
if
(
context.query_list.length =
==
i
)
{\n
//
No
new
element
to
loop
on
\n
return
true
;\n
if (
!Array.isArray(list)
) {\n
throw new TypeError("jioquery.limit(): " +
\n
"Argument 2 is not of type \'array\'")
;\n
}\n
queue\n
.push(function
()
{\n
var
sub_result =
context.query_list[i].match(item);\n
i
+=
1;\n
return
sub_result;\n
})\n
.push(executeNextIfNotFalse);\n
list.splice(0, limit_option[0]);\n
if (limit_option[1]) {\n
list.splice(limit_option[1]);\n
}\n
return list;\n
}\n
\n
executeNextIfNotFalse(true);\n
return
queue;\n
};\n
\n
/**\n
*
Comparison
operator,
test
if
one
of
the
sub
queries
matches
the\n
*
item
value\n
*\n
*
@method
OR\n
*
@param
{Object}
item
The
item
to
match\n
*
@return
{Boolean}
true
if
one
match,
false
otherwise\n
*/\n
ComplexQuery.prototype.OR =
function
(item)
{\n
var
queue =
new
RSVP.Queue(),\n
context =
this,\n
i =
0;\n
\n
function
executeNextIfNotTrue(result)
{\n
if
(
result =
==
true)
{\n
//
No
need
to
evaluate
the
other
elements,
as
one
is
true\n
return
result;\n
}\n
if
(
context.query_list.length =
==
i)
{\n
//
No
new
element
to
loop
on\n
return
false;\n
/**\n
* Filter a list of items, modifying them to select only wanted keys.\n
*\n
* @param {Array} select_option Key list to keep\n
* @param {Array} list The item list to filter\n
* @return {Array} The filtered list\n
*/\n
function select(select_option, list) {\n
var i, j, new_item;\n
if (!Array.isArray(select_option)) {\n
throw new TypeError("jioquery.select(): " +\n
"Argument 1 is not of type Array");\n
}\n
if (!Array.isArray(list)) {\n
throw new TypeError("jioquery.select(): " +\n
"Argument 2 is not of type Array");\n
}\n
for (i = 0; i
< list.length
;
i
+=
1)
{\n
new_item =
{};\n
for
(
j =
0;
j
<
select_option.length;
j
+=
1)
{\n
if
(list[i].hasOwnProperty([select_option[j]]))
{\n
new_item[select_option[j]]
=
list[i][select_option[j]];\n
}\n
}\n
for
(j
in
new_item)
{\n
if
(new_item.hasOwnProperty(j))
{\n
list[i]
=
new_item;\n
break;\n
}\n
}\n
}\n
queue\n
.push(function
()
{\n
var
sub_result =
context.query_list[i].match(item);\n
i
+=
1;\n
return
sub_result;\n
})\n
.push(executeNextIfNotTrue);\n
return
list;\n
}\n
\n
executeNextIfNotTrue(false);\n
return
queue;\n
};\n
/**\n
*
The
query
to
use
to
filter
a
list
of
objects.\n
*
This
is
an
abstract
class.\n
*\n
*
@class
Query\n
*
@constructor\n
*/\n
function
Query()
{\n
\n
/**\n
*
Comparison
operator,
test
if
the
sub
query
does
not
match
the\n
*
item
value\n
*\n
*
@method
NOT\n
*
@param
{Object}
item
The
item
to
match\n
*
@return
{Boolean}
true
if
one
match,
false
otherwise\n
*/\n
ComplexQuery.prototype.NOT =
function
(item)
{\n
return
new
RSVP.Queue()\n
.push(function
()
{\n
return
this.query_list[0].match(item);\n
})\n
.push(function
(answer)
{\n
return
!answer;\n
});\n
};\n
/**\n
*
Called
before
parsing
the
query.
Must
be
overridden!\n
*\n
*
@method
onParseStart\n
*
@param
{Object}
object
The
object
shared
in
the
parse
process\n
*
@param
{Object}
option
Some
option
gave
in
parse()\n
*/\n
//
this.onParseStart =
emptyFunction;\n
\n
query_class_dict.complex =
ComplexQuery;\n
/**\n
*
Called
when
parsing
a
simple
query.
Must
be
overridden!\n
*\n
*
@method
onParseSimpleQuery\n
*
@param
{Object}
object
The
object
shared
in
the
parse
process\n
*
@param
{Object}
option
Some
option
gave
in
parse()\n
*/\n
//
this.onParseSimpleQuery =
emptyFunction;\n
\n
window.ComplexQuery =
ComplexQuery;\n
;/*jslint
indent:
2,
maxlen:
80,
sloppy:
true,
nomen:
true
*/\n
/*global
window,
ComplexQuery,
SimpleQuery,
Query,
parseStringToObject,\n
query_class_dict
*/\n
/**\n
*
Called
when
parsing
a
complex
query.
Must
be
overridden!\n
*\n
*
@method
onParseComplexQuery\n
*
@param
{Object}
object
The
object
shared
in
the
parse
process\n
*
@param
{Object}
option
Some
option
gave
in
parse()\n
*/\n
//
this.onParseComplexQuery =
emptyFunction;\n
\n
/**\n
*
Provides
static
methods
to
create
Query
object
\n
*\n
*
@class
QueryFactory
\n
*/
\n
function
QueryFactory()
{
\n
return;
\n
}
\n
/**\n
*
Called
after
parsing
the
query.
Must
be
overridden!
\n
*\n
*
@method
onParseEnd
\n
*
@param
{Object}
object
The
object
shared
in
the
parse
process
\n
*
@param
{Object}
option
Some
option
gave
in
parse()
\n
*/
\n
//
this.onParseEnd =
emptyFunction;
\n
\n
/**\n
*
Creates
Query
object
from
a
search
text
string
or
a
serialized
version\n
*
of
a
Query.\n
*\n
*
@method
create\n
*
@static\n
*
@param
{Object,String}
object
The
search
text
or
the
serialized
version\n
*
of
a
Query\n
*
@return
{Query}
A
Query
object\n
*/\n
QueryFactory.create =
function
(object,
key_schema)
{\n
if
(
object =
==
"")
{\n
return
new
Query();\n
return;\n
}\n
if
(typeof
object =
==
"string")
{\n
object =
parseStringToObject(object);\n
}\n
if
(typeof
(object
||
{})
.type =
==
"string"
&&\n
query_class_dict[object.type])
{\n
return
new
query_class_dict[object.type](object,
key_schema);\n
}\n
throw
new
TypeError("QueryFactory.create():
"
+\n
"Argument
1
is
not
a
search
text
or
a
parsable
object");\n
};\n
\n
window.QueryFactory =
QueryFactory;\n
;/*jslint
indent:
2,
maxlen:
80,
sloppy:
true,
nomen:
true
*/\n
/*global
Query,
exports
*/\n
\n
function
objectToSearchText(query)
{\n
var
str_list =
[];\n
if
(
query.type =
==
"complex")
{\n
str_list.push("(");\n
(query.query_list
||
[]).forEach(function
(sub_query)
{\n
str_list.push(objectToSearchText(sub_query));\n
str_list.push(query.operator);\n
});\n
str_list.length
-=
1;\n
str_list.push(")");\n
return
str_list.join("
");\n
}\n
if
(
query.type =
==
"simple")
{\n
return
(query.key
?
query.key
+
":
"
:
"")
+\n
(query.operator
||
"")
+
\'
"\'
+
query.value
+
\'"\';\n
}\n
throw
new
TypeError("This
object
is
not
a
query");\n
}\n
Query.objectToSearchText =
objectToSearchText;\n
;/*jslint
indent:
2,
maxlen:
80,
sloppy:
true,
nomen:
true
*/\n
/*global
Query,
inherits,
query_class_dict,
window,\n
searchTextToRegExp,
RSVP
*/\n
\n
var
checkKeySchema =
function
(key_schema)
{\n
var
prop;\n
\n
if
(key_schema
!==
undefined)
{\n
if
(typeof
key_schema
!==
\'object\')
{\n
throw
new
TypeError("SimpleQuery().create():
"
+\n
"key_schema
is
not
of
type
\'object\'");\n
}\n
//
key_set
is
mandatory\n
if
(
key_schema.key_set =
==
undefined)
{\n
throw
new
TypeError("SimpleQuery().create():
"
+\n
"key_schema
has
no
\'key_set\'
property");\n
}\n
for
(prop
in
key_schema)
{\n
if
(key_schema.hasOwnProperty(prop))
{\n
switch
(prop)
{\n
case
\'key_set\':\n
case
\'cast_lookup\':\n
case
\'match_lookup\':\n
break;\n
default:\n
throw
new
TypeError("SimpleQuery().create():
"
+\n
"key_schema
has
unknown
property
\'"
+
prop
+
"\'");\n
}\n
/**\n
*
Filter
the
item
list
with
matching
item
only\n
*\n
*
@method
exec\n
*
@param
{Array}
item_list
The
list
of
object\n
*
@param
{Object}
[option]
Some
operation
option\n
*
@param
{Array}
[option.select_list]
A
object
keys
to
retrieve\n
*
@param
{Array}
[option.sort_on]
Couples
of
object
keys
and
"ascending"\n
*
or
"descending"\n
*
@param
{Array}
[option.limit]
Couple
of
integer,
first
is
an
index
and\n
*
second
is
the
length.\n
*/\n
Query.prototype.exec =
function
(item_list,
option)
{\n
if
(!Array.isArray(item_list))
{\n
throw
new
TypeError("Query().exec():
Argument
1
is
not
of
type
\'array\'");\n
}\n
if
(
option =
==
undefined)
{\n
option =
{};\n
}\n
if
(typeof
option
!==
\'object\')
{\n
throw
new
TypeError("Query().exec():
"
+\n
"Optional
argument
2
is
not
of
type
\'object\'");\n
}\n
var
context =
this,\n
i;\n
for
(
i =
item_list.length
-
1;
i
>
= 0; i -= 1) {\n
if (!context.match(item_list[i])) {\n
item_list.splice(i, 1);\n
}\n
}\n
}\n
};\n
\n
if (option.sort_on) {\n
sortOn(option.sort_on, item_list);\n
}\n
\n
/**\n
*
The
SimpleQuery
inherits
from
Query,
and
compares
one
metadata
value\n
*\n
*
@class
SimpleQuery\n
*
@extends
Query\n
*
@param
{Object}
[
spec=
{}]
The
specifications\n
*
@param
{String}
[
spec.operator=
"="
]
The
compare
method
to
use\n
*
@param
{String}
spec.key
The
metadata
key\n
*
@param
{String}
spec.value
The
value
of
the
metadata
to
compare\n
*/\n
function
SimpleQuery(spec,
key_schema)
{\n
Query.call(this);\n
if (option.limit) {\n
limit(option.limit, item_list);\n
}\n
\n
checkKeySchema(key_schema
);\n
select(option.select_list || [], item_list
);\n
\n
this._key_schema =
key_schema
||
{};\n
return new RSVP.Queue()\n
.push(function () {\n
return item_list;\n
});\n
};\n
\n
/**\n
*
Operator
to
use
to
compare
object
values
\n
*
Test if an item matches this query
\n
*\n
*
@
attribute
operator
\n
*
@
type
String
\n
*
@
optional
\n
* @
method match
\n
* @
param {Object} item The object to test
\n
* @
return {Boolean} true if match, false otherwise
\n
*/\n
this.operator =
spec.operator;\n
Query.prototype.match = function () {\n
return true;\n
};\n
\n
/**\n
*
Key
of
the
object
which
refers
to
the
value
to
compare
\n
*
Browse the Query in deep calling parser method in each step.
\n
*\n
*
@attribute
key\n
*
@type
String\n
* `onParseStart` is called first, on end `onParseEnd` is called.\n
* It starts from the simple queries at the bottom of the tree calling the\n
* parser method `onParseSimpleQuery`, and go up calling the\n
* `onParseComplexQuery` method.\n
*\n
* @method parse\n
* @param {Object} option Any options you want (except \'parsed\')\n
* @return {Any} The parse result\n
*/\n
this.key =
spec.key;\n
Query.prototype.parse = function (option) {\n
var that = this,\n
object;\n
/**\n
* The recursive parser.\n
*\n
* @param {Object} object The object shared in the parse process\n
* @param {Object} options Some options usable in the parseMethods\n
* @return {Any} The parser result\n
*/\n
function recParse(object, option) {\n
var query = object.parsed,\n
queue = new RSVP.Queue(),\n
i;\n
\n
function enqueue(j) {\n
queue\n
.push(function () {\n
object.parsed = query.query_list[j];\n
return recParse(object, option);\n
})\n
.push(function () {\n
query.query_list[j] = object.parsed;\n
});\n
}\n
\n
if (query.type === "complex") {\n
\n
\n
for (i = 0; i
< query.query_list.length
;
i
+=
1)
{\n
enqueue(i);\n
}\n
\n
return
queue\n
.push(function
()
{\n
object.parsed =
query;\n
return
that.onParseComplexQuery(object,
option);\n
});\n
\n
}\n
if
(
query.type =
==
"simple")
{\n
return
that.onParseSimpleQuery(object,
option);\n
}\n
}\n
object =
{\n
parsed:
JSON.parse(JSON.stringify(that.serialized()))\n
};\n
return
new
RSVP.Queue()\n
.push(function
()
{\n
return
that.onParseStart(object,
option);\n
})\n
.push(function
()
{\n
return
recParse(object,
option);\n
})\n
.push(function
()
{\n
return
that.onParseEnd(object,
option);\n
})\n
.push(function
()
{\n
return
object.parsed;\n
});\n
\n
};\n
\n
/**\n
*
Value
is
used
to
do
the
comparison
with
the
object
value
\n
*
Convert
this
query
to
a
parsable
string.
\n
*\n
*
@
attribute
value
\n
*
@
type
String
\n
*
@
method
toString
\n
*
@
return
{String}
The
string
version
of
this
query
\n
*/\n
this.value =
spec.value;\n
\n
}\n
inherits(SimpleQuery,
Query);\n
Query.prototype.toString =
function
()
{\n
return
"";\n
};\n
\n
SimpleQuery.prototype.type =
"simple"
;\n
/**\n
*
Convert
this
query
to
an
jsonable
object
in
order
to
be
remake
thanks
to\n
*
QueryFactory
class.\n
*\n
*
@method
serialized\n
*
@return
{Object}
The
jsonable
object\n
*/\n
Query.prototype.serialized =
function
()
{\n
return
undefined;\n
};\n
\n
var
checkKey =
function
(key)
{\n
var
prop;\n
/**\n
*
Provides
static
methods
to
create
Query
object\n
*\n
*
@class
QueryFactory\n
*/\n
function
QueryFactory()
{\n
return;\n
}\n
\n
if
(
key.read_from =
==
undefined)
{\n
throw
new
TypeError("Custom
key
is
missing
the
read_from
property");\n
/**\n
*
Escapes
regexp
special
chars
from
a
string.\n
*\n
*
@param
{String}
string
The
string
to
escape\n
*
@return
{String}
The
escaped
string\n
*/\n
function
stringEscapeRegexpCharacters(string)
{\n
return
string.replace(regexp_escape,
"\\\\$&");\n
}\n
\n
for
(prop
in
key)
{\n
if
(key.hasOwnProperty(prop))
{\n
switch
(prop)
{\n
case
\'read_from\':\n
case
\'cast_to\':\n
case
\'equal_match\':\n
break;\n
default:\n
throw
new
TypeError("Custom
key
has
unknown
property
\'"
+\n
prop
+
"\'");\n
/**\n
*
Inherits
the
prototype
methods
from
one
constructor
into
another.
The\n
*
prototype
of
`constructor`
will
be
set
to
a
new
object
created
from\n
*
`superConstructor`.\n
*\n
*
@param
{Function}
constructor
The
constructor
which
inherits
the
super
one\n
*
@param
{Function}
superConstructor
The
super
constructor\n
*/\n
function
inherits(constructor,
superConstructor)
{\n
constructor.super_ =
superConstructor;\n
constructor.prototype =
Object.create(superConstructor.prototype,
{\n
"constructor":
{\n
"configurable":
true,\n
"enumerable":
false,\n
"writable":
true,\n
"value":
constructor\n
}\n
}\n
}
);
\n
}\n
};\n
\n
\n
/**\n
*
#crossLink
"Query/match:method"\n
*/\n
SimpleQuery.prototype.match =
function
(item)
{\n
var
object_value =
null,\n
equal_match =
null,\n
cast_to =
null,\n
matchMethod =
null,\n
operator =
this.operator,\n
value =
null,\n
key =
this.key;\n
\n
/*jslint
regexp:
true
*/\n
if
(!(/^(?:!?=|<=?|
>
=?)$/i.test(operator))) {\n
// `operator` is not correct, we have to change it to "like" or "="\n
if (/%/.test(this.value)) {\n
// `value` contains a non escaped `%`\n
operator = "like";\n
} else {\n
// `value` does not contain non escaped `%`\n
operator = "=";\n
/**\n
*
Convert
a
search
text
to
a
regexp.\n
*\n
*
@param
{String}
string
The
string
to
convert\n
*
@param
{Boolean}
[
use_wildcard_character=
true]
Use
wildcard
"%"
and
"_"\n
*
@return
{RegExp}
The
search
text
regexp\n
*/\n
function
searchTextToRegExp(string,
use_wildcard_characters)
{\n
if
(typeof
string
!==
\'string\')
{\n
throw
new
TypeError("jioquery.searchTextToRegExp():
"
+\n
"Argument
1
is
not
of
type
\'string\'");\n
}\n
if
(
use_wildcard_characters =
==
false)
{\n
return
new
RegExp("^"
+
stringEscapeRegexpCharacters(string)
+
"$");\n
}\n
return
new
RegExp("^"
+
stringEscapeRegexpCharacters(string)\n
.replace(regexp_percent,
\'.*\')\n
.replace(regexp_underscore,
\'.\')
+
"$");\n
}\n
\n
matchMethod = this[operator];\n
/**\n
*
The
ComplexQuery
inherits
from
Query,
and
compares
one
or
several
metadata\n
*
values.\n
*\n
*
@class
ComplexQuery\n
*
@extends
Query\n
*
@param
{Object}
[
spec=
{}]
The
specifications\n
*
@param
{String}
[
spec.operator=
"AND"
]
The
compare
method
to
use\n
*
@param
{String}
spec.key
The
metadata
key\n
*
@param
{String}
spec.value
The
value
of
the
metadata
to
compare\n
*/\n
function
ComplexQuery(spec,
key_schema)
{\n
Query.call(this);\n
\n
if (this._key_schema.key_set
&&
this._key_schema.key_set[key] !== undefined) {\n
key = this._key_schema.key_set[key];\n
}\n
/**\n
*
Logical
operator
to
use
to
compare
object
values\n
*\n
*
@attribute
operator\n
*
@type
String\n
*
@default
"AND"\n
*
@optional\n
*/\n
this.operator =
spec.operator;\n
\n
/**\n
*
The
sub
Query
list
which
are
used
to
query
an
item.\n
*\n
*
@attribute
query_list\n
*
@type
Array\n
*
@default
[]\n
*
@optional\n
*/\n
this.query_list =
spec.query_list
||
[];\n
this.query_list =
this.query_list.map(\n
//
decorate
the
map
to
avoid
sending
the
index
as
key_schema
argument\n
function
(o)
{
return
QueryFactory.create(o,
key_schema);
}\n
);\n
\n
if (typeof key === \'object\') {\n
checkKey(key);\n
object_value = item[key.read_from];\n
}\n
inherits(ComplexQuery,
Query);\n
\n
equal_match = key.equal_match;\n
ComplexQuery.prototype.operator =
"AND"
;\n
ComplexQuery.prototype.type =
"complex"
;\n
\n
// equal_match can be a string\n
if (typeof equal_match === \'string\') {\n
// XXX raise error if equal_match not in match_lookup\n
equal_match = this._key_schema.match_lookup[equal_match];\n
/**\n
*
#crossLink
"Query/match:method"\n
*/\n
ComplexQuery.prototype.match =
function
(item)
{\n
var
operator =
this.operator;\n
if
(!(regexp_operator.test(operator)))
{\n
operator =
"AND"
;\n
}\n
return
this[operator.toUpperCase()](item);\n
};\n
\n
/**\n
*
#crossLink
"Query/toString:method"\n
*/\n
ComplexQuery.prototype.toString =
function
()
{\n
var
str_list =
[],
this_operator =
this.operator;\n
if
(
this.operator =
==
"NOT")
{\n
str_list.push("NOT
(");\n
str_list.push(this.query_list[0].toString());\n
str_list.push(")");\n
return
str_list.join("
");\n
}\n
this.query_list.forEach(function
(query)
{\n
str_list.push("(");\n
str_list.push(query.toString());\n
str_list.push(")");\n
str_list.push(this_operator);\n
});\n
str_list.length
-=
1;\n
return
str_list.join("
");\n
};\n
\n
/**\n
*
#crossLink
"Query/serialized:method"\n
*/\n
ComplexQuery.prototype.serialized =
function
()
{\n
var
s =
{\n
"type":
"complex",\n
"operator":
this.operator,\n
"query_list":
[]\n
};\n
this.query_list.forEach(function
(query)
{\n
s.query_list.push(\n
typeof
query.toJSON =
==
"function"
?
query.toJSON()
:
query\n
);\n
});\n
return
s;\n
};\n
ComplexQuery.prototype.toJSON =
ComplexQuery.prototype.serialized;\n
\n
/**\n
*
Comparison
operator,
test
if
all
sub
queries
match
the\n
*
item
value\n
*\n
*
@method
AND\n
*
@param
{Object}
item
The
item
to
match\n
*
@return
{Boolean}
true
if
all
match,
false
otherwise\n
*/\n
ComplexQuery.prototype.AND =
function
(item)
{\n
var
result =
true,\n
i =
0;\n
\n
// equal_match overrides the default \'=\' operator\n
if (equal_match !== undefined) {\n
matchMethod = (operator === "=" || operator === "like" ?\n
equal_match : matchMethod);\n
while
(result
&&
(i
!==
this.query_list.length))
{\n
result =
this.query_list[i].match(item);\n
i
+=
1;\n
}\n
return
result;\n
\n
value = this.value;\n
cast_to = key.cast_to;\n
if (cast_to) {\n
// cast_to can be a string\n
if (typeof cast_to === \'string\') {\n
// XXX raise error if cast_to not in cast_lookup\n
cast_to = this._key_schema.cast_lookup[cast_to];\n
}\n
};\n
\n
try {\n
value = cast_to(value);\n
} catch (e) {\n
value = undefined;\n
}\n
/**\n
*
Comparison
operator,
test
if
one
of
the
sub
queries
matches
the\n
*
item
value\n
*\n
*
@method
OR\n
*
@param
{Object}
item
The
item
to
match\n
*
@return
{Boolean}
true
if
one
match,
false
otherwise\n
*/\n
ComplexQuery.prototype.OR =
function
(item)
{\n
var
result =
false,\n
i =
0;\n
\n
try {\n
object_value = cast_to(object_value);\n
} catch (e) {\n
object_value = undefined;\n
}\n
while
((!result)
&&
(i
!==
this.query_list.length))
{\n
result =
this.query_list[i].match(item);\n
i
+=
1;\n
}\n
} else {\n
object_value = item[key];\n
value = this.value;\n
}\n
if (object_value === undefined || value === undefined) {\n
return RSVP.resolve(false);\n
}\n
return matchMethod(object_value, value);\n
};\n
\n
/**\n
* #crossLink "Query/toString:method"\n
*/\n
SimpleQuery.prototype.toString = function () {\n
return (this.key ? this.key + ":" : "") +\n
(this.operator ? " " + this.operator : "") + \' "\' + this.value + \'"\';\n
};\n
return
result;\n
};\n
\n
/**\n
* #crossLink "Query/serialized:method"\n
*/\n
SimpleQuery.prototype.serialized = function () {\n
var object = {\n
"type": "simple",\n
"key": this.key,\n
"value": this.value\n
};\n
if (this.operator !== undefined) {\n
object.operator = this.operator;\n
}\n
return object;\n
};\n
SimpleQuery.prototype.toJSON = SimpleQuery.prototype.serialized;\n
/**\n
*
Comparison
operator,
test
if
the
sub
query
does
not
match
the\n
*
item
value\n
*\n
*
@method
NOT\n
*
@param
{Object}
item
The
item
to
match\n
*
@return
{Boolean}
true
if
one
match,
false
otherwise\n
*/\n
ComplexQuery.prototype.NOT =
function
(item)
{\n
return
!this.query_list[0].match(item);\n
};\n
\n
/**\n
* Comparison operator, test if this query value matches the item value\n
*\n
* @method =\n
* @param {String} object_value The value to compare\n
* @param {String} comparison_value The comparison value\n
* @return {Boolean} true if match, false otherwise\n
*/\n
SimpleQuery.prototype["="] = function (object_value, comparison_value) {\n
var value, i;\n
if (!Array.isArray(object_value)) {\n
object_value = [object_value];\n
}\n
for (i = 0; i
< object_value.length
;
i
+=
1)
{\n
value =
object_value[i];\n
if
(typeof
value =
==
\'object\'
&&
value.hasOwnProperty(\'content\'))
{\n
value =
value.content;\n
/**\n
*
Creates
Query
object
from
a
search
text
string
or
a
serialized
version\n
*
of
a
Query.\n
*\n
*
@method
create\n
*
@static\n
*
@param
{Object,String}
object
The
search
text
or
the
serialized
version\n
*
of
a
Query\n
*
@return
{Query}
A
Query
object\n
*/\n
QueryFactory.create =
function
(object,
key_schema)
{\n
if
(
object =
==
"")
{\n
return
new
Query();\n
}\n
if
(typeof
value.cmp =
==
"function
")
{\n
return
RSVP.resolve(value.cmp(comparison_value)
===
0
);\n
if
(typeof
object =
==
"string
")
{\n
object =
parseStringToObject(object
);\n
}\n
if
(\n
searchTextToRegExp(comparison_value.toString(),
false).\n
test(value.toString())\n
)
{\n
return
RSVP.resolve(true);\n
if
(typeof
(object
||
{})
.type =
==
"string"
&&\n
query_class_dict[object.type])
{\n
return
new
query_class_dict[object.type](object,
key_schema);\n
}\n
}
\n
return
RSVP.resolve(false
);\n
};\n
throw
new
TypeError("QueryFactory.create():
"
+
\n
"Argument
1
is
not
a
search
text
or
a
parsable
object"
);\n
};\n
\n
/**\n
*
Comparison
operator,
test
if
this
query
value
matches
the
item
value\n
*\n
*
@method
like\n
*
@param
{String}
object_value
The
value
to
compare\n
*
@param
{String}
comparison_value
The
comparison
value\n
*
@return
{Boolean}
true
if
match,
false
otherwise\n
*/\n
SimpleQuery.prototype.like =
function
(object_value,
comparison_value)
{\n
var
value,
i;\n
if
(!Array.isArray(object_value))
{\n
object_value =
[object_value];\n
}\n
for
(
i =
0;
i
<
object_value.length;
i
+=
1)
{\n
value =
object_value[i];\n
if
(typeof
value =
==
\'object\'
&&
value.hasOwnProperty(\'content\'))
{\n
value =
value.content;\n
function
objectToSearchText(query)
{\n
var
str_list =
[];\n
if
(
query.type =
==
"complex")
{\n
str_list.push("(");\n
(query.query_list
||
[]).forEach(function
(sub_query)
{\n
str_list.push(objectToSearchText(sub_query));\n
str_list.push(query.operator);\n
});\n
str_list.length
-=
1;\n
str_list.push(")");\n
return
str_list.join("
");\n
}\n
if
(typeof
value.cmp =
==
"function")
{\n
return
RSVP.resolve(value.cmp(comparison_value)
===
0);\n
if
(
query.type =
==
"simple")
{\n
return
(query.key
?
query.key
+
":
"
:
"")
+\n
(query.operator
||
"")
+
\'
"\'
+
query.value
+
\'"\';\n
}\n
if
(\n
searchTextToRegExp(comparison_value.toString()).test(value.toString())\n
)
{\n
return
RSVP.resolve(true);\n
throw
new
TypeError("This
object
is
not
a
query");\n
}\n
\n
function
checkKeySchema(key_schema)
{\n
var
prop;\n
\n
if
(key_schema
!==
undefined)
{\n
if
(typeof
key_schema
!==
\'object\')
{\n
throw
new
TypeError("SimpleQuery().create():
"
+\n
"key_schema
is
not
of
type
\'object\'");\n
}\n
//
key_set
is
mandatory\n
if
(
key_schema.key_set =
==
undefined)
{\n
throw
new
TypeError("SimpleQuery().create():
"
+\n
"key_schema
has
no
\'key_set\'
property");\n
}\n
for
(prop
in
key_schema)
{\n
if
(key_schema.hasOwnProperty(prop))
{\n
switch
(prop)
{\n
case
\'key_set\':\n
case
\'cast_lookup\':\n
case
\'match_lookup\':\n
break;\n
default:\n
throw
new
TypeError("SimpleQuery().create():
"
+\n
"key_schema
has
unknown
property
\'"
+
prop
+
"\'");\n
}\n
}\n
}\n
}\n
}\n
return
RSVP.resolve(false);\n
};\n
\n
/**\n
*
Comparison
operator,
test
if
this
query
value
does
not
match
the
item
value\n
*\n
*
@method
!=\n
*
@param
{String}
object_value
The
value
to
compare\n
*
@param
{String}
comparison_value
The
comparison
value\n
*
@return
{Boolean}
true
if
not
match,
false
otherwise\n
*/\n
SimpleQuery.prototype["!="]
=
function
(object_value,
comparison_value)
{\n
var
value,
i;\n
if
(!Array.isArray(object_value))
{\n
object_value =
[object_value];\n
/**\n
*
The
SimpleQuery
inherits
from
Query,
and
compares
one
metadata
value\n
*\n
*
@class
SimpleQuery\n
*
@extends
Query\n
*
@param
{Object}
[
spec=
{}]
The
specifications\n
*
@param
{String}
[
spec.operator=
"="
]
The
compare
method
to
use\n
*
@param
{String}
spec.key
The
metadata
key\n
*
@param
{String}
spec.value
The
value
of
the
metadata
to
compare\n
*/\n
function
SimpleQuery(spec,
key_schema)
{\n
Query.call(this);\n
\n
checkKeySchema(key_schema);\n
\n
this._key_schema =
key_schema
||
{};\n
\n
/**\n
*
Operator
to
use
to
compare
object
values\n
*\n
*
@attribute
operator\n
*
@type
String\n
*
@optional\n
*/\n
this.operator =
spec.operator;\n
\n
/**\n
*
Key
of
the
object
which
refers
to
the
value
to
compare\n
*\n
*
@attribute
key\n
*
@type
String\n
*/\n
this.key =
spec.key;\n
\n
/**\n
*
Value
is
used
to
do
the
comparison
with
the
object
value\n
*\n
*
@attribute
value\n
*
@type
String\n
*/\n
this.value =
spec.value;\n
\n
}\n
for
(
i =
0;
i
<
object_value.length;
i
+=
1)
{\n
value =
object_value[i];\n
if
(typeof
value =
==
\'object\'
&&
value.hasOwnProperty(\'content\'))
{\n
value =
value.content;\n
}\n
if
(typeof
value.cmp =
==
"function")
{\n
return
RSVP.resolve(value.cmp(comparison_value)
!==
0);\n
inherits(SimpleQuery,
Query);\n
\n
SimpleQuery.prototype.type =
"simple"
;\n
\n
function
checkKey(key)
{\n
var
prop;\n
\n
if
(
key.read_from =
==
undefined)
{\n
throw
new
TypeError("Custom
key
is
missing
the
read_from
property");\n
}\n
if
(\n
searchTextToRegExp(comparison_value.toString(),
false).\n
test(value.toString())\n
)
{\n
return
RSVP.resolve(false);\n
\n
for
(prop
in
key)
{\n
if
(key.hasOwnProperty(prop))
{\n
switch
(prop)
{\n
case
\'read_from\':\n
case
\'cast_to\':\n
case
\'equal_match\':\n
break;\n
default:\n
throw
new
TypeError("Custom
key
has
unknown
property
\'"
+\n
prop
+
"\'");\n
}\n
}\n
}\n
}\n
return
RSVP.resolve(true);\n
};\n
\n
/**\n
*
Comparison
operator,
test
if
this
query
value
is
lower
than
the
item
value
\n
*
\n
*
@method
<
\n
*
@param
{Number,
String}
object_value
The
value
to
compare
\n
*
@param
{Number,
String}
comparison_value
The
comparison
value
\n
*
@return
{Boolean}
true
if
lower,
false
otherwise
\n
*/
\n
SimpleQuery.prototype["<"]
=
function
(object_value,
comparison_value)
{
\n
var
value;
\n
if
(!Array.isArray(object_value))
{
\n
object_value =
[object_value];
\n
}
\n
value =
object_value[0];
\n
if
(typeof
value =
==
\'object\'
&&
value.hasOwnProperty(\'content\'
))
{\n
value =
value.content;
\n
}
\n
if
(typeof
value.cmp =
==
"function")
{\n
return
RSVP.resolve(value.cmp(comparison_value)
<
0);
\n
}
\n
return
RSVP.resolve(value
<
comparison_value);
\n
};
\n
/**\n
*
#crossLink
"Query/match:method"
\n
*/
\n
SimpleQuery.prototype.match =
function
(item)
{
\n
var
object_value =
null,
\n
equal_match =
null,
\n
cast_to =
null,
\n
matchMethod =
null,
\n
operator =
this.operator,
\n
value =
null,
\n
key =
this.key;
\n
\n
if
(!(regexp_comparaison.test(operator)))
{
\n
//
`operator`
is
not
correct,
we
have
to
change
it
to
"like"
or
"="
\n
if
(regexp_percent.test(this.value
))
{\n
//
`value`
contains
a
non
escaped
`%`
\n
operator =
"like"
;
\n
}
else
{\n
//
`value`
does
not
contain
non
escaped
`%`
\n
operator =
"="
;
\n
}
\n
}
\n
\n
/**\n
*
Comparison
operator,
test
if
this
query
value
is
equal
or
lower
than
the\n
*
item
value\n
*\n
*
@method
<=\n
*
@param
{Number,
String}
object_value
The
value
to
compare\n
*
@param
{Number,
String}
comparison_value
The
comparison
value\n
*
@return
{Boolean}
true
if
equal
or
lower,
false
otherwise\n
*/\n
SimpleQuery.prototype["<="]
=
function
(object_value,
comparison_value)
{\n
var
value;\n
if
(!Array.isArray(object_value))
{\n
object_value =
[object_value];\n
}\n
value =
object_value[0];\n
if
(typeof
value =
==
\'object\'
&&
value.hasOwnProperty(\'content\'))
{\n
value =
value.content;\n
}\n
if
(typeof
value.cmp =
==
"function")
{\n
return
RSVP.resolve(value.cmp(comparison_value)
<=
0);\n
}\n
return
RSVP.resolve(value
<=
comparison_value);\n
};\n
matchMethod =
this[operator];\n
\n
/**\n
*
Comparison
operator,
test
if
this
query
value
is
greater
than
the
item\n
*
value\n
*\n
*
@method
>
\n
* @param {Number, String} object_value The value to compare\n
* @param {Number, String} comparison_value The comparison value\n
* @return {Boolean} true if greater, false otherwise\n
*/\n
SimpleQuery.prototype[">"] = function (object_value, comparison_value) {\n
var value;\n
if (!Array.isArray(object_value)) {\n
object_value = [object_value];\n
}\n
value = object_value[0];\n
if (typeof value === \'object\'
&&
value.hasOwnProperty(\'content\')) {\n
value = value.content;\n
}\n
if (typeof value.cmp === "function") {\n
return RSVP.resolve(value.cmp(comparison_value) > 0);\n
}\n
return RSVP.resolve(value > comparison_value);\n
};\n
if
(this._key_schema.key_set
&&
this._key_schema.key_set[key]
!==
undefined)
{\n
key =
this._key_schema.key_set[key];\n
}\n
\n
/**\n
* Comparison operator, test if this query value is equal or greater than the\n
* item value\n
*\n
* @method >=\n
* @param {Number, String} object_value The value to compare\n
* @param {Number, String} comparison_value The comparison value\n
* @return {Boolean} true if equal or greater, false otherwise\n
*/\n
SimpleQuery.prototype[">="] = function (object_value, comparison_value) {\n
var value;\n
if (!Array.isArray(object_value)) {\n
object_value = [object_value];\n
}\n
value = object_value[0];\n
if (typeof value === \'object\'
&&
value.hasOwnProperty(\'content\')) {\n
value = value.content;\n
}\n
if (typeof value.cmp === "function") {\n
return RSVP.resolve(value.cmp(comparison_value) >= 0);\n
}\n
return RSVP.resolve(value >= comparison_value);\n
};\n
if
(typeof
key =
==
\'object\')
{\n
checkKey(key);\n
object_value =
item[key.read_from];\n
\n
query_class_dict.simple = SimpleQuery
;\n
equal_match =
key.equal_match
;\n
\n
window.SimpleQuery = SimpleQuery;\n
;/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
/*global Query, RSVP, deepClone */\n
//
equal_match
can
be
a
string\n
if
(typeof
equal_match =
==
\'string\')
{\n
//
XXX
raise
error
if
equal_match
not
in
match_lookup\n
equal_match =
this._key_schema.match_lookup[equal_match];\n
}\n
\n
/**\n
* Escapes regexp special chars from a string.\n
*\n
* @param {String} string The string to escape\n
* @return {String} The escaped string\n
*/\n
function stringEscapeRegexpCharacters(string) {\n
if (typeof string === "string") {\n
return string.replace(/([\\\\\\.\\$\\[\\]\\(\\)\\{\\}\\^\\?\\*\\+\\-])/g, "\\\\$1");\n
}\n
throw new TypeError("Query.stringEscapeRegexpCharacters(): " +\n
"Argument no 1 is not of type \'string\'");\n
}\n
//
equal_match
overrides
the
default
\'=\'
operator\n
if
(equal_match
!==
undefined)
{\n
matchMethod =
(operator
===
"="
||
operator =
==
"like"
?\n
equal_match
:
matchMethod);\n
}\n
\n
Query.stringEscapeRegexpCharacters = stringEscapeRegexpCharacters;\n
value =
this.value;\n
cast_to =
key.cast_to;\n
if
(cast_to)
{\n
//
cast_to
can
be
a
string\n
if
(typeof
cast_to =
==
\'string\')
{\n
//
XXX
raise
error
if
cast_to
not
in
cast_lookup\n
cast_to =
this._key_schema.cast_lookup[cast_to];\n
}\n
\n
/**\n
* Convert metadata values to array of strings. ex:\n
*\n
* "a" -> ["a"],\n
* {"content": "a"} -> ["a"]\n
*\n
* @param {Any} value The metadata value\n
* @return {Array} The value in string array format\n
*/\n
function metadataValueToStringArray(value) {\n
var i, new_value = [];\n
if (value === undefined) {\n
return undefined;\n
}\n
if (!Array.isArray(value)) {\n
value = [value];\n
}\n
for (i = 0; i
< value.length
;
i
+=
1)
{\n
if
(typeof
value[i]
===
\'object\')
{\n
new_value[i]
=
value[i].content;\n
try
{\n
value =
cast_to(value);\n
}
catch
(e)
{\n
value =
undefined;\n
}\n
\n
try
{\n
object_value =
cast_to(object_value);\n
}
catch
(e)
{\n
object_value =
undefined;\n
}\n
}\n
}
else
{\n
new_value[i]
=
value[i];\n
object_value =
item[key];\n
value =
this.value;\n
}\n
}\n
return
new_value;\n
}\n
if
(
object_value =
==
undefined
||
value =
==
undefined)
{\n
return
false;\n
}\n
return
matchMethod(object_value,
value);\n
};\n
\n
/**\n
*
A
sort
function
to
sort
items
by
key\n
*\n
*
@param
{String}
key
The
key
to
sort
on\n
*
@param
{String}
[
way=
"ascending"
]
\'ascending\'
or
\'descending\'\n
*
@return
{Function}
The
sort
function\n
*/\n
function
sortFunction(key,
way)
{\n
var
result;\n
if
(
way =
==
\'descending\')
{\n
result =
1;\n
}
else
if
(
way =
==
\'ascending\')
{\n
result =
-1;\n
}
else
{\n
throw
new
TypeError("Query.sortFunction():
"
+\n
"Argument
2
must
be
\'ascending\'
or
\'descending\'");\n
}\n
return
function
(a,
b)
{\n
//
this
comparison
is
5
times
faster
than
json
comparison\n
var
i,
l;\n
a =
metadataValueToStringArray(a[key])
||
[];\n
b =
metadataValueToStringArray(b[key])
||
[];\n
l =
a.length
>
b.length ? a.length : b.length;\n
for (i = 0; i
< l
;
i
+=
1)
{\n
if
(a[i]
===
undefined)
{\n
return
result;\n
}\n
if
(b[i]
===
undefined)
{\n
return
-result;\n
/**\n
*
#crossLink
"Query/toString:method"\n
*/\n
SimpleQuery.prototype.toString =
function
()
{\n
return
(this.key
?
this.key
+
":"
:
"")
+\n
(this.operator
?
"
"
+
this.operator
:
"")
+
\'
"\'
+
this.value
+
\'"\';\n
};\n
\n
/**\n
*
#crossLink
"Query/serialized:method"\n
*/\n
SimpleQuery.prototype.serialized =
function
()
{\n
var
object =
{\n
"type":
"simple",\n
"key":
this.key,\n
"value":
this.value\n
};\n
if
(this.operator
!==
undefined)
{\n
object.operator =
this.operator;\n
}\n
return
object;\n
};\n
SimpleQuery.prototype.toJSON =
SimpleQuery.prototype.serialized;\n
\n
/**\n
*
Comparison
operator,
test
if
this
query
value
matches
the
item
value\n
*\n
*
@
method =
\n
*
@param
{String}
object_value
The
value
to
compare\n
*
@param
{String}
comparison_value
The
comparison
value\n
*
@return
{Boolean}
true
if
match,
false
otherwise\n
*/\n
SimpleQuery.prototype["="]
=
function
(object_value,
comparison_value)
{\n
var
value,
i;\n
if
(!Array.isArray(object_value))
{\n
object_value =
[object_value];\n
}\n
for
(
i =
0;
i
<
object_value.length;
i
+=
1)
{\n
value =
object_value[i];\n
if
(typeof
value =
==
\'object\'
&&
value.hasOwnProperty(\'content\'))
{\n
value =
value.content;\n
}\n
if
(
a[i]
>
b[i]
) {\n
return
-result
;\n
if
(
typeof
value.cmp =
==
"function"
)
{\n
return
(value.cmp(comparison_value)
===
0)
;\n
}\n
if (
a[i]
< b
[i]
)
{\n
return
result
;\n
if
(
comparison_value.toString()
===
value.toString()
)
{\n
return
true
;\n
}\n
}\n
return
0
;\n
return
false
;\n
};\n
}\n
\n
/**\n
*
Inherits
the
prototype
methods
from
one
constructor
into
another.
The\n
*
prototype
of
`constructor`
will
be
set
to
a
new
object
created
from\n
*
`superConstructor`.\n
*\n
*
@param
{Function}
constructor
The
constructor
which
inherits
the
super
one\n
*
@param
{Function}
superConstructor
The
super
constructor\n
*/\n
function
inherits(constructor,
superConstructor)
{\n
constructor.super_ =
superConstructor;\n
constructor.prototype =
Object.create(superConstructor.prototype,
{\n
"constructor":
{\n
"configurable":
true,\n
"enumerable":
false,\n
"writable":
true,\n
"value":
constructor\n
/**\n
*
Comparison
operator,
test
if
this
query
value
matches
the
item
value\n
*\n
*
@method
like\n
*
@param
{String}
object_value
The
value
to
compare\n
*
@param
{String}
comparison_value
The
comparison
value\n
*
@return
{Boolean}
true
if
match,
false
otherwise\n
*/\n
SimpleQuery.prototype.like =
function
(object_value,
comparison_value)
{\n
var
value,
i;\n
if
(!Array.isArray(object_value))
{\n
object_value =
[object_value];\n
}\n
for
(
i =
0;
i
<
object_value.length;
i
+=
1)
{\n
value =
object_value[i];\n
if
(typeof
value =
==
\'object\'
&&
value.hasOwnProperty(\'content\'))
{\n
value =
value.content;\n
}\n
if
(typeof
value.cmp =
==
"function")
{\n
return
(value.cmp(comparison_value)
===
0);\n
}\n
if
(\n
searchTextToRegExp(comparison_value.toString()).test(value.toString())\n
)
{\n
return
true;\n
}\n
}\n
});\n
}\n
\n
/**\n
*
Does
nothing\n
*/\n
function
emptyFunction()
{\n
return;\n
}\n
return
false;\n
};\n
\n
/**\n
*
Filter
a
list
of
items,
modifying
them
to
select
only
wanted
keys.
If\n
*
`clone`
is
true,
then
the
method
will
act
on
a
cloned
list.\n
*\n
*
@param
{Array}
select_option
Key
list
to
keep\n
*
@param
{Array}
list
The
item
list
to
filter\n
*
@param
{Boolean}
[
clone=
false]
If
true,
modifies
a
clone
of
the
list\n
*
@return
{Array}
The
filtered
list\n
*/\n
function
select(select_option,
list,
clone)
{\n
var
i,
j,
new_item;\n
if
(!Array.isArray(select_option))
{\n
throw
new
TypeError("jioquery.select():
"
+\n
"Argument
1
is
not
of
type
Array");\n
}\n
if
(!Array.isArray(list))
{\n
throw
new
TypeError("jioquery.select():
"
+\n
"Argument
2
is
not
of
type
Array");\n
}\n
if
(
clone =
==
true)
{\n
list =
deepClone(list);\n
}\n
for
(
i =
0;
i
<
list.length;
i
+=
1)
{\n
new_item =
{};\n
for
(
j =
0;
j
<
select_option.length;
j
+=
1)
{\n
if
(list[i].hasOwnProperty([select_option[j]]))
{\n
new_item[select_option[j]]
=
list[i][select_option[j]];\n
/**\n
*
Comparison
operator,
test
if
this
query
value
does
not
match
the
item
value\n
*\n
*
@method
!=\n
*
@param
{String}
object_value
The
value
to
compare\n
*
@param
{String}
comparison_value
The
comparison
value\n
*
@return
{Boolean}
true
if
not
match,
false
otherwise\n
*/\n
SimpleQuery.prototype["!="]
=
function
(object_value,
comparison_value)
{\n
var
value,
i;\n
if
(!Array.isArray(object_value))
{\n
object_value =
[object_value];\n
}\n
for
(
i =
0;
i
<
object_value.length;
i
+=
1)
{\n
value =
object_value[i];\n
if
(typeof
value =
==
\'object\'
&&
value.hasOwnProperty(\'content\'))
{\n
value =
value.content;\n
}\n
}
\n
for
(j
in
new_item)
{
\n
if
(new_item.hasOwnProperty(j))
{
\n
list[i]
=
new_item;
\n
break
;\n
if
(typeof
value.cmp =
==
"function")
{
\n
return
(value.cmp(comparison_value)
!==
0);
\n
}
\n
if
(comparison_value.toString()
===
value.toString())
{
\n
return
false
;\n
}\n
}\n
}\n
return
list;\n
}\n
return
true;\n
};\n
\n
Query.select =
select;\n
/**\n
*
Comparison
operator,
test
if
this
query
value
is
lower
than
the
item
value\n
*\n
*
@method
<\n
*
@param
{Number,
String}
object_value
The
value
to
compare\n
*
@param
{Number,
String}
comparison_value
The
comparison
value\n
*
@return
{Boolean}
true
if
lower,
false
otherwise\n
*/\n
SimpleQuery.prototype["<"]
=
function
(object_value,
comparison_value)
{\n
var
value;\n
if
(!Array.isArray(object_value))
{\n
object_value =
[object_value];\n
}\n
value =
object_value[0];\n
if
(typeof
value =
==
\'object\'
&&
value.hasOwnProperty(\'content\'))
{\n
value =
value.content;\n
}\n
if
(typeof
value.cmp =
==
"function")
{\n
return
(value.cmp(comparison_value)
<
0);\n
}\n
return
(value
<
comparison_value);\n
};\n
\n
/**\n
*
Sort
a
list
of
items,
according
to
keys
and
directions.
If
`clone`
is
true,\n
*
then
the
method
will
act
on
a
cloned
list.\n
*\n
*
@param
{Array}
sort_on_option
List
of
couples
[key,
direction]\n
*
@param
{Array}
list
The
item
list
to
sort\n
*
@param
{Boolean}
[
clone=
false]
If
true,
modifies
a
clone
of
the
list\n
*
@return
{Array}
The
filtered
list\n
*/\n
function
sortOn(sort_on_option,
list,
clone)
{\n
var
sort_index;\n
if
(!Array.isArray(sort_on_option))
{\n
throw
new
TypeError("jioquery.sortOn():
"
+\n
"Argument
1
is
not
of
type
\'array\'");\n
}\n
if
(clone)
{\n
list =
deepClone(list);\n
}\n
for
(
sort_index =
sort_on_option.length
-
1;
sort_index
>
= 0;\n
sort_index -= 1) {\n
list.sort(sortFunction(\n
sort_on_option[sort_index][0],\n
sort_on_option[sort_index][1]\n
));\n
}\n
return list;\n
}\n
/**\n
*
Comparison
operator,
test
if
this
query
value
is
equal
or
lower
than
the\n
*
item
value\n
*\n
*
@method
<=\n
*
@param
{Number,
String}
object_value
The
value
to
compare\n
*
@param
{Number,
String}
comparison_value
The
comparison
value\n
*
@return
{Boolean}
true
if
equal
or
lower,
false
otherwise\n
*/\n
SimpleQuery.prototype["<="]
=
function
(object_value,
comparison_value)
{\n
var
value;\n
if
(!Array.isArray(object_value))
{\n
object_value =
[object_value];\n
}\n
value =
object_value[0];\n
if
(typeof
value =
==
\'object\'
&&
value.hasOwnProperty(\'content\'))
{\n
value =
value.content;\n
}\n
if
(typeof
value.cmp =
==
"function")
{\n
return
(value.cmp(comparison_value)
<=
0);\n
}\n
return
(value
<=
comparison_value);\n
};\n
\n
Query.sortOn = sortOn;\n
/**\n
*
Comparison
operator,
test
if
this
query
value
is
greater
than
the
item\n
*
value\n
*\n
*
@method
>
\n
* @param {Number, String} object_value The value to compare\n
* @param {Number, String} comparison_value The comparison value\n
* @return {Boolean} true if greater, false otherwise\n
*/\n
SimpleQuery.prototype[">"] = function (object_value, comparison_value) {\n
var value;\n
if (!Array.isArray(object_value)) {\n
object_value = [object_value];\n
}\n
value = object_value[0];\n
if (typeof value === \'object\'
&&
value.hasOwnProperty(\'content\')) {\n
value = value.content;\n
}\n
if (typeof value.cmp === "function") {\n
return (value.cmp(comparison_value) > 0);\n
}\n
return (value > comparison_value);\n
};\n
\n
/**\n
* Limit a list of items, according to index and length. If `clone` is true,\n
* then the method will act on a cloned list.\n
*\n
* @param {Array} limit_option A couple [from, length]\n
* @param {Array} list The item list to limit\n
* @param {Boolean} [clone=false] If true, modifies a clone of the list\n
* @return {Array} The filtered list\n
*/\n
function limit(limit_option, list, clone) {\n
if (!Array.isArray(limit_option)) {\n
throw new TypeError("jioquery.limit(): " +\n
"Argument 1 is not of type \'array\'");\n
}\n
if (!Array.isArray(list)) {\n
throw new TypeError("jioquery.limit(): " +\n
"Argument 2 is not of type \'array\'");\n
}\n
if (clone) {\n
list = deepClone(list);\n
}\n
list.splice(0, limit_option[0]);\n
if (limit_option[1]) {\n
list.splice(limit_option[1]);\n
}\n
return list;\n
}\n
/**\n
* Comparison operator, test if this query value is equal or greater than the\n
* item value\n
*\n
* @method >=\n
* @param {Number, String} object_value The value to compare\n
* @param {Number, String} comparison_value The comparison value\n
* @return {Boolean} true if equal or greater, false otherwise\n
*/\n
SimpleQuery.prototype[">="] = function (object_value, comparison_value) {\n
var value;\n
if (!Array.isArray(object_value)) {\n
object_value = [object_value];\n
}\n
value = object_value[0];\n
if (typeof value === \'object\'
&&
value.hasOwnProperty(\'content\')) {\n
value = value.content;\n
}\n
if (typeof value.cmp === "function") {\n
return (value.cmp(comparison_value) >= 0);\n
}\n
return (value >= comparison_value);\n
};\n
\n
Query.limit = limit;\n
query_class_dict.simple = SimpleQuery;\n
query_class_dict.complex = ComplexQuery;\n
\n
/**\n
* Convert a search text to a regexp.\n
*\n
* @param {String} string The string to convert\n
* @param {Boolean} [use_wildcard_character=true] Use wildcard "%" and "_"\n
* @return {RegExp} The search text regexp\n
*/\n
function searchTextToRegExp(string, use_wildcard_characters) {\n
if (typeof string !== \'string\') {\n
throw new TypeError("jioquery.searchTextToRegExp(): " +\n
"Argument 1 is not of type \'string\'");\n
}\n
if (use_wildcard_characters === false) {\n
return new RegExp("^" + stringEscapeRegexpCharacters(string) + "$");\n
}\n
return new RegExp("^" + stringEscapeRegexpCharacters(string).replace(\n
/%/g,\n
".*"\n
).replace(\n
/_/g,\n
"."\n
) + "$");\n
}\n
Query.parseStringToObject = parseStringToObject;\n
Query.objectToSearchText = objectToSearchText;\n
\n
window.Query = Query;\n
window.SimpleQuery = SimpleQuery;\n
window.ComplexQuery = ComplexQuery;\n
window.QueryFactory = QueryFactory;\n
\n
Query.searchTextToRegExp = searchTextToRegExp
;\n
}(RSVP, window, parseStringToObject))
;\n
;/*global window, moment */\n
/*jslint nomen: true, maxlen: 200*/\n
(function (window, moment) {\n
...
...
@@ -6058,70 +5949,6 @@ Query.searchTextToRegExp = searchTextToRegExp;\n
});\n
}\n
util.ajax = ajax;\n
\n
/**\n
* Clones all native object in deep. Managed types: Object, Array, String,\n
* Number, Boolean, Function, null.\n
*\n
* It can also clone object which are serializable, like Date.\n
*\n
* To make a class serializable, you need to implement the `toJSON` function\n
* which returns a JSON representation of the object. The returned value is\n
* used as first parameter of the object constructor.\n
*\n
* @param {A} object The object to clone\n
* @return {A} The cloned object\n
*/\n
function deepClone(object) {\n
var i, cloned;\n
if (Array.isArray(object)) {\n
cloned = [];\n
for (i = 0; i
< object.length
;
i
+=
1)
{\n
cloned[i]
=
deepClone(object[i]);\n
}\n
return
cloned;\n
}\n
if
(
object =
==
null)
{\n
return
null;\n
}\n
if
(typeof
object =
==
\'object\')
{\n
if
(Object.getPrototypeOf(object)
===
Object.prototype)
{\n
cloned =
{};\n
for
(i
in
object)
{\n
if
(object.hasOwnProperty(i))
{\n
cloned[i]
=
deepClone(object[i]);\n
}\n
}\n
return
cloned;\n
}\n
if
(object
instanceof
Date)
{\n
//
XXX
this
block
is
to
enable
phantomjs
and
browsers
compatibility
with\n
//
Date.prototype.toJSON
when
it
is
an
invalid
date.
In
phantomjs,
it\n
//
returns
`"Invalid
Date"`
but
in
browsers
it
returns
`null`.
In\n
//
browsers,
giving
`null`
as
parameter
to
`new
Date()`
doesn\'t
return\n
//
an
invalid
date.\n
\n
//
Cloning
a
date
with
`return
new
Date(object)`
has
problems
on\n
//
Firefox.\n
//
I
don\'t
know
why...
(Tested
on
Firefox
23)\n
\n
if
(isFinite(object.getTime()))
{\n
return
new
Date(object.toJSON());\n
}\n
return
new
Date("Invalid
Date");\n
}\n
//
clone
serializable
objects\n
if
(typeof
object.toJSON =
==
\'function\')
{\n
return
new
(Object.getPrototypeOf(object).constructor)(object.toJSON());\n
}\n
//
cannot
clone\n
return
object;\n
}\n
return
object;\n
}\n
util.deepClone =
deepClone;\n
\n
\n
\n
function readBlobAsText(blob, encoding) {\n
var fr = new FileReader();\n
...
...
@@ -7634,13 +7461,13 @@ Query.searchTextToRegExp = searchTextToRegExp;\n
attachments:
{}\n
};\n
}\n
this._database[id]
.doc =
JSON.stringify(metadata)
;\n
this._database[id]
.doc =
metadata
;\n
return
id;\n
};\n
\n
MemoryStorage.prototype.get =
function
(id)
{\n
try
{\n
return
JSON.parse(this._database[id].doc)
;\n
return
this._database[id].doc
;\n
}
catch
(error)
{\n
if
(error
instanceof
TypeError)
{\n
throw
new
jIO.util.jIOError(\n
...
...
@@ -7728,18 +7555,26 @@ Query.searchTextToRegExp = searchTextToRegExp;\n
\n
\n
MemoryStorage.prototype.hasCapacity =
function
(name)
{\n
return
(
name =
==
"list"
);\n
return
(
(
name =
==
"list")
||
(
name =
==
"include")
);\n
};\n
\n
MemoryStorage.prototype.buildQuery =
function
()
{\n
MemoryStorage.prototype.buildQuery =
function
(
options
)
{\n
var
rows =
[],\n
i;\n
for
(i
in
this._database)
{\n
if
(this._database.hasOwnProperty(i))
{\n
rows.push({\n
id:
i,\n
value:
{}\n
});\n
if
(
options.include_docs =
==
true)
{\n
rows.push({\n
id:
i,\n
value:
{},\n
doc:
this._database[i]\n
});\n
}
else
{\n
rows.push({\n
id:
i,\n
value:
{}\n
});\n
}\n
\n
}\n
}\n
...
...
@@ -8731,6 +8566,250 @@ Query.searchTextToRegExp = searchTextToRegExp;\n
jIO.addStorage(\'dav\',
DavStorage);\n
\n
}(jIO,
RSVP,
DOMParser,
Blob));\n
;/*\n
*
Copyright
2015,
Nexedi
SA\n
*
Released
under
the
LGPL
license.\n
*
http://www.gnu.org/licenses/lgpl.html\n
*/\n
/**\n
*
JIO
Google
Drive
Storage.
Type =
"gdrive"
.\n
*
Google
Drive
"database"
storage.\n
*/\n
/*global
jIO,
Blob,
RSVP,
UriTemplate,
JSON*/\n
/*jslint
nomen:
true*/\n
\n
(function
(jIO,
Blob,
RSVP,
UriTemplate,
JSON)
{\n
"use
strict";\n
\n
var
UPLOAD_URL =
"https://www.googleapis.com{/upload}/drive/v2/files{/id}"
+\n
"{?uploadType,access_token}",\n
upload_template =
UriTemplate.parse(UPLOAD_URL),\n
REMOVE_URL =
"https://www.googleapis.com/drive/v2/"
+\n
"files{/id,trash}{?access_token}",\n
remove_template =
UriTemplate.parse(REMOVE_URL),\n
LIST_URL =
"https://www.googleapis.com/drive/v2/files"
+\n
"?
prettyPrint=
false{&pageToken}&q=trashed=false"
+\n
"&
fields=
nextPageToken,items(id){&access_token}",\n
list_template =
UriTemplate.parse(LIST_URL),\n
GET_URL =
"https://www.googleapis.com/drive/v2/files{/id}{?alt}"
,\n
get_template =
UriTemplate.parse(GET_URL);\n
\n
function
handleError(error,
id)
{\n
if
(
error.target.status =
==
404)
{\n
throw
new
jIO.util.jIOError(\n
"Cannot
find
document:
"
+
id,\n
404\n
);\n
}\n
throw
error;\n
}\n
\n
function
listPage(result,
token)
{\n
var
i,\n
obj;\n
return
new
RSVP.Queue()\n
.push(function
()
{\n
return
jIO.util.ajax({\n
"type":
"GET",\n
"url":
list_template.expand({\n
pageToken
:
(result.nextPageToken
||
""),\n
access_token:
token\n
})\n
});\n
})\n
.push(function
(data)
{\n
obj =
JSON.parse(data.target.response
||
data.target.responseText);\n
for
(
i =
0;
i
<
obj.items.length;
i
+=
1)
{\n
obj.items[i]
.value =
{};\n
result.push(obj.items[i]);\n
}\n
result.nextPageToken =
obj.nextPageToken;\n
return
result;\n
},
handleError);\n
}\n
\n
function
checkName(name)
{\n
if
(name
!==
"enclosure")
{\n
throw
new
jIO.util.jIOError("Only
support
\'enclosure\'
attachment",
400);\n
}\n
}\n
\n
/**\n
*
The
JIO
Google
Drive
Storage
extension\n
*\n
*
@class
GdriveStorage\n
*
@constructor\n
*/\n
function
GdriveStorage(spec)
{\n
if
(
spec =
==
undefined
||
spec.access_token =
==
undefined
||\n
typeof
spec.access_token
!==
\'string\')
{\n
throw
new
TypeError("Access
Token
must
be
a
string
"
+\n
"which
contains
more
than
one
character.");\n
}\n
if
(spec.trashing
!==
undefined
&&\n
(spec.trashing
!==
true
&&
spec.trashing
!==
false))
{\n
throw
new
TypeError("trashing
parameter"
+\n
"
must
be
a
boolean
(true
or
false)");\n
}\n
this._trashing =
spec.trashing
||
true;\n
this._access_token =
spec.access_token;\n
return;\n
}\n
\n
function
recursiveAllDocs(result,
accessToken)
{\n
return
new
RSVP.Queue()\n
.push(function
()
{\n
return
listPage(result,
accessToken);\n
})\n
.push(function
()
{\n
if
(result.nextPageToken)
{\n
return
recursiveAllDocs(result,
accessToken);\n
}\n
return
result;\n
});\n
}\n
\n
GdriveStorage.prototype.hasCapacity =
function
(name)
{\n
return
(
name =
==
"list");\n
};\n
\n
GdriveStorage.prototype.buildQuery =
function
()
{\n
return
recursiveAllDocs([],
this._access_token);\n
};\n
\n
function
sendMetaData(id,
param,
token)
{\n
var
boundary =
"-------314159265358979323846"
;\n
\n
return
new
RSVP.Queue()\n
.push(function
()
{\n
return
jIO.util.ajax({\n
"type":
id
?
"PUT"
:
"POST",\n
"url":
upload_template.expand({\n
access_token:
token,\n
id:
id
||
[],\n
upload:
id
?
[]
:
"upload",\n
uploadType:
"multipart"\n
}),\n
headers:
{\n
"Content-Type"
:
\'multipart/related;
boundary=
"\' + boundary + \'"
\'\n
},\n
data:
\'--\'
+
boundary
+
\'\\n\'
+\n
\'Content-Type:
application/json;
charset=
UTF-8\\n\\n\'
+\n
JSON.stringify(param)
+
\'\\n\\n--\'
+
boundary
+
"--"\n
});\n
})\n
.push(function
(result)
{\n
var
obj =
JSON.parse(result.target.responseText);\n
\n
return
obj.id;\n
},\n
function
(error)
{handleError(error,
id);
});\n
}\n
\n
GdriveStorage.prototype.put =
function
(id,
param)
{\n
return
sendMetaData(id,
param,
this._access_token);\n
};\n
\n
GdriveStorage.prototype.post =
function
(param)
{\n
return
sendMetaData(undefined,
param,
this._access_token);\n
};\n
\n
function
sendData(id,
blob,
token)
{\n
return
new
RSVP.Queue()\n
.push(function
()
{\n
return
jIO.util.ajax({\n
"type":
"PUT",\n
"url":
upload_template.expand({\n
access_token:
token,\n
upload:
"upload",\n
id:
id,\n
uploadType:
"media"\n
}),\n
data:
blob\n
});\n
})\n
.push(function
(data)
{\n
data =
JSON.parse(data.target.responseText);\n
if
(
data.mimeType =
==
"application/vnd.google-apps.folder")
{\n
throw
new
jIO.util.jIOError("cannot
put
attachments
to
folder",
400);\n
}\n
return
data;\n
},
function
(error)
{handleError(error,
id);
});\n
}\n
\n
GdriveStorage.prototype.putAttachment =
function
(id,
name,
blob)
{\n
checkName(name);\n
return
sendData(id,
blob,
this._access_token);\n
};\n
\n
GdriveStorage.prototype.remove =
function
(id)
{\n
var
that =
this;\n
return
new
RSVP.Queue()\n
.push(function
()
{\n
return
jIO.util.ajax({\n
type:
that._trashing
?
"POST"
:
"DELETE",\n
url:
remove_template.expand({\n
id
:
id,\n
access_token
:
that._access_token,\n
trash
:
that._trashing
?
"trash"
:
[]\n
})\n
});\n
})\n
.push(undefined,
function
(error)
{handleError(error,
id);
});\n
};\n
\n
function
getData(id,
attach,
token)
{\n
return
new
RSVP.Queue()\n
.push(function
()
{\n
return
jIO.util.ajax({\n
type:
"GET",\n
dataType:
attach
?
"blob"
:
"json",\n
url:
get_template.expand({\n
id:
id,\n
alt:
attach
?
"media"
:
[],\n
access_token:
token\n
}),\n
headers:
{\n
"Authorization"
:
"Bearer
"
+
token\n
}\n
});\n
})\n
.push(function
(evt)
{\n
return
evt.target.response
||\n
(attach
?
new
Blob([evt.target.responseText],\n
{"type"
:\n
evt.target.responseHeaders["Content-Type"]})
:\n
JSON.parse(evt.target.responseText));\n
},
function
(error)
{handleError(error,
id);
});\n
}\n
\n
GdriveStorage.prototype.get =
function
(id)
{\n
return
getData(id,
false,
this._access_token);\n
};\n
\n
GdriveStorage.prototype.getAttachment =
function
(id,
name)
{\n
checkName(name);\n
return
getData(id,
true,
this._access_token);\n
};\n
\n
GdriveStorage.prototype.allAttachments =
function
(id)
{\n
var
token =
this._access_token;\n
\n
return
new
RSVP.Queue()\n
.push(function
()
{\n
return
getData(id,
false,
token);\n
})\n
.push(function
(data)
{\n
if
(
data.mimeType =
==
"application/vnd.google-apps.folder")
{\n
return
{};\n
}\n
return
{"enclosure":
{}};\n
});\n
};\n
\n
jIO.addStorage(\'gdrive\',
GdriveStorage);\n
\n
}(jIO,
Blob,
RSVP,
UriTemplate,
JSON));\n
;/*jslint
nomen:
true
*/\n
/*global
RSVP*/\n
\n
...
...
@@ -8989,10 +9068,10 @@ Query.searchTextToRegExp = searchTextToRegExp;\n
//
}\n
\n
/*jslint
nomen:
true,
unparam:
true
*/\n
/*global
jIO,
UriTemplate,
FormData,
RSVP,
URI,
Blob,
objectToSearchText,
\n
/*global
jIO,
UriTemplate,
FormData,
RSVP,
URI,
Blob,\n
SimpleQuery,
ComplexQuery*/\n
\n
(function
(jIO,
UriTemplate,
FormData,
RSVP,
URI,
Blob,
objectToSearchText,
\n
(function
(jIO,
UriTemplate,
FormData,
RSVP,
URI,
Blob,\n
SimpleQuery,
ComplexQuery)
{\n
"use
strict";\n
\n
...
...
@@ -9449,14 +9528,14 @@ Query.searchTextToRegExp = searchTextToRegExp;\n
if
(result_list)
{\n
local_roles =
result_list;\n
parsed_query.query_list.splice(i,
1);\n
query =
objectToSearchText(parsed_query);\n
query =
jIO.Query.
objectToSearchText(parsed_query);\n
i =
parsed_query.query_list.length;\n
}
else
{\n
result_list =
isMultipleLocalRoles(sub_query);\n
if
(result_list)
{\n
local_roles =
result_list;\n
parsed_query.query_list.splice(i,
1);\n
query =
objectToSearchText(parsed_query);\n
query =
jIO.Query.
objectToSearchText(parsed_query);\n
i =
parsed_query.query_list.length;\n
}\n
}\n
...
...
@@ -9507,7 +9586,7 @@ Query.searchTextToRegExp = searchTextToRegExp;\n
\n
jIO.addStorage("erp5",
ERP5Storage);\n
\n
}(jIO,
UriTemplate,
FormData,
RSVP,
URI,
Blob,
objectToSearchText,
\n
}(jIO,
UriTemplate,
FormData,
RSVP,
URI,
Blob,\n
SimpleQuery,
ComplexQuery));\n
;/*jslint
nomen:
true*/\n
/*global
RSVP*/\n
...
...
@@ -10651,8 +10730,7 @@ Query.searchTextToRegExp = searchTextToRegExp;\n
};\n
\n
jIO.addStorage("indexeddb",
IndexedDBStorage);\n
}(indexedDB,
jIO,
RSVP,
Blob,
Math,
IDBKeyRange));\n
}(indexedDB,
jIO,
RSVP,
Blob,
Math,
IDBKeyRange));
]]
></string>
</value>
</item>
...
...
@@ -10789,7 +10867,7 @@ Query.searchTextToRegExp = searchTextToRegExp;\n
</item>
<item>
<key>
<string>
serial
</string>
</key>
<value>
<string>
947.
13956.40084.22186
</string>
</value>
<value>
<string>
947.
22494.14742.48810
</string>
</value>
</item>
<item>
<key>
<string>
state
</string>
</key>
...
...
@@ -10807,7 +10885,7 @@ Query.searchTextToRegExp = searchTextToRegExp;\n
</tuple>
<state>
<tuple>
<float>
144
8293989.05
</float>
<float>
144
9226044.59
</float>
<string>
UTC
</string>
</tuple>
</state>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment