Skip to content

Commit 2b19932

Browse files
committed
Closes #91
Merge commit '63eb0fa7e0e1ebedea5be2f04a2bb4e7abf468bd'
2 parents 8c41c30 + 63eb0fa commit 2b19932

File tree

6 files changed

+150
-3
lines changed

6 files changed

+150
-3
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*!
2+
* jQuery QueryBuilder Loopback Support
3+
* Copyright 2014-2015 Fabien Franzen (https://github.com/fabien)
4+
* Licensed under MIT (http://opensource.org/licenses/MIT)
5+
*/
6+
7+
(function($){
8+
9+
// DEFAULT CONFIG
10+
// ===============================
11+
$.fn.queryBuilder.defaults.set({
12+
loopbackOperators: {
13+
equal: function(v){ return v[0]; },
14+
not_equal: function(v){ return {'neq': v[0]}; },
15+
in: function(v){ return {'inq': v}; },
16+
not_in: function(v){ return {'nin': v}; },
17+
less: function(v){ return {'lt': v[0]}; },
18+
less_or_equal: function(v){ return {'lte': v[0]}; },
19+
greater: function(v){ return {'gt': v[0]}; },
20+
greater_or_equal: function(v){ return {'gte': v[0]}; },
21+
between: function(v){ return {'between': v}; },
22+
begins_with: function(v){ return {'like': '^' + escapeRegExp(v[0])}; },
23+
not_begins_with: function(v){ return {'nlike': '^' + escapeRegExp(v[0])}; },
24+
contains: function(v){ return {'like': escapeRegExp(v[0])}; },
25+
not_contains: function(v){ return {'nlike': escapeRegExp(v[0])}; },
26+
ends_with: function(v){ return {'like': escapeRegExp(v[0]) + '$'}; },
27+
not_ends_with: function(v){ return {'nlike': escapeRegExp(v[0]) + '$'}; },
28+
is_empty: function(v){ return ''; },
29+
is_not_empty: function(v){ return {'neq': ''}; },
30+
is_null: function(v){ return null; },
31+
is_not_null: function(v){ return {'neq': null}; }
32+
}
33+
});
34+
35+
36+
// PUBLIC METHODS
37+
// ===============================
38+
$.fn.queryBuilder.extend({
39+
/**
40+
* Get rules as Loopback query
41+
* @param data {object} (optional) rules
42+
* @return {object}
43+
*/
44+
getLoopback: function(data) {
45+
data = (data===undefined) ? this.getRules() : data;
46+
47+
var that = this;
48+
49+
return (function parse(data) {
50+
if (!data.condition) {
51+
data.condition = that.settings.default_condition;
52+
}
53+
if (['AND', 'OR'].indexOf(data.condition.toUpperCase()) === -1) {
54+
$.error('Unable to build Loopback query with '+ data.condition +' condition');
55+
}
56+
57+
if (!data.rules) {
58+
return {};
59+
}
60+
61+
var parts = [];
62+
63+
$.each(data.rules, function(i, rule) {
64+
if (rule.rules && rule.rules.length>0) {
65+
parts.push(parse(rule));
66+
}
67+
else {
68+
var mdb = that.settings.loopbackOperators[rule.operator],
69+
ope = that.getOperatorByType(rule.operator),
70+
values = [];
71+
72+
if (mdb === undefined) {
73+
$.error('Loopback operation unknown for operator '+ rule.operator);
74+
}
75+
76+
if (ope.accept_values) {
77+
if (!(rule.value instanceof Array)) {
78+
rule.value = [rule.value];
79+
}
80+
81+
rule.value.forEach(function(v, i) {
82+
values.push(changeType(v, rule.type));
83+
});
84+
}
85+
86+
var part = {};
87+
part[rule.field] = mdb.call(that, values);
88+
parts.push(part);
89+
}
90+
});
91+
92+
var res = {};
93+
if (parts.length > 0) {
94+
res[ data.condition.toLowerCase() ] = parts;
95+
}
96+
return res;
97+
}(data));
98+
}
99+
});
100+
101+
102+
// UTILITIES
103+
// ===============================
104+
/**
105+
* Change type of a value to int, float or boolean
106+
* @param value {mixed}
107+
* @param type {string}
108+
* @return {mixed}
109+
*/
110+
function changeType(value, type, db) {
111+
switch (type) {
112+
case 'integer': return parseInt(value);
113+
case 'double': return parseFloat(value);
114+
case 'boolean':
115+
var bool = value.trim().toLowerCase() === 'true' || value.trim() === '1' || value === 1;
116+
if (db === 'sql') {
117+
return bool ? 1 : 0;
118+
}
119+
else {
120+
return bool;
121+
}
122+
break;
123+
default: return value;
124+
}
125+
}
126+
127+
/**
128+
* Escape value for use in regex
129+
* @param value {string}
130+
* @return {string}
131+
*/
132+
function escapeRegExp(str) {
133+
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
134+
}
135+
136+
}(jQuery));

src/plugins/mongodb-support/plugin.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@
264264
if (db === 'sql') {
265265
return bool ? 1 : 0;
266266
}
267-
else if (db === 'mongo') {
267+
else {
268268
return bool;
269269
}
270270
break;

src/plugins/sql-support/plugin.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@
188188
if (db === 'sql') {
189189
return bool ? 1 : 0;
190190
}
191-
else if (db === 'mongo') {
191+
else {
192192
return bool;
193193
}
194194
break;

tests/core_tests.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ $(function(){
114114
assert.equal($('#container8_group_1.rules-group-container [data-delete=group] i').attr('class'), "fa fa-times", 'Group delete icon should have been replaced');
115115
});
116116

117-
QUnit.test('SQL/MongoDB export + MongoDB import', function(assert) {
117+
QUnit.test('SQL/MongoDB/Loopback export/import', function(assert) {
118118
$('#container9').queryBuilder({
119119
filters: basic_filters,
120120
rules: basic_rules
@@ -124,6 +124,7 @@ $(function(){
124124
assert.deepEqual($('#container9').queryBuilder('getSQL', true, false), basic_rules_sql_stmt, 'Should create SQL query with statements');
125125
assert.deepEqual($('#container9').queryBuilder('getMongo'), basic_rules_mongodb, 'Should create MongoDB query');
126126
assert.deepEqual($('#container9').queryBuilder('getRulesFromMongo',basic_rules_mongodb), basic_rules, 'Should return object with rules');
127+
assert.deepEqual($('#container9').queryBuilder('getLoopback'), basic_rules_loopback, 'Should create Loopback query');
127128
});
128129

129130
QUnit.test('Validation callback', function(assert) {

tests/data.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,15 @@ var basic_rules_mongodb = {'$and': [
110110
]}
111111
]};
112112

113+
var basic_rules_loopback = {'and': [
114+
{'price': { 'lt': 10.25 }},
115+
{'name': null},
116+
{'or': [
117+
{'category': {'inq': ['mo', 'mu']}},
118+
{'id': {'neq': '1234-azer-5678'}}
119+
]}
120+
]};
121+
113122
var invalid_rules = {
114123
condition: 'AND',
115124
rules: [{

tests/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<script src="../src/query-builder.js"></script>
1616
<script src="../src/plugins/sql-support/plugin.js"></script>
1717
<script src="../src/plugins/mongodb-support/plugin.js"></script>
18+
<script src="../src/plugins/loopback-support/plugin.js"></script>
1819
<script src="data.js"></script>
1920
<script src="core_tests.js"></script>
2021
</head>

0 commit comments

Comments
 (0)