From 4b849d5d8ba5a2ad5d889673ac352a20f06c6eae Mon Sep 17 00:00:00 2001 From: Roman Chyla Date: Wed, 11 Jun 2014 22:39:40 -0400 Subject: [PATCH 01/15] Exporting unminified files as bower target --- bower.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bower.json b/bower.json index 45b4767a..d7e5f215 100644 --- a/bower.json +++ b/bower.json @@ -8,7 +8,9 @@ "description": "jQuery plugin for user friendly query/filter creator", "main": [ "dist/query-builder.min.js", - "dist/query-builder.min.css" + "dist/query-builder.min.css", + "src/query-builder.js", + "src/query-builder.css" ], "dependencies" : { "jquery": ">= 1.9.0", From 188f05728becf8a6e2d491501986d35e36876b45 Mon Sep 17 00:00:00 2001 From: Roman Chyla Date: Wed, 11 Jun 2014 22:39:40 -0400 Subject: [PATCH 02/15] Exporting unminified files as bower target --- bower.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bower.json b/bower.json index 45b4767a..cbfb356b 100644 --- a/bower.json +++ b/bower.json @@ -8,7 +8,9 @@ "description": "jQuery plugin for user friendly query/filter creator", "main": [ "dist/query-builder.min.js", - "dist/query-builder.min.css" + "dist/query-builder.min.css", + "src/query-builder.js", + "src/query-builder.css" ], "dependencies" : { "jquery": ">= 1.9.0", @@ -25,7 +27,7 @@ "homepage": "https://github.com/mistic100/jQuery-QueryBuilder", "repository": { "type": "git", - "url": "git://github.com/mistic100/jQuery-QueryBuilder.git" + "url": "git://github.com/romanchyla/jQuery-QueryBuilder.git" }, "ignore": [ "**/.*", From f204b067bb7528269a6a06824a08e1dbab862b5f Mon Sep 17 00:00:00 2001 From: Roman Chyla Date: Thu, 12 Jun 2014 20:48:37 -0400 Subject: [PATCH 03/15] Removed window.QueryBuilder and added a mocha test --- bower.json | 9 +- src/i18n/en.js | 56 +++---- src/i18n/fr.js | 56 +++---- src/i18n/ro.js | 56 +++---- src/query-builder.js | 24 ++- tests/index.html | 1 + tests/mocha/basic-functionality.js | 30 ++++ tests/mocha/index.html | 229 +++++++++++++++++++++++++++++ 8 files changed, 370 insertions(+), 91 deletions(-) create mode 100644 tests/mocha/basic-functionality.js create mode 100644 tests/mocha/index.html diff --git a/bower.json b/bower.json index cbfb356b..52db9fe7 100644 --- a/bower.json +++ b/bower.json @@ -27,7 +27,7 @@ "homepage": "https://github.com/mistic100/jQuery-QueryBuilder", "repository": { "type": "git", - "url": "git://github.com/romanchyla/jQuery-QueryBuilder.git" + "url": "git://github.com/mistic100/jQuery-QueryBuilder.git" }, "ignore": [ "**/.*", @@ -35,5 +35,10 @@ "bower_components", "test", "tests" - ] + ], + "devDependencies": { + "chai": "~1.8.0", + "mocha": "~1.20.0", + "sinon": "http://sinonjs.org/releases/sinon-1.9.0.js" + } } diff --git a/src/i18n/en.js b/src/i18n/en.js index eb151803..cc406dc7 100644 --- a/src/i18n/en.js +++ b/src/i18n/en.js @@ -1,30 +1,32 @@ -QueryBuilder.setDefaults({ lang: { - "add_rule": "Add rule", - "add_group": "Add group", - "delete_rule": "Delete", - "delete_group": "Delete", +(function($){ + $.fn.queryBuilder.defaults.set({ lang: { + "add_rule": "Add rule", + "add_group": "Add group", + "delete_rule": "Delete", + "delete_group": "Delete", - "and_condition": "AND", - "or_condition": "OR", + "and_condition": "AND", + "or_condition": "OR", - "filter_select_placeholder": "------", + "filter_select_placeholder": "------", - "operator_equal": "equal", - "operator_not_equal": "not equal", - "operator_in": "in", - "operator_not_in": "not in", - "operator_less": "less", - "operator_less_or_equal": "less or equal", - "operator_greater": "greater", - "operator_greater_or_equal": "greater or equal", - "operator_begins_with": "begins with", - "operator_not_begins_with": "doesn't begin with", - "operator_contains": "contains", - "operator_not_contains": "doesn't contain", - "operator_ends_with": "ends with", - "operator_not_ends_with": "doesn't end with", - "operator_is_empty": "is empty", - "operator_is_not_empty": "is not empty", - "operator_is_null": "is null", - "operator_is_not_null": "is not null" -}}); \ No newline at end of file + "operator_equal": "equal", + "operator_not_equal": "not equal", + "operator_in": "in", + "operator_not_in": "not in", + "operator_less": "less", + "operator_less_or_equal": "less or equal", + "operator_greater": "greater", + "operator_greater_or_equal": "greater or equal", + "operator_begins_with": "begins with", + "operator_not_begins_with": "doesn't begin with", + "operator_contains": "contains", + "operator_not_contains": "doesn't contain", + "operator_ends_with": "ends with", + "operator_not_ends_with": "doesn't end with", + "operator_is_empty": "is empty", + "operator_is_not_empty": "is not empty", + "operator_is_null": "is null", + "operator_is_not_null": "is not null" + }}); +}(jQuery)); diff --git a/src/i18n/fr.js b/src/i18n/fr.js index 4255913f..81b6fc40 100644 --- a/src/i18n/fr.js +++ b/src/i18n/fr.js @@ -1,30 +1,32 @@ -QueryBuilder.setDefaults({ lang: { - "add_rule": "Ajouter une règle", - "add_group": "Ajouter un groupe", - "delete_rule": "Supprimer", - "delete_group": "Supprimer", +(function($){ + $.fn.queryBuilder.defaults.set({ lang: { + "add_rule": "Ajouter une règle", + "add_group": "Ajouter un groupe", + "delete_rule": "Supprimer", + "delete_group": "Supprimer", - "and_condition": "ET", - "or_condition": "OU", + "and_condition": "ET", + "or_condition": "OU", - "filter_select_placeholder": "------", + "filter_select_placeholder": "------", - "operator_equal": "égal", - "operator_not_equal": "non égal", - "operator_in": "dans", - "operator_not_in": "pas dans", - "operator_less": "inférieur", - "operator_less_or_equal": "inférieur ou égal", - "operator_greater": "supérieur", - "operator_greater_or_equal": "supérieur ou égal", - "operator_begins_with": "commence par", - "operator_not_begins_with": "ne commence pas par", - "operator_contains": "contient", - "operator_not_contains": "ne contient pas", - "operator_ends_with": "finit par", - "operator_not_ends_with": "ne finit pas par", - "operator_is_empty": "est vide", - "operator_is_not_empty": "n'est pas vide", - "operator_is_null": "est nul", - "operator_is_not_null": "n'est pas nul" -}}); \ No newline at end of file + "operator_equal": "égal", + "operator_not_equal": "non égal", + "operator_in": "dans", + "operator_not_in": "pas dans", + "operator_less": "inférieur", + "operator_less_or_equal": "inférieur ou égal", + "operator_greater": "supérieur", + "operator_greater_or_equal": "supérieur ou égal", + "operator_begins_with": "commence par", + "operator_not_begins_with": "ne commence pas par", + "operator_contains": "contient", + "operator_not_contains": "ne contient pas", + "operator_ends_with": "finit par", + "operator_not_ends_with": "ne finit pas par", + "operator_is_empty": "est vide", + "operator_is_not_empty": "n'est pas vide", + "operator_is_null": "est nul", + "operator_is_not_null": "n'est pas nul" + }}); +}(jQuery)); \ No newline at end of file diff --git a/src/i18n/ro.js b/src/i18n/ro.js index 1120bc31..36788ae7 100644 --- a/src/i18n/ro.js +++ b/src/i18n/ro.js @@ -1,30 +1,32 @@ -QueryBuilder.setDefaults({ lang: { - "add_rule": "Adaugă regulă", - "add_group": "Adaugă grup", - "delete_rule": "Şterge", - "delete_group": "Şterge", +(function ($) { + $.fn.queryBuilder.defaults.set({ lang: { + "add_rule": "Adaugă regulă", + "add_group": "Adaugă grup", + "delete_rule": "Şterge", + "delete_group": "Şterge", - "and_condition": "ŞI", - "or_condition": "SAU", + "and_condition": "ŞI", + "or_condition": "SAU", - "filter_select_placeholder": "------", + "filter_select_placeholder": "------", - "operator_equal": "egal", - "operator_not_equal": "diferit", - "operator_in": "în", - "operator_not_in": "nu în", - "operator_less": "mai puţin", - "operator_less_or_equal": "mai puţin sau egal", - "operator_greater": "mai mare", - "operator_greater_or_equal": "mai mare sau egal", - "operator_begins_with": "începe cu", - "operator_not_begins_with": "nu începe cu", - "operator_contains": "conţine", - "operator_not_contains": "nu conţine", - "operator_ends_with": "se termină cu", - "operator_not_ends_with": "nu se termină cu", - "operator_is_empty": "este gol", - "operator_is_not_empty": "nu este gol", - "operator_is_null": "e nul", - "operator_is_not_null": "nu e nul" -}}); \ No newline at end of file + "operator_equal": "egal", + "operator_not_equal": "diferit", + "operator_in": "în", + "operator_not_in": "nu în", + "operator_less": "mai puţin", + "operator_less_or_equal": "mai puţin sau egal", + "operator_greater": "mai mare", + "operator_greater_or_equal": "mai mare sau egal", + "operator_begins_with": "începe cu", + "operator_not_begins_with": "nu începe cu", + "operator_contains": "conţine", + "operator_not_contains": "nu conţine", + "operator_ends_with": "se termină cu", + "operator_not_ends_with": "nu se termină cu", + "operator_is_empty": "este gol", + "operator_is_not_empty": "nu este gol", + "operator_is_null": "e nul", + "operator_is_not_null": "nu e nul" + }}); +}(jQuery)); \ No newline at end of file diff --git a/src/query-builder.js b/src/query-builder.js index e41e186d..c499ee45 100644 --- a/src/query-builder.js +++ b/src/query-builder.js @@ -187,13 +187,6 @@ ] }; - // expose setDefaults static method - window.QueryBuilder = { - setDefaults: function(config) { - $.extend(true, QueryBuilder.DEFAULTS, config); - } - }; - // PUBLIC METHODS // =============================== @@ -1112,7 +1105,7 @@ // =============================== $.fn.queryBuilder = function(option) { if (this.length > 1) { - $.error('Unable to initialize on multiple target'); + $.error('Unable to initialize multiple instances on the same target'); } var data = this.data('queryBuilder'), @@ -1131,4 +1124,19 @@ return this; }; + // expose setDefaults static method + $.fn.queryBuilder.defaults = { + set: function(config) { + $.extend(true, QueryBuilder.DEFAULTS, config); + }, + get: function(key) { + var config = QueryBuilder.DEFAULTS; + if (key) { + config = config.key; + } + // equivalent to a clone + return JSON.parse(JSON.stringify(config)); + } + }; + }(jQuery)); diff --git a/tests/index.html b/tests/index.html index 941216b0..15a68110 100644 --- a/tests/index.html +++ b/tests/index.html @@ -5,6 +5,7 @@ + diff --git a/tests/mocha/basic-functionality.js b/tests/mocha/basic-functionality.js new file mode 100644 index 00000000..f7ff6259 --- /dev/null +++ b/tests/mocha/basic-functionality.js @@ -0,0 +1,30 @@ +// globals: $ +describe("QueryBuilder (Basic API)", function () { + + + it("can set a different language interface", function (done) { + expect($.fn.queryBuilder.defaults.get().lang.delete_group).to.eql('Delete'); + + var original = $.fn.queryBuilder.defaults.get(); + + var head = document.getElementsByTagName('head')[0]; + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = '../../src/i18n/fr.js'; + + var checkit = function () { + expect($.fn.queryBuilder.defaults.get().lang.delete_group).to.eql('Supprimer'); + $.fn.queryBuilder.defaults.set(original); + expect($.fn.queryBuilder.defaults.get().lang.delete_group).to.eql('Delete'); + done(); + }; + + script.onreadystatechange = function () { + if (this.readyState == 'complete') checkit(); + }; + script.onload= checkit; + + head.appendChild(script); + + }); +}); \ No newline at end of file diff --git a/tests/mocha/index.html b/tests/mocha/index.html new file mode 100644 index 00000000..56f679cc --- /dev/null +++ b/tests/mocha/index.html @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ + + +
+ +
+

Output

+

+        
+
+
+ +
+ + + + + + + + + + From e0910a2f0960fd7789d71cb403f55ec5108db539 Mon Sep 17 00:00:00 2001 From: Roman Chyla Date: Thu, 12 Jun 2014 21:14:04 -0400 Subject: [PATCH 04/15] Better clone() --- src/query-builder.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/query-builder.js b/src/query-builder.js index c499ee45..79caa8be 100644 --- a/src/query-builder.js +++ b/src/query-builder.js @@ -1135,7 +1135,7 @@ config = config.key; } // equivalent to a clone - return JSON.parse(JSON.stringify(config)); + return $.extend(true, {}, config); } }; From 9978db26374a0d0f0331d06c8601056a1000ef1f Mon Sep 17 00:00:00 2001 From: Roman Chyla Date: Fri, 13 Jun 2014 00:00:57 -0400 Subject: [PATCH 05/15] Fixed bug: order of operators not respected --- bower.json | 3 ++- src/query-builder.js | 25 ++++++++++++++++++------ tests/mocha/basic-functionality.js | 31 ++++++++++++++++++++++++++++++ tests/mocha/index.html | 1 + 4 files changed, 53 insertions(+), 7 deletions(-) diff --git a/bower.json b/bower.json index 52db9fe7..7d4d53f2 100644 --- a/bower.json +++ b/bower.json @@ -39,6 +39,7 @@ "devDependencies": { "chai": "~1.8.0", "mocha": "~1.20.0", - "sinon": "http://sinonjs.org/releases/sinon-1.9.0.js" + "sinon": "http://sinonjs.org/releases/sinon-1.9.0.js", + "lodash": "~2.4.1" } } diff --git a/src/query-builder.js b/src/query-builder.js index 79caa8be..b44287b7 100644 --- a/src/query-builder.js +++ b/src/query-builder.js @@ -845,15 +845,28 @@ var res = []; - for (var i=0, l=this.operators.length; i 0) { + for (var i= 0, l=filter.operators.length; i -1) { + res.push({ + type: op, + label: this.lang['operator_'+op] + }); continue; + } } + } + } - if (filter.operators) { - if (filter.operators.indexOf(this.operators[i].type) == -1) { - continue; - } + if (res.length > 0) + return res; + + for (var i=0, l=this.operators.length; idiv.rule-operator-container>select>option'), function(x) {return $(x).val()}); + expect(vals).to.eql(['not_equal', 'contains', 'equal']); + }); + }); \ No newline at end of file diff --git a/tests/mocha/index.html b/tests/mocha/index.html index 56f679cc..0852a169 100644 --- a/tests/mocha/index.html +++ b/tests/mocha/index.html @@ -6,6 +6,7 @@ + From e88f931f04d06da5a70c820b0bc2ec0561ffb23d Mon Sep 17 00:00:00 2001 From: Roman Chyla Date: Fri, 13 Jun 2014 14:26:27 -0400 Subject: [PATCH 06/15] Basis for the ADS form --- tests/mocha/ads.html | 138 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 tests/mocha/ads.html diff --git a/tests/mocha/ads.html b/tests/mocha/ads.html new file mode 100644 index 00000000..7b3f2148 --- /dev/null +++ b/tests/mocha/ads.html @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ + + +
+ +
+

Output

+

+        
+
+
+ +
+ + + + + + + + + + From bc5bf0b6ae6db52b54b2e1d5c86d8f8d550108e8 Mon Sep 17 00:00:00 2001 From: Roman Chyla Date: Fri, 13 Jun 2014 16:23:17 -0400 Subject: [PATCH 07/15] Improved the form --- src/query-builder.js | 2 +- tests/mocha/ads.html | 59 ++++++++++++++++++++++++++++++++------------ 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/query-builder.js b/src/query-builder.js index b44287b7..89a6f97f 100644 --- a/src/query-builder.js +++ b/src/query-builder.js @@ -855,7 +855,7 @@ type: op, label: this.lang['operator_'+op] }); - continue; + break; } } } diff --git a/tests/mocha/ads.html b/tests/mocha/ads.html index 7b3f2148..b681a71a 100644 --- a/tests/mocha/ads.html +++ b/tests/mocha/ads.html @@ -55,33 +55,60 @@

Output

diff --git a/tests/mocha/basic-functionality.js b/tests/mocha/basic-functionality.js index 746f88c6..f7a3148d 100644 --- a/tests/mocha/basic-functionality.js +++ b/tests/mocha/basic-functionality.js @@ -58,4 +58,37 @@ describe("QueryBuilder (Basic API)", function () { expect(vals).to.eql(['not_equal', 'contains', 'equal']); }); + it("allows to change conditions", function() { + $('#builder').queryBuilder('destroy'); + $('#builder').queryBuilder({ + conditions: ['AND', 'OR', 'DEFOP'], + filters:[ + { + id: 'name', + label: 'Name', + type: 'string', + operators: ['not_equal', 'contains', 'equal'] + } + ] + }); + + $('#builder').queryBuilder('setRules', { + "condition": "DEFOP", + "rules": [ + { + "id": "name", + "field": "name", + "type": "string", + "input": "text", + "operator": "equal", + "value": "x" + } + ] + }); + + var vals = _.map($.find('label.btn-primary'), function(x) {return $(x).text()}); + expect(vals).to.eql(['AND', 'OR', 'DEFOP']); + expect($('#builder').find('label.btn-primary.active').text()).to.be.eql('DEFOP'); + }); + }); \ No newline at end of file From bdb911b44ce832f6ca71dce94f821932fab7bbcb Mon Sep 17 00:00:00 2001 From: Roman Chyla Date: Thu, 10 Jul 2014 18:51:39 -0400 Subject: [PATCH 10/15] wrong reference + added all field --- src/query-builder.js | 2 +- tests/mocha/ads.html | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/query-builder.js b/src/query-builder.js index 15621eb7..8321de08 100644 --- a/src/query-builder.js +++ b/src/query-builder.js @@ -321,7 +321,7 @@ $buttons = $group.find('>dt input[name$=_cond]'); if (!data.condition) { - data.condition = this.settings.default_condition; + data.condition = that.settings.default_condition; } var l = that.settings.conditions.length, cond; diff --git a/tests/mocha/ads.html b/tests/mocha/ads.html index ec654fde..40f77997 100644 --- a/tests/mocha/ads.html +++ b/tests/mocha/ads.html @@ -114,6 +114,8 @@

Output

operators: singleTokenOperators}, {id: 'title', label: 'Title', type: 'string', operators: multiTokenOperators}, + {id: '__all__', label: 'Any Field', type: 'string', + operators: multiTokenOperators}, {id: 'abstract', label: 'Abstract', type: 'string', operators: multiTokenOperators}, {id: 'keyword', label: 'Keyword', type: 'string', From bc80ce75c1f5ba7dc27d4fbae6e3711ed62453f4 Mon Sep 17 00:00:00 2001 From: Roman Chyla Date: Fri, 11 Jul 2014 23:11:26 -0400 Subject: [PATCH 11/15] Added option to insert non-defined operator --- src/query-builder.js | 12 ++++++++++- tests/mocha/basic-functionality.js | 33 ++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/query-builder.js b/src/query-builder.js index 19b59470..479c1497 100644 --- a/src/query-builder.js +++ b/src/query-builder.js @@ -365,7 +365,17 @@ $value = $rule.find('.rule-value-container'); $rule.find('.rule-filter-container select[name$=_filter]').val(rule.id).trigger('change'); - $rule.find('.rule-operator-container select[name$=_operator]').val(rule.operator).trigger('change'); + + var $operator = $rule.find('.rule-operator-container select[name$=_operator]'); + if ($operator.children('option[value="' + rule.operator + '"]').length == 0) { + if (filter.createOperatorIfNecessary) { + $operator.append($('')); + } + else { + throw 'Unknown operator: ' + rule.operator; + } + } + $operator.val(rule.operator).trigger('change'); if (operator.accept_values) { switch (filter.input) { diff --git a/tests/mocha/basic-functionality.js b/tests/mocha/basic-functionality.js index f7a3148d..3989ce09 100644 --- a/tests/mocha/basic-functionality.js +++ b/tests/mocha/basic-functionality.js @@ -91,4 +91,37 @@ describe("QueryBuilder (Basic API)", function () { expect($('#builder').find('label.btn-primary.active').text()).to.be.eql('DEFOP'); }); + it("allows to insert non-existing operator", function() { + $('#builder').queryBuilder('destroy'); + $('#builder').queryBuilder({ + filters:[ + { + id: 'name', + label: 'Name', + type: 'string', + operators: ['not_equal', 'contains', 'equal'], + createOperatorIfNecessary: true + } + ] + }); + + $('#builder').queryBuilder('setRules', { + "condition": "DEFOP", + "rules": [ + { + "id": "name", + "field": "name", + "type": "string", + "input": "text", + "operator": "in", + "value": "x" + } + ] + }); + + var vals = _.map($.find('.rule-operator-container option'), function(x) {return $(x).val()}); + expect(vals).to.eql(["not_equal", "contains", "equal", "in"]); + expect($($.find('.rule-operator-container select')).val()).to.be.eql('in'); + }); + }); \ No newline at end of file From 2d5f04b75de1847135ab1cdf40b82214265a70a8 Mon Sep 17 00:00:00 2001 From: Roman Chyla Date: Tue, 15 Jul 2014 16:42:54 -0400 Subject: [PATCH 12/15] Changes to the query builder to accommodate ADS styling --- src/ads-query-builder.css | 140 ++++++++++++++++++++++++++++++++++++++ src/query-builder.js | 6 +- tests/mocha/ads.html | 11 ++- 3 files changed, 153 insertions(+), 4 deletions(-) create mode 100644 src/ads-query-builder.css diff --git a/src/ads-query-builder.css b/src/ads-query-builder.css new file mode 100644 index 00000000..eb6059ee --- /dev/null +++ b/src/ads-query-builder.css @@ -0,0 +1,140 @@ +/*! + * jQuery QueryBuilder + * Copyright 2014 Damien "Mistic" Sorel (http://www.strangeplanet.fr) + * Licensed under MIT (http://opensource.org/licenses/MIT) + */ + +.rule-container, +.rules-group-container, +.rule-placeholder { + margin:4px 0; + border-radius:5px; + //padding:5px; + //border:1px solid #eee; + background:#fff; + background:rgba(255, 255, 255, 0.9); + +} + +/* GROUPS */ +.rules-group-container { + //padding:10px 10px 5px 10px; + border:1px solid #66afe9; + //background:#FCF9ED; + //background:rgba(250, 240, 210, 0.5); +} + .rules-group-header { + margin-bottom:10px; + } + .rules-group-header input[name$=_cond] { + display:none; + } + +/* RULES */ +.rules-list { + list-style:none; + padding:0 0 0 20px; + margin:0; +} + .rule-container {} + .rule-container.has-error { + background:#fdd; + border-color:#f99; + } + .rule-container>div:not(.rule-header) { + display:inline-block; + margin:0 5px 0 0; + vertical-align:top; + } + .rule-value-container:not(:empty) { + border-left:1px solid #ddd; + padding-left:5px; + } + .rule-value-container label { + margin-bottom:0; + } + .rule-value-container label.block { + display:block; + } + .rule-container select, + .rule-container input[type=text], + .rule-container input[type=number] { + padding:1px; + } + +/* TICKS */ +.rules-list>* { + position:relative; +} + .rules-list>*:before, + .rules-list>*:after { + content:''; + position:absolute; + left:-15px; + width:15px; + height:calc(50% + 4px); + border-color:#ccc; + //border-style:solid; + } + + .rules-list>*:before { + top:-2px; + border-width:0 0 2px 2px; + } + .rules-list>*:after { + top:50%; + border-width:0 0 0 2px; + } + + .rules-list>*:first-child:before { + top:-12px; + height:calc(50% + 14px); + } + .rules-list>*:last-child:before { + border-radius:0 0 0 4px; + } + .rules-list>*:last-child:after { + display:none; + } + +/* DRAG & DROP */ +.rule-container .drag-handle, +.rules-group-container .drag-handle { + cursor:move; + display:inline-block; +} + +.rule-container .dragged, +.rules-group-container .dragged { + opacity:0.5; +} + +.rule-placeholder { + border:1px dashed #bbb; + opacity:0.7; +} + +/* hide first delete button and drag handle */ +.query-builder>.rules-group-container>.rules-group-header [data-delete], +.query-builder>.rules-group-container>.rules-group-header .drag-handle { + display:none; +} + +.btn:active, .btn.active { + color:#66afe9; + background-color: white; +} + +.query-builder > .rules-group-container > .rules-group-header > .btn-group > .btn-primary { + display:none; +} +.btn-danger { + color: #d9534f; + background-color: white; + border-color: white; +} +.btn-success { + color: #5cb85c; + background-color: white; + border-color: white; +} \ No newline at end of file diff --git a/src/query-builder.js b/src/query-builder.js index 8321de08..41d3f7ee 100644 --- a/src/query-builder.js +++ b/src/query-builder.js @@ -320,6 +320,10 @@ $ul = $group.find('>dd>ul'), $buttons = $group.find('>dt input[name$=_cond]'); + if (!data.rules) { + throw new Error("Missing data.rules element"); + } + if (!data.condition) { data.condition = that.settings.default_condition; } @@ -1024,7 +1028,7 @@ return '\
  • \
    \ -
    \ +
    \ \
    \
    \ diff --git a/tests/mocha/ads.html b/tests/mocha/ads.html index 40f77997..f9ae68ed 100644 --- a/tests/mocha/ads.html +++ b/tests/mocha/ads.html @@ -9,7 +9,7 @@ - + @@ -71,7 +71,12 @@

    Output

    "operator_f_citations": "Get Citations", "operator_f_references": "Get References", "operator_f_trending": "Find Trending Papers", - "operator_f_instructive": "Find Instructive Papers" + "operator_f_instructive": "Find Instructive Papers", + + delete_rule: ' ', + delete_group: '', + add_rule: ' ', + add_group: ' ' }, operators: [ @@ -105,7 +110,7 @@

    Output

    // define filters $('#builder').queryBuilder({ - sortable: true, + sortable: false, filters: [ {id: 'author', label: 'Author', type: 'string', placeholder: 'Planck, Max', From 72f1d2a7472e0155e5209d17497b55b58b2384cd Mon Sep 17 00:00:00 2001 From: Roman Chyla Date: Tue, 15 Jul 2014 18:43:13 -0400 Subject: [PATCH 13/15] Added ability to extend the QB instance --- src/query-builder.js | 8 ++++++- tests/mocha/ads.html | 51 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/query-builder.js b/src/query-builder.js index b3a13eff..bb5d41ed 100644 --- a/src/query-builder.js +++ b/src/query-builder.js @@ -35,6 +35,12 @@ var QueryBuilder = function($el, options) { var that = this; + + if ('extend' in options) { + $.extend(this, options.extend); + delete options['extend']; + } + // global variables this.$el = $el; this.settings = $.extend(true, {}, QueryBuilder.DEFAULTS, options); @@ -1060,7 +1066,7 @@ var h = '\
  • \
    \ -
    \ +
    \ \
    \
    \ diff --git a/tests/mocha/ads.html b/tests/mocha/ads.html index f9ae68ed..79400783 100644 --- a/tests/mocha/ads.html +++ b/tests/mocha/ads.html @@ -110,6 +110,55 @@

    Output

    // define filters $('#builder').queryBuilder({ + extend: { + getGroupTemplate: function(group_id) { + + var conditions = []; + var l = this.settings.conditions.length, cond; + for (var i=0; i < l; i++) { + cond = this.settings.conditions[i]; + conditions.push(''); + } + conditions = conditions.join('\n'); + + var h = '\ +
    \ +
    \ +
    \ + \ + \ + \ +
    \ +
    \ + ' + conditions + '\ +
    \ + '+ (this.settings.sortable ? '
    ' : '') +' \ +
    \ +
    \ +
      \ +
      \ +
      '; + + return h; + }, + + getRuleTemplate: function(rule_id) { + var h = '\ +
    • \ +
      \ +
      \ + \ +
      \ +
      \ + '+ (this.settings.sortable ? '
      ' : '') +' \ +
      \ +
      \ +
      \ +
    • '; + + return h; + } + }, sortable: false, filters: [ @@ -183,6 +232,8 @@

      Output

      ] }); + + $('#builder').on('change.queryBuilder', function(ev) { console.log('change', ev); }); From 06e0052694fd2a518bab8a7801aa52cf0ec97405 Mon Sep 17 00:00:00 2001 From: Roman Chyla Date: Tue, 15 Jul 2014 19:18:54 -0400 Subject: [PATCH 14/15] Lighter css for the query form --- src/ads-query-builder.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ads-query-builder.css b/src/ads-query-builder.css index eb6059ee..764e626f 100644 --- a/src/ads-query-builder.css +++ b/src/ads-query-builder.css @@ -19,7 +19,7 @@ /* GROUPS */ .rules-group-container { //padding:10px 10px 5px 10px; - border:1px solid #66afe9; + border:1px dashed #66afe9; //background:#FCF9ED; //background:rgba(250, 240, 210, 0.5); } @@ -137,4 +137,7 @@ color: #5cb85c; background-color: white; border-color: white; +} +div.query-builder > .rules-group-container { + border:1px solid white; } \ No newline at end of file From 6bfa9c50004af4347135d6af95ba7b4d020b4173 Mon Sep 17 00:00:00 2001 From: Roman Chyla Date: Wed, 16 Jul 2014 20:07:40 -0400 Subject: [PATCH 15/15] Prototype of the flexible function input --- tests/mocha/ads.html | 63 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/tests/mocha/ads.html b/tests/mocha/ads.html index 79400783..26f3b827 100644 --- a/tests/mocha/ads.html +++ b/tests/mocha/ads.html @@ -108,6 +108,28 @@

      Output

      var multiTokenOperators = ['contains', 'contains_phrase', 'contains_not', 'contains_not_phrase', 'is_not_empty']; var functionOperators = ['is', 'is_not']; + + var createFunctionInputs = function(builder, profiles) { + var $target, values, $current, $container; + $container = $(''); + var $target = $(builder.getRuleInput(profiles[0].id, profiles[0])); + $target.addClass('hide'); + values = []; + + for (var i=1; i

      Output

      {id: 'full', label: 'Fulltext', type: 'string', operators: multiTokenOperators}, {id: 'function', label: 'Function', type: 'string', - operators: functionOperators}, - {id: 'f_pos', label: 'Match by Position()', type: 'string', operators: functionOperators, input: function($rule, filter) { - var $container = $rule.find('.rule-value-container'); - + return createFunctionInputs(this, [ + {id: $rule.attr('id'), label: 'function', type: 'text', placeholder: 'hidden target'}, + {id: 'any-query', label: 'function', type: 'text', placeholder: '(any valid query)'}, + {id: 'any-number', label: 'function', type: 'number', placeholder: '(any valid query)'} + ]); - return '\ - \ - start: \ - end (optional): \ - '; - } - }, + }}, + {id: 'f_pos', label: 'Match by Position()', type: 'string', + operators: functionOperators, + input: function($rule, filter) { + return createFunctionInputs(this, [ + {id: $rule.attr('id'), label: 'function', type: 'text', placeholder: 'hidden target'}, + {id: 'any-query', label: 'function', type: 'text', placeholder: '(any valid query)'}, + {id: 'any-number', label: 'function', type: 'number', placeholder: '(any valid query)'}, + { + id: 'category', + label: 'Category', + type: 'integer', + input: 'select', + values: { + 1: 'Books', + 2: 'Movies', + 3: 'Music', + 4: 'Tools', + 5: 'Goodies', + 6: 'Clothes' + }, + operators: ['in', 'not_in', 'equal', 'not_equal', 'is_null', 'is_not_null'] + } + ]); + }}, {id: 'f_citations', label: 'Find Citations()', type: 'string', placeholder: '<any valid query>', operators: functionOperators}, {id: 'f_references', label: 'Find References()', type: 'string', placeholder: '<any valid query>',