diff --git a/.gitignore b/.gitignore
index 2b7141a4..81b7cea3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,5 @@
bower_components
node_modules
-dist
doc
.sass-cache
.coverage-results
diff --git a/README.md b/README.md
index 3f5fea48..0c851396 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,24 @@
+# jQuery QueryBuilder fork
+## Forked from the original repo, which is [/mistic100/jQuery-QueryBuilder](https://github.com/mistic100/jQuery-QueryBuilder)
+## New things in my fork:
+* Bootstrap 4 Compatibility
+* Hungarian language support -- Already merged in [/mistic100/jQuery-QueryBuilder](https://github.com/mistic100/jQuery-QueryBuilder)
+
+Extra Requirements:
+* Bootstrap 4
+* FontAwesome V5.12.1 - Free
+
+Unrequired:
+* Bootstrap 3
+
+### My Profiles:
+* [LinkedIn](https://www.linkedin.com/in/tailor993/)
+* [GitHub](https://github.com/Tailor993)
+* [Facebook](https://www.facebook.com/tailor1993)
+* [Web Page for my Self-employment](https://www.tailor993.hu)
+* [Company which is made by me and my friends](https://fejlesztech.hu)
+
+# The original jQuery QueryBuilder readme.md file:
# jQuery QueryBuilder
[](https://www.npmjs.com/package/jQuery-QueryBuilder)
diff --git a/dist/css/query-builder.dark.css b/dist/css/query-builder.dark.css
new file mode 100644
index 00000000..0a09d3c2
--- /dev/null
+++ b/dist/css/query-builder.dark.css
@@ -0,0 +1,173 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Copyright 2014-2020 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+.query-builder .rules-group-container, .query-builder .rule-container, .query-builder .rule-placeholder {
+ position: relative;
+ margin: 4px 0;
+ border-radius: 5px;
+ padding: 5px;
+ border: 1px solid #111;
+ background: rgba(40, 40, 40, 0.9);
+}
+
+.query-builder .rule-container .rule-filter-container,
+.query-builder .rule-container .rule-operator-container,
+.query-builder .rule-container .rule-value-container, .query-builder .error-container, .query-builder .drag-handle {
+ display: inline-block;
+ margin: 0 5px 0 0;
+ vertical-align: middle;
+}
+
+.query-builder .rules-group-container {
+ padding: 10px;
+ padding-bottom: 6px;
+ border: 1px solid #00164A;
+ background: rgba(50, 70, 80, 0.5);
+}
+
+.query-builder .rules-group-header {
+ margin-bottom: 10px;
+}
+
+.query-builder .rules-group-header .group-conditions .btn.readonly:not(.active),
+.query-builder .rules-group-header .group-conditions input[name$='_cond'] {
+ border: 0;
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
+ white-space: nowrap;
+}
+
+.query-builder .rules-group-header .group-conditions .btn.readonly {
+ border-radius: 3px;
+}
+
+.query-builder .rules-list {
+ list-style: none;
+ padding: 0 0 0 15px;
+ margin: 0;
+}
+
+.query-builder .rule-value-container {
+ border-left: 1px solid #DDD;
+ padding-left: 5px;
+}
+
+.query-builder .rule-value-container label {
+ margin-bottom: 0;
+ font-weight: normal;
+}
+
+.query-builder .rule-value-container label.block {
+ display: block;
+}
+
+.query-builder .rule-value-container select,
+.query-builder .rule-value-container input[type='text'],
+.query-builder .rule-value-container input[type='number'] {
+ padding: 1px;
+}
+
+.query-builder .error-container {
+ display: none;
+ cursor: help;
+ color: #F00;
+}
+
+.query-builder .has-error {
+ background-color: #322;
+ border-color: #800;
+}
+
+.query-builder .has-error .error-container {
+ display: inline-block !important;
+}
+
+.query-builder .rules-list > *::before, .query-builder .rules-list > *::after {
+ content: '';
+ position: absolute;
+ left: -10px;
+ width: 10px;
+ height: calc(50% + 4px);
+ border-color: #222;
+ border-style: solid;
+}
+
+.query-builder .rules-list > *::before {
+ top: -4px;
+ border-width: 0 0 2px 2px;
+}
+
+.query-builder .rules-list > *::after {
+ top: 50%;
+ border-width: 0 0 0 2px;
+}
+
+.query-builder .rules-list > *:first-child::before {
+ top: -12px;
+ height: calc(50% + 14px);
+}
+
+.query-builder .rules-list > *:last-child::before {
+ border-radius: 0 0 0 4px;
+}
+
+.query-builder .rules-list > *:last-child::after {
+ display: none;
+}
+
+.query-builder.bt-checkbox-glyphicons .checkbox input[type='checkbox']:checked + label::after {
+ font-family: 'Glyphicons Halflings';
+ content: '\e013';
+}
+
+.query-builder.bt-checkbox-glyphicons .checkbox label::after {
+ padding-left: 4px;
+ padding-top: 2px;
+ font-size: 9px;
+}
+
+.query-builder .error-container + .tooltip .tooltip-inner {
+ color: #F22 !important;
+}
+
+.query-builder p.filter-description {
+ margin: 5px 0 0 0;
+ background: rgba(0, 170, 255, 0.2);
+ border: 1px solid #346F7B;
+ color: #AAD1E4;
+ border-radius: 5px;
+ padding: 2.5px 5px;
+ font-size: .8em;
+}
+
+.query-builder .rules-group-header [data-invert] {
+ margin-left: 5px;
+}
+
+.query-builder .drag-handle {
+ cursor: move;
+ vertical-align: middle;
+ margin-left: 5px;
+}
+
+.query-builder .dragging {
+ position: fixed;
+ opacity: .5;
+ z-index: 100;
+}
+
+.query-builder .dragging::before, .query-builder .dragging::after {
+ display: none;
+}
+
+.query-builder .rule-placeholder {
+ border: 1px dashed #BBB;
+ opacity: .7;
+}
diff --git a/dist/css/query-builder.dark.min.css b/dist/css/query-builder.dark.min.css
new file mode 100644
index 00000000..d24c9d6d
--- /dev/null
+++ b/dist/css/query-builder.dark.min.css
@@ -0,0 +1,6 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Copyright 2014-2020 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+.query-builder .rule-container,.query-builder .rule-placeholder,.query-builder .rules-group-container{position:relative;margin:4px 0;border-radius:5px;padding:5px;border:1px solid #111;background:rgba(40,40,40,.9)}.query-builder .drag-handle,.query-builder .error-container,.query-builder .rule-container .rule-filter-container,.query-builder .rule-container .rule-operator-container,.query-builder .rule-container .rule-value-container{display:inline-block;margin:0 5px 0 0;vertical-align:middle}.query-builder .rules-group-container{padding:10px;padding-bottom:6px;border:1px solid #00164a;background:rgba(50,70,80,.5)}.query-builder .rules-group-header{margin-bottom:10px}.query-builder .rules-group-header .group-conditions .btn.readonly:not(.active),.query-builder .rules-group-header .group-conditions input[name$='_cond']{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;white-space:nowrap}.query-builder .rules-group-header .group-conditions .btn.readonly{border-radius:3px}.query-builder .rules-list{list-style:none;padding:0 0 0 15px;margin:0}.query-builder .rule-value-container{border-left:1px solid #ddd;padding-left:5px}.query-builder .rule-value-container label{margin-bottom:0;font-weight:400}.query-builder .rule-value-container label.block{display:block}.query-builder .rule-value-container input[type=number],.query-builder .rule-value-container input[type=text],.query-builder .rule-value-container select{padding:1px}.query-builder .error-container{display:none;cursor:help;color:red}.query-builder .has-error{background-color:#322;border-color:#800}.query-builder .has-error .error-container{display:inline-block!important}.query-builder .rules-list>::after,.query-builder .rules-list>::before{content:'';position:absolute;left:-10px;width:10px;height:calc(50% + 4px);border-color:#222;border-style:solid}.query-builder .rules-list>::before{top:-4px;border-width:0 0 2px 2px}.query-builder .rules-list>::after{top:50%;border-width:0 0 0 2px}.query-builder .rules-list>:first-child::before{top:-12px;height:calc(50% + 14px)}.query-builder .rules-list>:last-child::before{border-radius:0 0 0 4px}.query-builder .rules-list>:last-child::after{display:none}.query-builder.bt-checkbox-glyphicons .checkbox input[type=checkbox]:checked+label::after{font-family:'Glyphicons Halflings';content:'\e013'}.query-builder.bt-checkbox-glyphicons .checkbox label::after{padding-left:4px;padding-top:2px;font-size:9px}.query-builder .error-container+.tooltip .tooltip-inner{color:#f22!important}.query-builder p.filter-description{margin:5px 0 0 0;background:rgba(0,170,255,.2);border:1px solid #346f7b;color:#aad1e4;border-radius:5px;padding:2.5px 5px;font-size:.8em}.query-builder .rules-group-header [data-invert]{margin-left:5px}.query-builder .drag-handle{cursor:move;vertical-align:middle;margin-left:5px}.query-builder .dragging{position:fixed;opacity:.5;z-index:100}.query-builder .dragging::after,.query-builder .dragging::before{display:none}.query-builder .rule-placeholder{border:1px dashed #bbb;opacity:.7}
\ No newline at end of file
diff --git a/dist/css/query-builder.default.css b/dist/css/query-builder.default.css
new file mode 100644
index 00000000..b8ba4577
--- /dev/null
+++ b/dist/css/query-builder.default.css
@@ -0,0 +1,173 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Copyright 2014-2020 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+.query-builder .rules-group-container, .query-builder .rule-container, .query-builder .rule-placeholder {
+ position: relative;
+ margin: 4px 0;
+ border-radius: 5px;
+ padding: 5px;
+ border: 1px solid #EEE;
+ background: rgba(255, 255, 255, 0.9);
+}
+
+.query-builder .rule-container .rule-filter-container,
+.query-builder .rule-container .rule-operator-container,
+.query-builder .rule-container .rule-value-container, .query-builder .error-container, .query-builder .drag-handle {
+ display: inline-block;
+ margin: 0 5px 0 0;
+ vertical-align: middle;
+}
+
+.query-builder .rules-group-container {
+ padding: 10px;
+ padding-bottom: 6px;
+ border: 1px solid #DCC896;
+ background: rgba(250, 240, 210, 0.5);
+}
+
+.query-builder .rules-group-header {
+ margin-bottom: 10px;
+}
+
+.query-builder .rules-group-header .group-conditions .btn.readonly:not(.active),
+.query-builder .rules-group-header .group-conditions input[name$='_cond'] {
+ border: 0;
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
+ white-space: nowrap;
+}
+
+.query-builder .rules-group-header .group-conditions .btn.readonly {
+ border-radius: 3px;
+}
+
+.query-builder .rules-list {
+ list-style: none;
+ padding: 0 0 0 15px;
+ margin: 0;
+}
+
+.query-builder .rule-value-container {
+ border-left: 1px solid #DDD;
+ padding-left: 5px;
+}
+
+.query-builder .rule-value-container label {
+ margin-bottom: 0;
+ font-weight: normal;
+}
+
+.query-builder .rule-value-container label.block {
+ display: block;
+}
+
+.query-builder .rule-value-container select,
+.query-builder .rule-value-container input[type='text'],
+.query-builder .rule-value-container input[type='number'] {
+ padding: 1px;
+}
+
+.query-builder .error-container {
+ display: none;
+ cursor: help;
+ color: #F00;
+}
+
+.query-builder .has-error {
+ background-color: #FDD;
+ border-color: #F99;
+}
+
+.query-builder .has-error .error-container {
+ display: inline-block !important;
+}
+
+.query-builder .rules-list > *::before, .query-builder .rules-list > *::after {
+ content: '';
+ position: absolute;
+ left: -10px;
+ width: 10px;
+ height: calc(50% + 4px);
+ border-color: #CCC;
+ border-style: solid;
+}
+
+.query-builder .rules-list > *::before {
+ top: -4px;
+ border-width: 0 0 2px 2px;
+}
+
+.query-builder .rules-list > *::after {
+ top: 50%;
+ border-width: 0 0 0 2px;
+}
+
+.query-builder .rules-list > *:first-child::before {
+ top: -12px;
+ height: calc(50% + 14px);
+}
+
+.query-builder .rules-list > *:last-child::before {
+ border-radius: 0 0 0 4px;
+}
+
+.query-builder .rules-list > *:last-child::after {
+ display: none;
+}
+
+.query-builder.bt-checkbox-glyphicons .checkbox input[type='checkbox']:checked + label::after {
+ font-family: 'Glyphicons Halflings';
+ content: '\e013';
+}
+
+.query-builder.bt-checkbox-glyphicons .checkbox label::after {
+ padding-left: 4px;
+ padding-top: 2px;
+ font-size: 9px;
+}
+
+.query-builder .error-container + .tooltip .tooltip-inner {
+ color: #F99 !important;
+}
+
+.query-builder p.filter-description {
+ margin: 5px 0 0 0;
+ background: #D9EDF7;
+ border: 1px solid #BCE8F1;
+ color: #31708F;
+ border-radius: 5px;
+ padding: 2.5px 5px;
+ font-size: .8em;
+}
+
+.query-builder .rules-group-header [data-invert] {
+ margin-left: 5px;
+}
+
+.query-builder .drag-handle {
+ cursor: move;
+ vertical-align: middle;
+ margin-left: 5px;
+}
+
+.query-builder .dragging {
+ position: fixed;
+ opacity: .5;
+ z-index: 100;
+}
+
+.query-builder .dragging::before, .query-builder .dragging::after {
+ display: none;
+}
+
+.query-builder .rule-placeholder {
+ border: 1px dashed #BBB;
+ opacity: .7;
+}
diff --git a/dist/css/query-builder.default.min.css b/dist/css/query-builder.default.min.css
new file mode 100644
index 00000000..edcb630b
--- /dev/null
+++ b/dist/css/query-builder.default.min.css
@@ -0,0 +1,6 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Copyright 2014-2020 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+.query-builder .rule-container,.query-builder .rule-placeholder,.query-builder .rules-group-container{position:relative;margin:4px 0;border-radius:5px;padding:5px;border:1px solid #eee;background:rgba(255,255,255,.9)}.query-builder .drag-handle,.query-builder .error-container,.query-builder .rule-container .rule-filter-container,.query-builder .rule-container .rule-operator-container,.query-builder .rule-container .rule-value-container{display:inline-block;margin:0 5px 0 0;vertical-align:middle}.query-builder .rules-group-container{padding:10px;padding-bottom:6px;border:1px solid #dcc896;background:rgba(250,240,210,.5)}.query-builder .rules-group-header{margin-bottom:10px}.query-builder .rules-group-header .group-conditions .btn.readonly:not(.active),.query-builder .rules-group-header .group-conditions input[name$='_cond']{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;white-space:nowrap}.query-builder .rules-group-header .group-conditions .btn.readonly{border-radius:3px}.query-builder .rules-list{list-style:none;padding:0 0 0 15px;margin:0}.query-builder .rule-value-container{border-left:1px solid #ddd;padding-left:5px}.query-builder .rule-value-container label{margin-bottom:0;font-weight:400}.query-builder .rule-value-container label.block{display:block}.query-builder .rule-value-container input[type=number],.query-builder .rule-value-container input[type=text],.query-builder .rule-value-container select{padding:1px}.query-builder .error-container{display:none;cursor:help;color:red}.query-builder .has-error{background-color:#fdd;border-color:#f99}.query-builder .has-error .error-container{display:inline-block!important}.query-builder .rules-list>::after,.query-builder .rules-list>::before{content:'';position:absolute;left:-10px;width:10px;height:calc(50% + 4px);border-color:#ccc;border-style:solid}.query-builder .rules-list>::before{top:-4px;border-width:0 0 2px 2px}.query-builder .rules-list>::after{top:50%;border-width:0 0 0 2px}.query-builder .rules-list>:first-child::before{top:-12px;height:calc(50% + 14px)}.query-builder .rules-list>:last-child::before{border-radius:0 0 0 4px}.query-builder .rules-list>:last-child::after{display:none}.query-builder.bt-checkbox-glyphicons .checkbox input[type=checkbox]:checked+label::after{font-family:'Glyphicons Halflings';content:'\e013'}.query-builder.bt-checkbox-glyphicons .checkbox label::after{padding-left:4px;padding-top:2px;font-size:9px}.query-builder .error-container+.tooltip .tooltip-inner{color:#f99!important}.query-builder p.filter-description{margin:5px 0 0 0;background:#d9edf7;border:1px solid #bce8f1;color:#31708f;border-radius:5px;padding:2.5px 5px;font-size:.8em}.query-builder .rules-group-header [data-invert]{margin-left:5px}.query-builder .drag-handle{cursor:move;vertical-align:middle;margin-left:5px}.query-builder .dragging{position:fixed;opacity:.5;z-index:100}.query-builder .dragging::after,.query-builder .dragging::before{display:none}.query-builder .rule-placeholder{border:1px dashed #bbb;opacity:.7}
\ No newline at end of file
diff --git a/dist/i18n/query-builder.ar.js b/dist/i18n/query-builder.ar.js
new file mode 100644
index 00000000..c1698b11
--- /dev/null
+++ b/dist/i18n/query-builder.ar.js
@@ -0,0 +1,80 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Arabic (ar)
+ * Author: Mohamed YOUNES, https://github.com/MedYOUNES
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['ar'] = {
+ "__locale": "Arabic (ar)",
+ "__author": "Mohamed YOUNES, https://github.com/MedYOUNES",
+ "add_rule": "إضافة حُكم",
+ "add_group": "إضافة زُمْرَة",
+ "delete_rule": "حذف",
+ "delete_group": "حذف",
+ "conditions": {
+ "AND": "و",
+ "OR": "أو"
+ },
+ "operators": {
+ "equal": "يساوي",
+ "not_equal": "غير مساوٍ",
+ "in": "في",
+ "not_in": "ليس في",
+ "less": "أقل من",
+ "less_or_equal": "أصغر أو مساو",
+ "greater": "أكبر",
+ "greater_or_equal": "أكبر أو مساو",
+ "between": "محصور بين",
+ "not_between": "غير محصور بين",
+ "begins_with": "يبدأ بـ",
+ "not_begins_with": "لا يبدأ بـ",
+ "contains": "يحتوي على",
+ "not_contains": "لا يحتوي على",
+ "ends_with": "ينتهي بـ",
+ "not_ends_with": "لا ينتهي بـ",
+ "is_empty": "فارغ",
+ "is_not_empty": "غير فارغ",
+ "is_null": "صفر",
+ "is_not_null": "ليس صفرا"
+ },
+ "errors": {
+ "no_filter": "لم تحدد أي مرشح",
+ "empty_group": "الزمرة فارغة",
+ "radio_empty": "لم تحدد أي قيمة",
+ "checkbox_empty": "لم تحدد أي قيمة",
+ "select_empty": "لم تحدد أي قيمة",
+ "string_empty": "النص فارغ",
+ "string_exceed_min_length": "النص دون الأدنى المسموح به",
+ "string_exceed_max_length": "النص فوق الأقصى المسموح به",
+ "string_invalid_format": "تركيبة غير صحيحة",
+ "number_nan": "ليس عددا",
+ "number_not_integer": "ليس عددا صحيحا",
+ "number_not_double": "ليس عددا كسريا",
+ "number_exceed_min": "العدد أصغر من الأدنى المسموح به",
+ "number_exceed_max": "العدد أكبر من الأقصى المسموح به",
+ "number_wrong_step": "أخطأت في حساب مضاعفات العدد",
+ "datetime_empty": "لم تحدد التاريخ",
+ "datetime_invalid": "صيغة التاريخ غير صحيحة",
+ "datetime_exceed_min": "التاريخ دون الأدنى المسموح به",
+ "datetime_exceed_max": "التاريخ أكبر من الأقصى المسموح به",
+ "boolean_not_valid": "ليست قيمة منطقية ثنائية",
+ "operator_not_multiple": "العامل ليس متعدد القيَم"
+ },
+ "invert": "قَلْبُ"
+};
+
+QueryBuilder.defaults({ lang_code: 'ar' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.az.js b/dist/i18n/query-builder.az.js
new file mode 100644
index 00000000..42f538b4
--- /dev/null
+++ b/dist/i18n/query-builder.az.js
@@ -0,0 +1,79 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Azerbaijan (az)
+ * Author: Megaplan, mborisv
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['az'] = {
+ "__locale": "Azerbaijan (az)",
+ "__author": "Megaplan, mborisv ",
+ "add_rule": "Əlavə etmək",
+ "add_group": "Qrup əlavə etmək",
+ "delete_rule": "Silmək",
+ "delete_group": "Silmək",
+ "conditions": {
+ "AND": "VƏ",
+ "OR": "VƏ YA"
+ },
+ "operators": {
+ "equal": "bərabərdir",
+ "not_equal": "bərabər deyil",
+ "in": "qeyd edilmişlərdən",
+ "not_in": "qeyd olunmamışlardan",
+ "less": "daha az",
+ "less_or_equal": "daha az və ya bərabər",
+ "greater": "daha çox",
+ "greater_or_equal": "daha çox və ya bərabər",
+ "between": "arasında",
+ "begins_with": "başlayır",
+ "not_begins_with": "başlamır",
+ "contains": "ibarətdir",
+ "not_contains": "yoxdur",
+ "ends_with": "başa çatır",
+ "not_ends_with": "başa çatmır",
+ "is_empty": "boş sətir",
+ "is_not_empty": "boş olmayan sətir",
+ "is_null": "boşdur",
+ "is_not_null": "boş deyil"
+ },
+ "errors": {
+ "no_filter": "Filterlər seçilməyib",
+ "empty_group": "Qrup boşdur",
+ "radio_empty": "Məna seçilməyib",
+ "checkbox_empty": "Məna seçilməyib",
+ "select_empty": "Məna seçilməyib",
+ "string_empty": "Doldurulmayıb",
+ "string_exceed_min_length": "{0} daha çox simvol olmalıdır",
+ "string_exceed_max_length": "{0} daha az simvol olmalıdır",
+ "string_invalid_format": "Yanlış format ({0})",
+ "number_nan": "Rəqəm deyil",
+ "number_not_integer": "Rəqəm deyil",
+ "number_not_double": "Rəqəm deyil",
+ "number_exceed_min": "{0} daha çox olmalıdır",
+ "number_exceed_max": "{0} daha az olmalıdır",
+ "number_wrong_step": "{0} bölünən olmalıdır",
+ "datetime_empty": "Doldurulmayıb",
+ "datetime_invalid": "Yanlış tarix formatı ({0})",
+ "datetime_exceed_min": "{0} sonra olmalıdır",
+ "datetime_exceed_max": "{0} əvvəl olmalıdır",
+ "boolean_not_valid": "Loqik olmayan",
+ "operator_not_multiple": "\"{1}\" operatoru çoxlu məna daşımır"
+ },
+ "invert": "invert"
+};
+
+QueryBuilder.defaults({ lang_code: 'az' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.bg.js b/dist/i18n/query-builder.bg.js
new file mode 100644
index 00000000..88a66e71
--- /dev/null
+++ b/dist/i18n/query-builder.bg.js
@@ -0,0 +1,79 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Bulgarian (bg)
+ * Author: Valentin Hristov
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['bg'] = {
+ "__locale": "Bulgarian (bg)",
+ "__author": "Valentin Hristov",
+ "add_rule": "Добави правило",
+ "add_group": "Добави група",
+ "delete_rule": "Изтрий",
+ "delete_group": "Изтрий",
+ "conditions": {
+ "AND": "И",
+ "OR": "ИЛИ"
+ },
+ "operators": {
+ "equal": "равно",
+ "not_equal": "различно",
+ "in": "в",
+ "not_in": "не е в",
+ "less": "по-малко",
+ "less_or_equal": "по-малко или равно",
+ "greater": "по-голям",
+ "greater_or_equal": "по-голям или равно",
+ "between": "между",
+ "not_between": "не е между",
+ "begins_with": "започва с",
+ "not_begins_with": "не започва с",
+ "contains": "съдържа",
+ "not_contains": "не съдържа",
+ "ends_with": "завършва с",
+ "not_ends_with": "не завършва с",
+ "is_empty": "е празно",
+ "is_not_empty": "не е празно",
+ "is_null": "е нищо",
+ "is_not_null": "различно от нищо"
+ },
+ "errors": {
+ "no_filter": "Не е избран филтър",
+ "empty_group": "Групата е празна",
+ "radio_empty": "Не е селектирана стойност",
+ "checkbox_empty": "Не е селектирана стойност",
+ "select_empty": "Не е селектирана стойност",
+ "string_empty": "Празна стойност",
+ "string_exceed_min_length": "Необходимо е да съдържа поне {0} символа",
+ "string_exceed_max_length": "Необходимо е да съдържа повече от {0} символа",
+ "string_invalid_format": "Невалиден формат ({0})",
+ "number_nan": "Не е число",
+ "number_not_integer": "Не е цяло число",
+ "number_not_double": "Не е реално число",
+ "number_exceed_min": "Трябва да е по-голямо от {0}",
+ "number_exceed_max": "Трябва да е по-малко от {0}",
+ "number_wrong_step": "Трябва да е кратно на {0}",
+ "datetime_empty": "Празна стойност",
+ "datetime_invalid": "Невалиден формат на дата ({0})",
+ "datetime_exceed_min": "Трябва да е след {0}",
+ "datetime_exceed_max": "Трябва да е преди {0}",
+ "boolean_not_valid": "Не е булева",
+ "operator_not_multiple": "Оператора \"{1}\" не може да приеме множество стойности"
+ }
+};
+
+QueryBuilder.defaults({ lang_code: 'bg' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.cs.js b/dist/i18n/query-builder.cs.js
new file mode 100644
index 00000000..f570387c
--- /dev/null
+++ b/dist/i18n/query-builder.cs.js
@@ -0,0 +1,79 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Čeština (cs)
+ * Author: Megaplan, mborisv
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['cs'] = {
+ "__locale": "Čeština (cs)",
+ "__author": "Megaplan, mborisv ",
+ "add_rule": "Přidat",
+ "add_group": "Přidat skupinu",
+ "delete_rule": "Odstranit",
+ "delete_group": "Odstranit skupinu",
+ "conditions": {
+ "AND": "I",
+ "OR": "NEBO"
+ },
+ "operators": {
+ "equal": "stejně",
+ "not_equal": "liší se",
+ "in": "z uvedených",
+ "not_in": "ne z uvedených",
+ "less": "méně",
+ "less_or_equal": "méně nebo stejně",
+ "greater": "více",
+ "greater_or_equal": "více nebo stejně",
+ "between": "mezi",
+ "begins_with": "začíná z",
+ "not_begins_with": "nezačíná z",
+ "contains": "obsahuje",
+ "not_contains": "neobsahuje",
+ "ends_with": "končí na",
+ "not_ends_with": "nekončí na",
+ "is_empty": "prázdný řádek",
+ "is_not_empty": "neprázdný řádek",
+ "is_null": "prázdno",
+ "is_not_null": "plno"
+ },
+ "errors": {
+ "no_filter": "není vybraný filtr",
+ "empty_group": "prázdná skupina",
+ "radio_empty": "Není udaná hodnota",
+ "checkbox_empty": "Není udaná hodnota",
+ "select_empty": "Není udaná hodnota",
+ "string_empty": "Nevyplněno",
+ "string_exceed_min_length": "Musí obsahovat více {0} symbolů",
+ "string_exceed_max_length": "Musí obsahovat méně {0} symbolů",
+ "string_invalid_format": "Nesprávný formát ({0})",
+ "number_nan": "Žádné číslo",
+ "number_not_integer": "Žádné číslo",
+ "number_not_double": "Žádné číslo",
+ "number_exceed_min": "Musí být více {0}",
+ "number_exceed_max": "Musí být méně {0}",
+ "number_wrong_step": "Musí být násobkem {0}",
+ "datetime_empty": "Nevyplněno",
+ "datetime_invalid": "Nesprávný formát datumu ({0})",
+ "datetime_exceed_min": "Musí být po {0}",
+ "datetime_exceed_max": "Musí být do {0}",
+ "boolean_not_valid": "Nelogické",
+ "operator_not_multiple": "Operátor \"{1}\" nepodporuje mnoho hodnot"
+ },
+ "invert": "invertní"
+};
+
+QueryBuilder.defaults({ lang_code: 'cs' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.da.js b/dist/i18n/query-builder.da.js
new file mode 100644
index 00000000..eabb185d
--- /dev/null
+++ b/dist/i18n/query-builder.da.js
@@ -0,0 +1,56 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Danish (da)
+ * Author: Jna Borup Coyle, github@coyle.dk
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['da'] = {
+ "__locale": "Danish (da)",
+ "__author": "Jna Borup Coyle, github@coyle.dk",
+ "add_rule": "Tilføj regel",
+ "add_group": "Tilføj gruppe",
+ "delete_rule": "Slet regel",
+ "delete_group": "Slet gruppe",
+ "conditions": {
+ "AND": "OG",
+ "OR": "ELLER"
+ },
+ "condition_and": "OG",
+ "condition_or": "ELLER",
+ "operators": {
+ "equal": "lig med",
+ "not_equal": "ikke lige med",
+ "in": "i",
+ "not_in": "ikke i",
+ "less": "mindre",
+ "less_or_equal": "mindre eller lig med",
+ "greater": "større",
+ "greater_or_equal": "større eller lig med",
+ "begins_with": "begynder med",
+ "not_begins_with": "begynder ikke med",
+ "contains": "indeholder",
+ "not_contains": "indeholder ikke",
+ "ends_with": "slutter med",
+ "not_ends_with": "slutter ikke med",
+ "is_empty": "er tom",
+ "is_not_empty": "er ikke tom",
+ "is_null": "er null",
+ "is_not_null": "er ikke null"
+ }
+};
+
+QueryBuilder.defaults({ lang_code: 'da' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.de.js b/dist/i18n/query-builder.de.js
new file mode 100644
index 00000000..8758b935
--- /dev/null
+++ b/dist/i18n/query-builder.de.js
@@ -0,0 +1,76 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: German (de)
+ * Author: "raimu"
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['de'] = {
+ "__locale": "German (de)",
+ "__author": "\"raimu\"",
+ "add_rule": "neue Regel",
+ "add_group": "neue Gruppe",
+ "delete_rule": "löschen",
+ "delete_group": "löschen",
+ "conditions": {
+ "AND": "UND",
+ "OR": "ODER"
+ },
+ "operators": {
+ "equal": "gleich",
+ "not_equal": "ungleich",
+ "in": "in",
+ "not_in": "nicht in",
+ "less": "kleiner",
+ "less_or_equal": "kleiner gleich",
+ "greater": "größer",
+ "greater_or_equal": "größer gleich",
+ "between": "zwischen",
+ "not_between": "nicht zwischen",
+ "begins_with": "beginnt mit",
+ "not_begins_with": "beginnt nicht mit",
+ "contains": "enthält",
+ "not_contains": "enthält nicht",
+ "ends_with": "endet mit",
+ "not_ends_with": "endet nicht mit",
+ "is_empty": "ist leer",
+ "is_not_empty": "ist nicht leer",
+ "is_null": "ist null",
+ "is_not_null": "ist nicht null"
+ },
+ "errors": {
+ "no_filter": "Kein Filter ausgewählt",
+ "empty_group": "Die Gruppe ist leer",
+ "radio_empty": "Kein Wert ausgewählt",
+ "checkbox_empty": "Kein Wert ausgewählt",
+ "select_empty": "Kein Wert ausgewählt",
+ "string_empty": "Leerer Wert",
+ "string_exceed_min_length": "Muss mindestens {0} Zeichen enthalten",
+ "string_exceed_max_length": "Darf nicht mehr als {0} Zeichen enthalten",
+ "string_invalid_format": "Ungültiges Format ({0})",
+ "number_nan": "Keine Zahl",
+ "number_not_integer": "Keine Ganzzahl",
+ "number_not_double": "Keine Dezimalzahl",
+ "number_exceed_min": "Muss größer als {0} sein",
+ "number_exceed_max": "Muss kleiner als {0} sein",
+ "number_wrong_step": "Muss ein Vielfaches von {0} sein",
+ "datetime_invalid": "Ungültiges Datumsformat ({0})",
+ "datetime_exceed_min": "Muss nach dem {0} sein",
+ "datetime_exceed_max": "Muss vor dem {0} sein"
+ }
+};
+
+QueryBuilder.defaults({ lang_code: 'de' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.el.js b/dist/i18n/query-builder.el.js
new file mode 100644
index 00000000..e6ecad66
--- /dev/null
+++ b/dist/i18n/query-builder.el.js
@@ -0,0 +1,80 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Greek (el)
+ * Author: Stelios Patsatzis, https://www.linkedin.com/in/stelios-patsatzis-89841561
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['el'] = {
+ "__locale": "Greek (el)",
+ "__author": "Stelios Patsatzis, https://www.linkedin.com/in/stelios-patsatzis-89841561",
+ "add_rule": "Προσθήκη Συνθήκης",
+ "add_group": "Προσθήκη Ομάδας",
+ "delete_rule": "Διαγραφή",
+ "delete_group": "Διαγραφή",
+ "conditions": {
+ "AND": "Λογικό ΚΑΙ",
+ "OR": "Λογικό Η"
+ },
+ "operators": {
+ "equal": "Ισούται με",
+ "not_equal": "Διάφορο από ",
+ "in": "Περιέχει",
+ "not_in": "Δεν Περιέχει",
+ "less": "Λιγότερο από",
+ "less_or_equal": "Λιγότερο ή Ίσο",
+ "greater": "Μεγαλύτερο από",
+ "greater_or_equal": "Μεγαλύτερο ή Ίσο",
+ "between": "Μεταξύ",
+ "not_between": "Εκτός",
+ "begins_with": "Αρχίζει με",
+ "not_begins_with": "Δεν αρχίζει με",
+ "contains": "Περιέχει",
+ "not_contains": "Δεν περιέχει",
+ "ends_with": "Τελειώνει σε",
+ "not_ends_with": "Δεν τελειώνει σε",
+ "is_empty": "Είναι άδειο",
+ "is_not_empty": "Δεν είναι άδειο",
+ "is_null": "Είναι NULL",
+ "is_not_null": "Δεν είναι NULL"
+ },
+ "errors": {
+ "no_filter": "Χωρίς φίλτρα",
+ "empty_group": "Άδεια ομάδα",
+ "radio_empty": "Χωρίς τιμή",
+ "checkbox_empty": "Χωρίς τιμή",
+ "select_empty": "Χωρίς τιμή",
+ "string_empty": "Χωρίς τιμή",
+ "string_exceed_min_length": "Ελάχιστο όριο {0} χαρακτήρων",
+ "string_exceed_max_length": "Μέγιστο όριο {0} χαρακτήρων",
+ "string_invalid_format": "Λανθασμένη μορφή ({0})",
+ "number_nan": "Δεν είναι αριθμός",
+ "number_not_integer": "Δεν είναι ακέραιος αριθμός",
+ "number_not_double": "Δεν είναι πραγματικός αριθμός",
+ "number_exceed_min": "Πρέπει να είναι μεγαλύτερο απο {0}",
+ "number_exceed_max": "Πρέπει να είναι μικρότερο απο {0}",
+ "number_wrong_step": "Πρέπει να είναι πολλαπλάσιο του {0}",
+ "datetime_empty": "Χωρίς τιμή",
+ "datetime_invalid": "Λανθασμένη μορφή ημερομηνίας ({0})",
+ "datetime_exceed_min": "Νεότερο από {0}",
+ "datetime_exceed_max": "Παλαιότερο από {0}",
+ "boolean_not_valid": "Δεν είναι BOOLEAN",
+ "operator_not_multiple": "Η συνθήκη \"{1}\" δεν μπορεί να δεχθεί πολλαπλές τιμές"
+ },
+ "invert": "Εναλλαγή"
+};
+
+QueryBuilder.defaults({ lang_code: 'el' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.en.js b/dist/i18n/query-builder.en.js
new file mode 100644
index 00000000..e756a2b8
--- /dev/null
+++ b/dist/i18n/query-builder.en.js
@@ -0,0 +1,83 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: English (en)
+ * Author: Damien "Mistic" Sorel, http://www.strangeplanet.fr
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['en'] = {
+ "__locale": "English (en)",
+ "__author": "Damien \"Mistic\" Sorel, http://www.strangeplanet.fr",
+ "add_rule": "Add rule",
+ "add_group": "Add group",
+ "delete_rule": "Delete",
+ "delete_group": "Delete",
+ "conditions": {
+ "AND": "AND",
+ "OR": "OR"
+ },
+ "operators": {
+ "equal": "equal",
+ "not_equal": "not equal",
+ "in": "in",
+ "not_in": "not in",
+ "less": "less",
+ "less_or_equal": "less or equal",
+ "greater": "greater",
+ "greater_or_equal": "greater or equal",
+ "between": "between",
+ "not_between": "not between",
+ "begins_with": "begins with",
+ "not_begins_with": "doesn't begin with",
+ "contains": "contains",
+ "not_contains": "doesn't contain",
+ "ends_with": "ends with",
+ "not_ends_with": "doesn't end with",
+ "is_empty": "is empty",
+ "is_not_empty": "is not empty",
+ "is_null": "is null",
+ "is_not_null": "is not null"
+ },
+ "errors": {
+ "no_filter": "No filter selected",
+ "empty_group": "The group is empty",
+ "radio_empty": "No value selected",
+ "checkbox_empty": "No value selected",
+ "select_empty": "No value selected",
+ "string_empty": "Empty value",
+ "string_exceed_min_length": "Must contain at least {0} characters",
+ "string_exceed_max_length": "Must not contain more than {0} characters",
+ "string_invalid_format": "Invalid format ({0})",
+ "number_nan": "Not a number",
+ "number_not_integer": "Not an integer",
+ "number_not_double": "Not a real number",
+ "number_exceed_min": "Must be greater than {0}",
+ "number_exceed_max": "Must be lower than {0}",
+ "number_wrong_step": "Must be a multiple of {0}",
+ "number_between_invalid": "Invalid values, {0} is greater than {1}",
+ "datetime_empty": "Empty value",
+ "datetime_invalid": "Invalid date format ({0})",
+ "datetime_exceed_min": "Must be after {0}",
+ "datetime_exceed_max": "Must be before {0}",
+ "datetime_between_invalid": "Invalid values, {0} is greater than {1}",
+ "boolean_not_valid": "Not a boolean",
+ "operator_not_multiple": "Operator \"{1}\" cannot accept multiple values"
+ },
+ "invert": "Invert",
+ "NOT": "NOT"
+};
+
+QueryBuilder.defaults({ lang_code: 'en' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.es.js b/dist/i18n/query-builder.es.js
new file mode 100644
index 00000000..511eb5fa
--- /dev/null
+++ b/dist/i18n/query-builder.es.js
@@ -0,0 +1,81 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Spanish (es)
+ * Author: "pyarza", "kddlb"
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['es'] = {
+ "__locale": "Spanish (es)",
+ "__author": "\"pyarza\", \"kddlb\"",
+ "add_rule": "Añadir regla",
+ "add_group": "Añadir grupo",
+ "delete_rule": "Borrar",
+ "delete_group": "Borrar",
+ "conditions": {
+ "AND": "Y",
+ "OR": "O"
+ },
+ "operators": {
+ "equal": "igual",
+ "not_equal": "distinto",
+ "in": "en",
+ "not_in": "no en",
+ "less": "menor",
+ "less_or_equal": "menor o igual",
+ "greater": "mayor",
+ "greater_or_equal": "mayor o igual",
+ "between": "entre",
+ "not_between": "no está entre",
+ "begins_with": "empieza por",
+ "not_begins_with": "no empieza por",
+ "contains": "contiene",
+ "not_contains": "no contiene",
+ "ends_with": "acaba con",
+ "not_ends_with": "no acaba con",
+ "is_empty": "está vacío",
+ "is_not_empty": "no está vacío",
+ "is_null": "es nulo",
+ "is_not_null": "no es nulo"
+ },
+ "errors": {
+ "no_filter": "No se ha seleccionado ningún filtro",
+ "empty_group": "El grupo está vacío",
+ "radio_empty": "Ningún valor seleccionado",
+ "checkbox_empty": "Ningún valor seleccionado",
+ "select_empty": "Ningún valor seleccionado",
+ "string_empty": "Cadena vacía",
+ "string_exceed_min_length": "Debe contener al menos {0} caracteres",
+ "string_exceed_max_length": "No debe contener más de {0} caracteres",
+ "string_invalid_format": "Formato inválido ({0})",
+ "number_nan": "No es un número",
+ "number_not_integer": "No es un número entero",
+ "number_not_double": "No es un número real",
+ "number_exceed_min": "Debe ser mayor que {0}",
+ "number_exceed_max": "Debe ser menor que {0}",
+ "number_wrong_step": "Debe ser múltiplo de {0}",
+ "datetime_invalid": "Formato de fecha inválido ({0})",
+ "datetime_exceed_min": "Debe ser posterior a {0}",
+ "datetime_exceed_max": "Debe ser anterior a {0}",
+ "number_between_invalid": "Valores Inválidos, {0} es mayor que {1}",
+ "datetime_empty": "Campo vacio",
+ "datetime_between_invalid": "Valores Inválidos, {0} es mayor que {1}",
+ "boolean_not_valid": "No es booleano",
+ "operator_not_multiple": "El operador \"{1}\" no puede aceptar valores multiples"
+ }
+};
+
+QueryBuilder.defaults({ lang_code: 'es' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.fa-IR.js b/dist/i18n/query-builder.fa-IR.js
new file mode 100644
index 00000000..33bdc4c1
--- /dev/null
+++ b/dist/i18n/query-builder.fa-IR.js
@@ -0,0 +1,79 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Farsi (fa-ir)
+ * Author: Behzad Sedighzade, behzad.sedighzade@gmail.com
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['fa-IR'] = {
+ "__locale": "Farsi (fa-ir)",
+ "__author": "Behzad Sedighzade, behzad.sedighzade@gmail.com",
+ "add_rule": "افزودن قاعده",
+ "add_group": "افزودن گروه",
+ "delete_rule": "حذف قاعده",
+ "delete_group": "حذف گروه",
+ "conditions": {
+ "AND": "و",
+ "OR": "یا"
+ },
+ "operators": {
+ "equal": "برابر با",
+ "not_equal": "مخالف",
+ "in": "شامل مجموعه شود",
+ "not_in": "شامل مجموعه نشود",
+ "less": "کمتر از",
+ "less_or_equal": "کمتر یا مساوی با",
+ "greater": "بزرگتر از",
+ "greater_or_equal": "بزرگتر یا مساوی با",
+ "between": "مابین",
+ "not_between": "مابین نباشد",
+ "begins_with": "شروع شود با",
+ "not_begins_with": "شروع نشود با",
+ "contains": "شامل شود",
+ "not_contains": "شامل نشود",
+ "ends_with": "خاتمه یابد با",
+ "not_ends_with": "خاتمه نیابد با",
+ "is_empty": "خالی باشد",
+ "is_not_empty": "خالی نباشد",
+ "is_null": "باشد ( null ) پوچ",
+ "is_not_null": "نباشد( null ) پوچ "
+ },
+ "errors": {
+ "no_filter": "هیچ قاعده ای انتخاب نشده است",
+ "empty_group": "گروه خالی است",
+ "radio_empty": "مقداری انتخاب نشده است",
+ "checkbox_empty": "مقداری انتخاب نشده است",
+ "select_empty": "مقداری انتخاب نشده است",
+ "string_empty": "مقدار متنی خالی است",
+ "string_exceed_min_length": "رشته حداقل باید {0} عدد حرف داشته باشد",
+ "string_exceed_max_length": "رشته حداکثر {0} عدد حرف می تواند قبول کند",
+ "string_invalid_format": "قالب رشته {0} نامعتبر ست",
+ "number_nan": "عدد وارد کنید",
+ "number_not_integer": "مقدار صحیح وارد کنید",
+ "number_not_double": "مقدار اعشاری وارد کنید",
+ "number_exceed_min": "باید از {0} بزرگتر باشد",
+ "number_exceed_max": "باید از {0} کمتر باشد",
+ "number_wrong_step": "باید مضربی از {0} باشد",
+ "datetime_empty": "مقدار تاریخ خالی وارد شده!",
+ "datetime_invalid": "قالب تاریخ ( {0} ) اشتباه است",
+ "datetime_exceed_min": "باید بعد از {0} باشد",
+ "datetime_exceed_max": "باید قبل از {0} باشد",
+ "boolean_not_valid": "مقدار دودویی وارد کنید",
+ "operator_not_multiple": "اپراتور \"{1}\" نمی تواند چند مقدار قبول کند"
+ }
+};
+
+QueryBuilder.defaults({ lang_code: 'fa-IR' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.fr.js b/dist/i18n/query-builder.fr.js
new file mode 100644
index 00000000..4b5f580c
--- /dev/null
+++ b/dist/i18n/query-builder.fr.js
@@ -0,0 +1,83 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: French (fr)
+ * Author: Damien "Mistic" Sorel, http://www.strangeplanet.fr
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['fr'] = {
+ "__locale": "French (fr)",
+ "__author": "Damien \"Mistic\" Sorel, http://www.strangeplanet.fr",
+ "add_rule": "Ajouter une règle",
+ "add_group": "Ajouter un groupe",
+ "delete_rule": "Supprimer",
+ "delete_group": "Supprimer",
+ "conditions": {
+ "AND": "ET",
+ "OR": "OU"
+ },
+ "operators": {
+ "equal": "est égal à",
+ "not_equal": "n'est pas égal à",
+ "in": "est compris dans",
+ "not_in": "n'est pas compris dans",
+ "less": "est inférieur à",
+ "less_or_equal": "est inférieur ou égal à",
+ "greater": "est supérieur à",
+ "greater_or_equal": "est supérieur ou égal à",
+ "between": "est entre",
+ "not_between": "n'est pas entre",
+ "begins_with": "commence par",
+ "not_begins_with": "ne commence pas par",
+ "contains": "contient",
+ "not_contains": "ne contient pas",
+ "ends_with": "finit par",
+ "not_ends_with": "ne finit pas par",
+ "is_empty": "est vide",
+ "is_not_empty": "n'est pas vide",
+ "is_null": "est nul",
+ "is_not_null": "n'est pas nul"
+ },
+ "errors": {
+ "no_filter": "Aucun filtre sélectionné",
+ "empty_group": "Le groupe est vide",
+ "radio_empty": "Pas de valeur selectionnée",
+ "checkbox_empty": "Pas de valeur selectionnée",
+ "select_empty": "Pas de valeur selectionnée",
+ "string_empty": "Valeur vide",
+ "string_exceed_min_length": "Doit contenir au moins {0} caractères",
+ "string_exceed_max_length": "Ne doit pas contenir plus de {0} caractères",
+ "string_invalid_format": "Format invalide ({0})",
+ "number_nan": "N'est pas un nombre",
+ "number_not_integer": "N'est pas un entier",
+ "number_not_double": "N'est pas un nombre réel",
+ "number_exceed_min": "Doit être plus grand que {0}",
+ "number_exceed_max": "Doit être plus petit que {0}",
+ "number_wrong_step": "Doit être un multiple de {0}",
+ "number_between_invalid": "Valeurs invalides, {0} est plus grand que {1}",
+ "datetime_empty": "Valeur vide",
+ "datetime_invalid": "Fomat de date invalide ({0})",
+ "datetime_exceed_min": "Doit être après {0}",
+ "datetime_exceed_max": "Doit être avant {0}",
+ "datetime_between_invalid": "Valeurs invalides, {0} est plus grand que {1}",
+ "boolean_not_valid": "N'est pas un booléen",
+ "operator_not_multiple": "L'opérateur \"{1}\" ne peut utiliser plusieurs valeurs"
+ },
+ "invert": "Inverser",
+ "NOT": "NON"
+};
+
+QueryBuilder.defaults({ lang_code: 'fr' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.he.js b/dist/i18n/query-builder.he.js
new file mode 100644
index 00000000..99799318
--- /dev/null
+++ b/dist/i18n/query-builder.he.js
@@ -0,0 +1,81 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Hebrew (he)
+ * Author: Kfir Stri https://github.com/kfirstri
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['he'] = {
+ "__locale": "Hebrew (he)",
+ "__author": "Kfir Stri https://github.com/kfirstri",
+ "add_rule": "הוסף כלל",
+ "add_group": "הוסף קבוצה",
+ "delete_rule": "מחק",
+ "delete_group": "מחק",
+ "conditions": {
+ "AND": "וגם",
+ "OR": "או"
+ },
+ "operators": {
+ "equal": "שווה ל",
+ "not_equal": "שונה מ",
+ "in": "חלק מ",
+ "not_in": "לא חלק מ",
+ "less": "פחות מ",
+ "less_or_equal": "פחות או שווה ל",
+ "greater": "גדול מ",
+ "greater_or_equal": "גדול או שווה ל",
+ "between": "בין",
+ "not_between": "לא בין",
+ "begins_with": "מתחיל ב",
+ "not_begins_with": "לא מתחיל ב",
+ "contains": "מכיל",
+ "not_contains": "לא מכיל",
+ "ends_with": "מסתיים ב",
+ "not_ends_with": "לא מסתיים ב",
+ "is_empty": "ריק",
+ "is_not_empty": "לא ריק",
+ "is_null": "חסר ערך",
+ "is_not_null": "לא חסר ערך"
+ },
+ "errors": {
+ "no_filter": "לא נבחרו מסננים",
+ "empty_group": "הקבוצה רירקה",
+ "radio_empty": "לא נבחר אף ערך",
+ "checkbox_empty": "לא נבחר אף ערך",
+ "select_empty": "לא נבחר אף ערך",
+ "string_empty": "חסר ערך",
+ "string_exceed_min_length": "המחרוזת חייבת להכיל לפחות {0} תווים",
+ "string_exceed_max_length": "המחרוזת לא יכולה להכיל יותר מ{0} תווים",
+ "string_invalid_format": "המחרוזת בפורמט שגוי ({0})",
+ "number_nan": "זהו לא מספר",
+ "number_not_integer": "המספר אינו מספר שלם",
+ "number_not_double": "המספר אינו מספר עשרוני",
+ "number_exceed_min": "המספר צריך להיות גדול מ {0}",
+ "number_exceed_max": "המספר צריך להיות קטן מ{0}",
+ "number_wrong_step": "המספר צריך להיות כפולה של {0}",
+ "datetime_empty": "תאריך ריק",
+ "datetime_invalid": "פורמט תאריך שגוי ({0})",
+ "datetime_exceed_min": "התאריך חייב להיות אחרי {0}",
+ "datetime_exceed_max": "התאריך חייב להיות לפני {0}",
+ "boolean_not_valid": "זהו לא בוליאני",
+ "operator_not_multiple": "האופרטור \"{1}\" לא יכול לקבל ערכים מרובים"
+ },
+ "invert": "הפוך שאילתא",
+ "NOT": "לא"
+};
+
+QueryBuilder.defaults({ lang_code: 'he' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.hu.js b/dist/i18n/query-builder.hu.js
new file mode 100644
index 00000000..f03f4d71
--- /dev/null
+++ b/dist/i18n/query-builder.hu.js
@@ -0,0 +1,83 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Hungarian - Magyar (hu)
+ * Author: Szabó Attila "Tailor993", https://www.tailor993.hu
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['hu'] = {
+ "__locale": "Hungarian - Magyar (hu)",
+ "__author": "Szabó Attila \"Tailor993\", https://www.tailor993.hu",
+ "add_rule": "Feltétel hozzáadása",
+ "add_group": "Csoport hozzáadása",
+ "delete_rule": "Feltétel törlése",
+ "delete_group": "Csoport törlése",
+ "conditions": {
+ "AND": "ÉS",
+ "OR": "VAGY"
+ },
+ "operators": {
+ "equal": "egyenlő",
+ "not_equal": "nem egyenlő",
+ "in": "bennevan",
+ "not_in": "nincs benne",
+ "less": "kisebb",
+ "less_or_equal": "kisebb vagy egyenlő",
+ "greater": "nagyobb",
+ "greater_or_equal": "nagyobb vagy egyenlő",
+ "between": "közötte",
+ "not_between": "nincs közötte",
+ "begins_with": "ezzel kezdődik",
+ "not_begins_with": "ezzel nem kezdődik",
+ "contains": "tartalmazza",
+ "not_contains": "nem tartalmazza",
+ "ends_with": "erre végződik",
+ "not_ends_with": "errre nem végződik",
+ "is_empty": "üres",
+ "is_not_empty": "nem üres",
+ "is_null": "null",
+ "is_not_null": "nem null"
+ },
+ "errors": {
+ "no_filter": "Nincs kiválasztott feltétel",
+ "empty_group": "A csoport üres",
+ "radio_empty": "Nincs kiválasztott érték",
+ "checkbox_empty": "Nincs kiválasztott érték",
+ "select_empty": "Nincs kiválasztott érték",
+ "string_empty": "Üres érték",
+ "string_exceed_min_length": "A megadott szöveg rövidebb a várt {0} karakternél",
+ "string_exceed_max_length": "A megadott szöveg nem tartalmazhat többet, mint {0} karaktert",
+ "string_invalid_format": "Nem megfelelő formátum ({0})",
+ "number_nan": "Nem szám",
+ "number_not_integer": "Nem egész szám (integer)",
+ "number_not_double": "Nem valós szám",
+ "number_exceed_min": "Nagyobbnak kell lennie, mint {0}",
+ "number_exceed_max": "Kisebbnek kell lennie, mint {0}",
+ "number_wrong_step": "{0} többszörösének kell lennie.",
+ "number_between_invalid": "INem megfelelő érték, {0} nagyobb, mint {1}",
+ "datetime_empty": "Üres érték",
+ "datetime_invalid": "nem megfelelő dátum formátum ({0})",
+ "datetime_exceed_min": "A dátumnak későbbinek kell lennie, mint{0}",
+ "datetime_exceed_max": "A dátumnak korábbinak kell lennie, mint {0}",
+ "datetime_between_invalid": "Nem megfelelő értékek, {0} nagyobb, mint {1}",
+ "boolean_not_valid": "Nem igaz/hamis (boolean)",
+ "operator_not_multiple": "Ez a művelet: \"{1}\" nem fogadhat el több értéket"
+ },
+ "invert": "Megfordítás (Invertálás)",
+ "NOT": "NEM"
+};
+
+QueryBuilder.defaults({ lang_code: 'hu' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.it.js b/dist/i18n/query-builder.it.js
new file mode 100644
index 00000000..944c8d04
--- /dev/null
+++ b/dist/i18n/query-builder.it.js
@@ -0,0 +1,81 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Italian (it)
+ * Author: davegraziosi, Giuseppe Lodi Rizzini
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['it'] = {
+ "__locale": "Italian (it)",
+ "__author": "davegraziosi, Giuseppe Lodi Rizzini",
+ "add_rule": "Aggiungi regola",
+ "add_group": "Aggiungi gruppo",
+ "delete_rule": "Elimina",
+ "delete_group": "Elimina",
+ "conditions": {
+ "AND": "E",
+ "OR": "O"
+ },
+ "operators": {
+ "equal": "uguale",
+ "not_equal": "non uguale",
+ "in": "in",
+ "not_in": "non in",
+ "less": "minore",
+ "less_or_equal": "minore o uguale",
+ "greater": "maggiore",
+ "greater_or_equal": "maggiore o uguale",
+ "between": "compreso tra",
+ "not_between": "non compreso tra",
+ "begins_with": "inizia con",
+ "not_begins_with": "non inizia con",
+ "contains": "contiene",
+ "not_contains": "non contiene",
+ "ends_with": "finisce con",
+ "not_ends_with": "non finisce con",
+ "is_empty": "è vuoto",
+ "is_not_empty": "non è vuoto",
+ "is_null": "è nullo",
+ "is_not_null": "non è nullo"
+ },
+ "errors": {
+ "no_filter": "Nessun filtro selezionato",
+ "empty_group": "Il gruppo è vuoto",
+ "radio_empty": "No value selected",
+ "checkbox_empty": "Nessun valore selezionato",
+ "select_empty": "Nessun valore selezionato",
+ "string_empty": "Valore vuoto",
+ "string_exceed_min_length": "Deve contenere almeno {0} caratteri",
+ "string_exceed_max_length": "Non deve contenere più di {0} caratteri",
+ "string_invalid_format": "Formato non valido ({0})",
+ "number_nan": "Non è un numero",
+ "number_not_integer": "Non è un intero",
+ "number_not_double": "Non è un numero con la virgola",
+ "number_exceed_min": "Deve essere maggiore di {0}",
+ "number_exceed_max": "Deve essere minore di {0}",
+ "number_wrong_step": "Deve essere multiplo di {0}",
+ "number_between_invalid": "Valori non validi, {0} è maggiore di {1}",
+ "datetime_empty": "Valore vuoto",
+ "datetime_invalid": "Formato data non valido ({0})",
+ "datetime_exceed_min": "Deve essere successivo a {0}",
+ "datetime_exceed_max": "Deve essere precedente a {0}",
+ "datetime_between_invalid": "Valori non validi, {0} è maggiore di {1}",
+ "boolean_not_valid": "Non è un booleano",
+ "operator_not_multiple": "L'Operatore {0} non può accettare valori multipli"
+ }
+};
+
+QueryBuilder.defaults({ lang_code: 'it' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.lt.js b/dist/i18n/query-builder.lt.js
new file mode 100644
index 00000000..c6c2ac39
--- /dev/null
+++ b/dist/i18n/query-builder.lt.js
@@ -0,0 +1,83 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Lithuanian (lt)
+ * Author: Dalius Guzauskas (aka Tichij), https://lt.linkedin.com/in/daliusg
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['lt'] = {
+ "__locale": "Lithuanian (lt)",
+ "__author": "Dalius Guzauskas (aka Tichij), https://lt.linkedin.com/in/daliusg",
+ "add_rule": "Pridėti taisyklę",
+ "add_group": "Pridėti grupę",
+ "delete_rule": "Ištrinti",
+ "delete_group": "Ištrinti",
+ "conditions": {
+ "AND": "IR",
+ "OR": "ARBA"
+ },
+ "operators": {
+ "equal": "lygu",
+ "not_equal": "nėra lygu",
+ "in": "iš nurodytų",
+ "not_in": "ne iš nurodytų",
+ "less": "mažiau",
+ "less_or_equal": "mažiau arba lygu",
+ "greater": "daugiau",
+ "greater_or_equal": "daugiau arba lygu",
+ "between": "tarp",
+ "not_between": "nėra tarp",
+ "begins_with": "prasideda",
+ "not_begins_with": "neprasideda",
+ "contains": "turi",
+ "not_contains": "neturi",
+ "ends_with": "baigiasi",
+ "not_ends_with": "nesibaigia",
+ "is_empty": "tuščia",
+ "is_not_empty": "ne tuščia",
+ "is_null": "neapibrėžta",
+ "is_not_null": "nėra neapibrėžta"
+ },
+ "errors": {
+ "no_filter": "Nepasirinktas filtras",
+ "empty_group": "Grupė tuščia",
+ "radio_empty": "Nepasirinkta reikšmė",
+ "checkbox_empty": "Nepasirinkta reikšmė",
+ "select_empty": "Nepasirinkta reikšmė",
+ "string_empty": "Tuščia reikšmė",
+ "string_exceed_min_length": "Turi būti bent {0} simbolių",
+ "string_exceed_max_length": "Turi būti ne daugiau kaip {0} simbolių",
+ "string_invalid_format": "Klaidingas formatas ({0})",
+ "number_nan": "Nėra skaičius",
+ "number_not_integer": "Ne sveikasis skaičius",
+ "number_not_double": "Ne realusis skaičius",
+ "number_exceed_min": "Turi būti daugiau už {0}",
+ "number_exceed_max": "Turi būti mažiau už {0}",
+ "number_wrong_step": "Turi būti {0} kartotinis",
+ "number_between_invalid": "Klaidingos reikšmės, {0} yra daugiau už {1}",
+ "datetime_empty": "Tuščia reikšmė",
+ "datetime_invalid": "Klaidingas datos formatas ({0})",
+ "datetime_exceed_min": "Turi būti po {0}",
+ "datetime_exceed_max": "Turi būti prieš {0}",
+ "datetime_between_invalid": "Klaidingos reikšmės, {0} yra daugiau už {1}",
+ "boolean_not_valid": "Nėra loginis tipas",
+ "operator_not_multiple": "Operatorius \"{1}\" negali priimti kelių reikšmių"
+ },
+ "invert": "Invertuoti",
+ "NOT": "NE"
+};
+
+QueryBuilder.defaults({ lang_code: 'lt' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.nl.js b/dist/i18n/query-builder.nl.js
new file mode 100644
index 00000000..4991f78d
--- /dev/null
+++ b/dist/i18n/query-builder.nl.js
@@ -0,0 +1,76 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Dutch (nl)
+ * Author: "Roywcm"
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['nl'] = {
+ "__locale": "Dutch (nl)",
+ "__author": "\"Roywcm\"",
+ "add_rule": "Nieuwe regel",
+ "add_group": "Nieuwe groep",
+ "delete_rule": "Verwijder",
+ "delete_group": "Verwijder",
+ "conditions": {
+ "AND": "EN",
+ "OR": "OF"
+ },
+ "operators": {
+ "equal": "gelijk",
+ "not_equal": "niet gelijk",
+ "in": "in",
+ "not_in": "niet in",
+ "less": "minder",
+ "less_or_equal": "minder of gelijk",
+ "greater": "groter",
+ "greater_or_equal": "groter of gelijk",
+ "between": "tussen",
+ "not_between": "niet tussen",
+ "begins_with": "begint met",
+ "not_begins_with": "begint niet met",
+ "contains": "bevat",
+ "not_contains": "bevat niet",
+ "ends_with": "eindigt met",
+ "not_ends_with": "eindigt niet met",
+ "is_empty": "is leeg",
+ "is_not_empty": "is niet leeg",
+ "is_null": "is null",
+ "is_not_null": "is niet null"
+ },
+ "errors": {
+ "no_filter": "Geen filter geselecteerd",
+ "empty_group": "De groep is leeg",
+ "radio_empty": "Geen waarde geselecteerd",
+ "checkbox_empty": "Geen waarde geselecteerd",
+ "select_empty": "Geen waarde geselecteerd",
+ "string_empty": "Lege waarde",
+ "string_exceed_min_length": "Dient minstens {0} karakters te bevatten",
+ "string_exceed_max_length": "Dient niet meer dan {0} karakters te bevatten",
+ "string_invalid_format": "Ongeldig format ({0})",
+ "number_nan": "Niet een nummer",
+ "number_not_integer": "Geen geheel getal",
+ "number_not_double": "Geen echt nummer",
+ "number_exceed_min": "Dient groter te zijn dan {0}",
+ "number_exceed_max": "Dient lager te zijn dan {0}",
+ "number_wrong_step": "Dient een veelvoud te zijn van {0}",
+ "datetime_invalid": "Ongeldige datumformat ({0})",
+ "datetime_exceed_min": "Dient na {0}",
+ "datetime_exceed_max": "Dient voor {0}"
+ }
+};
+
+QueryBuilder.defaults({ lang_code: 'nl' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.no.js b/dist/i18n/query-builder.no.js
new file mode 100644
index 00000000..59bb9446
--- /dev/null
+++ b/dist/i18n/query-builder.no.js
@@ -0,0 +1,54 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Norwegian (no)
+ * Author: Jna Borup Coyle, github@coyle.dk
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['no'] = {
+ "__locale": "Norwegian (no)",
+ "__author": "Jna Borup Coyle, github@coyle.dk",
+ "add_rule": "Legg til regel",
+ "add_group": "Legg til gruppe",
+ "delete_rule": "Slett regel",
+ "delete_group": "Slett gruppe",
+ "conditions": {
+ "AND": "OG",
+ "OR": "ELLER"
+ },
+ "operators": {
+ "equal": "er lik",
+ "not_equal": "er ikke lik",
+ "in": "finnes i",
+ "not_in": "finnes ikke i",
+ "less": "er mindre enn",
+ "less_or_equal": "er mindre eller lik",
+ "greater": "er større enn",
+ "greater_or_equal": "er større eller lik",
+ "begins_with": "begynner med",
+ "not_begins_with": "begynner ikke med",
+ "contains": "inneholder",
+ "not_contains": "inneholder ikke",
+ "ends_with": "slutter med",
+ "not_ends_with": "slutter ikke med",
+ "is_empty": "er tom",
+ "is_not_empty": "er ikke tom",
+ "is_null": "er null",
+ "is_not_null": "er ikke null"
+ }
+};
+
+QueryBuilder.defaults({ lang_code: 'no' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.pl.js b/dist/i18n/query-builder.pl.js
new file mode 100644
index 00000000..a8307ac6
--- /dev/null
+++ b/dist/i18n/query-builder.pl.js
@@ -0,0 +1,80 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Polish (pl)
+ * Author: Artur Smolarek
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['pl'] = {
+ "__locale": "Polish (pl)",
+ "__author": "Artur Smolarek",
+ "add_rule": "Dodaj regułę",
+ "add_group": "Dodaj grupę",
+ "delete_rule": "Usuń",
+ "delete_group": "Usuń",
+ "conditions": {
+ "AND": "ORAZ",
+ "OR": "LUB"
+ },
+ "operators": {
+ "equal": "równa się",
+ "not_equal": "jest różne od",
+ "in": "zawiera",
+ "not_in": "nie zawiera",
+ "less": "mniejsze",
+ "less_or_equal": "mniejsze lub równe",
+ "greater": "większe",
+ "greater_or_equal": "większe lub równe",
+ "between": "pomiędzy",
+ "not_between": "nie jest pomiędzy",
+ "begins_with": "rozpoczyna się od",
+ "not_begins_with": "nie rozpoczyna się od",
+ "contains": "zawiera",
+ "not_contains": "nie zawiera",
+ "ends_with": "kończy się na",
+ "not_ends_with": "nie kończy się na",
+ "is_empty": "jest puste",
+ "is_not_empty": "nie jest puste",
+ "is_null": "jest niezdefiniowane",
+ "is_not_null": "nie jest niezdefiniowane"
+ },
+ "errors": {
+ "no_filter": "Nie wybrano żadnego filtra",
+ "empty_group": "Grupa jest pusta",
+ "radio_empty": "Nie wybrano wartości",
+ "checkbox_empty": "Nie wybrano wartości",
+ "select_empty": "Nie wybrano wartości",
+ "string_empty": "Nie wpisano wartości",
+ "string_exceed_min_length": "Minimalna długość to {0} znaków",
+ "string_exceed_max_length": "Maksymalna długość to {0} znaków",
+ "string_invalid_format": "Nieprawidłowy format ({0})",
+ "number_nan": "To nie jest liczba",
+ "number_not_integer": "To nie jest liczba całkowita",
+ "number_not_double": "To nie jest liczba rzeczywista",
+ "number_exceed_min": "Musi być większe niż {0}",
+ "number_exceed_max": "Musi być mniejsze niż {0}",
+ "number_wrong_step": "Musi być wielokrotnością {0}",
+ "datetime_empty": "Nie wybrano wartości",
+ "datetime_invalid": "Nieprawidłowy format daty ({0})",
+ "datetime_exceed_min": "Musi być po {0}",
+ "datetime_exceed_max": "Musi być przed {0}",
+ "boolean_not_valid": "Niepoprawna wartość logiczna",
+ "operator_not_multiple": "Operator \"{1}\" nie przyjmuje wielu wartości"
+ },
+ "invert": "Odwróć"
+};
+
+QueryBuilder.defaults({ lang_code: 'pl' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.pt-BR.js b/dist/i18n/query-builder.pt-BR.js
new file mode 100644
index 00000000..8412f081
--- /dev/null
+++ b/dist/i18n/query-builder.pt-BR.js
@@ -0,0 +1,80 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Brazilian Portuguese (pr-BR)
+ * Author: Leandro Gehlen, leandrogehlen@gmail.com; Marcos Ferretti, marcosvferretti@gmail.com
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['pt-BR'] = {
+ "__locale": "Brazilian Portuguese (pr-BR)",
+ "__author": "Leandro Gehlen, leandrogehlen@gmail.com; Marcos Ferretti, marcosvferretti@gmail.com",
+ "add_rule": "Nova Regra",
+ "add_group": "Novo Grupo",
+ "delete_rule": "Excluir",
+ "delete_group": "Excluir",
+ "conditions": {
+ "AND": "E",
+ "OR": "OU"
+ },
+ "operators": {
+ "equal": "Igual",
+ "not_equal": "Diferente",
+ "in": "Contido",
+ "not_in": "Não contido",
+ "less": "Menor",
+ "less_or_equal": "Menor ou igual",
+ "greater": "Maior",
+ "greater_or_equal": "Maior ou igual",
+ "between": "Entre",
+ "not_between": "Não entre",
+ "begins_with": "Iniciando com",
+ "not_begins_with": "Não iniciando com",
+ "contains": "Contém",
+ "not_contains": "Não contém",
+ "ends_with": "Terminando com",
+ "not_ends_with": "Terminando sem",
+ "is_empty": "É vazio",
+ "is_not_empty": "Não é vazio",
+ "is_null": "É nulo",
+ "is_not_null": "Não é nulo"
+ },
+ "errors": {
+ "no_filter": "Nenhum filtro selecionado",
+ "empty_group": "O grupo está vazio",
+ "radio_empty": "Nenhum valor selecionado",
+ "checkbox_empty": "Nenhum valor selecionado",
+ "select_empty": "Nenhum valor selecionado",
+ "string_empty": "Valor vazio",
+ "string_exceed_min_length": "É necessário conter pelo menos {0} caracteres",
+ "string_exceed_max_length": "É necessário conter mais de {0} caracteres",
+ "string_invalid_format": "Formato inválido ({0})",
+ "number_nan": "Não é um número",
+ "number_not_integer": "Não é um número inteiro",
+ "number_not_double": "Não é um número real",
+ "number_exceed_min": "É necessário ser maior que {0}",
+ "number_exceed_max": "É necessário ser menor que {0}",
+ "number_wrong_step": "É necessário ser múltiplo de {0}",
+ "datetime_invalid": "Formato de data inválido ({0})",
+ "datetime_exceed_min": "É necessário ser superior a {0}",
+ "datetime_exceed_max": "É necessário ser inferior a {0}",
+ "datetime_empty": "Nenhuma data selecionada",
+ "boolean_not_valid": "Não é um valor booleano",
+ "operator_not_multiple": "O operador \"{1}\" não aceita valores múltiplos"
+ },
+ "invert": "Inverter"
+};
+
+QueryBuilder.defaults({ lang_code: 'pt-BR' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.pt-PT.js b/dist/i18n/query-builder.pt-PT.js
new file mode 100644
index 00000000..7051ed10
--- /dev/null
+++ b/dist/i18n/query-builder.pt-PT.js
@@ -0,0 +1,75 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Portuguese (pt-PT)
+ * Author: Miguel Guerreiro, migas.csi@gmail.com
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['pt-PT'] = {
+ "__locale": "Portuguese (pt-PT)",
+ "__author": "Miguel Guerreiro, migas.csi@gmail.com",
+ "add_rule": "Nova Regra",
+ "add_group": "Novo Grupo",
+ "delete_rule": "Excluir",
+ "delete_group": "Excluir",
+ "conditions": {
+ "AND": "E",
+ "OR": "OU"
+ },
+ "operators": {
+ "equal": "Igual a",
+ "not_equal": "Diferente de",
+ "in": "Contido",
+ "not_in": "Não contido",
+ "less": "Menor que",
+ "less_or_equal": "Menor ou igual a",
+ "greater": "Maior que",
+ "greater_or_equal": "Maior ou igual que",
+ "between": "Entre",
+ "begins_with": "Começar por",
+ "not_begins_with": "Não a começar por",
+ "contains": "Contém",
+ "not_contains": "Não contém",
+ "ends_with": "Terminando com",
+ "not_ends_with": "Terminando sem",
+ "is_empty": "É vazio",
+ "is_not_empty": "Não é vazio",
+ "is_null": "É nulo",
+ "is_not_null": "Não é nulo"
+ },
+ "errors": {
+ "no_filter": "Nenhum filtro selecionado",
+ "empty_group": "O grupo está vazio",
+ "radio_empty": "Nenhum valor selecionado",
+ "checkbox_empty": "Nenhum valor selecionado",
+ "select_empty": "Nenhum valor selecionado",
+ "string_empty": "Valor vazio",
+ "string_exceed_min_length": "É necessário conter pelo menos {0} caracteres",
+ "string_exceed_max_length": "É necessário conter mais de {0} caracteres",
+ "string_invalid_format": "Formato inválido ({0})",
+ "number_nan": "Não é um número",
+ "number_not_integer": "Não é um número inteiro",
+ "number_not_double": "Não é um número real",
+ "number_exceed_min": "É necessário ser maior que {0}",
+ "number_exceed_max": "É necessário ser menor que {0}",
+ "number_wrong_step": "É necessário ser múltiplo de {0}",
+ "datetime_invalid": "Formato de data inválido ({0})",
+ "datetime_exceed_min": "É necessário ser superior a {0}",
+ "datetime_exceed_max": "É necessário ser inferior a {0}"
+ }
+};
+
+QueryBuilder.defaults({ lang_code: 'pt-PT' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.ro.js b/dist/i18n/query-builder.ro.js
new file mode 100644
index 00000000..e0c1c04e
--- /dev/null
+++ b/dist/i18n/query-builder.ro.js
@@ -0,0 +1,54 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Romanian (ro)
+ * Author: ArianServ
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['ro'] = {
+ "__locale": "Romanian (ro)",
+ "__author": "ArianServ",
+ "add_rule": "Adaugă regulă",
+ "add_group": "Adaugă grup",
+ "delete_rule": "Şterge",
+ "delete_group": "Şterge",
+ "conditions": {
+ "AND": "ŞI",
+ "OR": "SAU"
+ },
+ "operators": {
+ "equal": "egal",
+ "not_equal": "diferit",
+ "in": "în",
+ "not_in": "nu în",
+ "less": "mai puţin",
+ "less_or_equal": "mai puţin sau egal",
+ "greater": "mai mare",
+ "greater_or_equal": "mai mare sau egal",
+ "begins_with": "începe cu",
+ "not_begins_with": "nu începe cu",
+ "contains": "conţine",
+ "not_contains": "nu conţine",
+ "ends_with": "se termină cu",
+ "not_ends_with": "nu se termină cu",
+ "is_empty": "este gol",
+ "is_not_empty": "nu este gol",
+ "is_null": "e nul",
+ "is_not_null": "nu e nul"
+ }
+};
+
+QueryBuilder.defaults({ lang_code: 'ro' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.ru.js b/dist/i18n/query-builder.ru.js
new file mode 100644
index 00000000..796bbb15
--- /dev/null
+++ b/dist/i18n/query-builder.ru.js
@@ -0,0 +1,81 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Russian (ru)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['ru'] = {
+ "__locale": "Russian (ru)",
+ "add_rule": "Добавить",
+ "add_group": "Добавить группу",
+ "delete_rule": "Удалить",
+ "delete_group": "Удалить",
+ "conditions": {
+ "AND": "И",
+ "OR": "ИЛИ"
+ },
+ "operators": {
+ "equal": "равно",
+ "not_equal": "не равно",
+ "in": "из указанных",
+ "not_in": "не из указанных",
+ "less": "меньше",
+ "less_or_equal": "меньше или равно",
+ "greater": "больше",
+ "greater_or_equal": "больше или равно",
+ "between": "между",
+ "not_between": "не между",
+ "begins_with": "начинается с",
+ "not_begins_with": "не начинается с",
+ "contains": "содержит",
+ "not_contains": "не содержит",
+ "ends_with": "оканчивается на",
+ "not_ends_with": "не оканчивается на",
+ "is_empty": "пустая строка",
+ "is_not_empty": "не пустая строка",
+ "is_null": "пусто",
+ "is_not_null": "не пусто"
+ },
+ "errors": {
+ "no_filter": "Фильтр не выбран",
+ "empty_group": "Группа пуста",
+ "radio_empty": "Не выбрано значение",
+ "checkbox_empty": "Не выбрано значение",
+ "select_empty": "Не выбрано значение",
+ "string_empty": "Не заполнено",
+ "string_exceed_min_length": "Должен содержать больше {0} символов",
+ "string_exceed_max_length": "Должен содержать меньше {0} символов",
+ "string_invalid_format": "Неверный формат ({0})",
+ "number_nan": "Не число",
+ "number_not_integer": "Не число",
+ "number_not_double": "Не число",
+ "number_exceed_min": "Должно быть больше {0}",
+ "number_exceed_max": "Должно быть меньше, чем {0}",
+ "number_wrong_step": "Должно быть кратно {0}",
+ "number_between_invalid": "Недопустимые значения, {0} больше {1}",
+ "datetime_empty": "Не заполнено",
+ "datetime_invalid": "Неверный формат даты ({0})",
+ "datetime_exceed_min": "Должно быть, после {0}",
+ "datetime_exceed_max": "Должно быть, до {0}",
+ "datetime_between_invalid": "Недопустимые значения, {0} больше {1}",
+ "boolean_not_valid": "Не логическое",
+ "operator_not_multiple": "Оператор \"{1}\" не поддерживает много значений"
+ },
+ "invert": "Инвертировать",
+ "NOT": "НЕ"
+};
+
+QueryBuilder.defaults({ lang_code: 'ru' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.sk.js b/dist/i18n/query-builder.sk.js
new file mode 100644
index 00000000..26859408
--- /dev/null
+++ b/dist/i18n/query-builder.sk.js
@@ -0,0 +1,83 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Slovensky (sk)
+ * Author: k2s
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['sk'] = {
+ "__locale": "Slovensky (sk)",
+ "__author": "k2s",
+ "add_rule": "Pridať podmienku",
+ "add_group": "Pridať skupinu",
+ "delete_rule": "Zmazať",
+ "delete_group": "Zmazať",
+ "conditions": {
+ "AND": "A",
+ "OR": "ALEBO"
+ },
+ "operators": {
+ "equal": "rovné",
+ "not_equal": "nerovné",
+ "in": "v",
+ "not_in": "nie v",
+ "less": "menej",
+ "less_or_equal": "menej alebo rovné",
+ "greater": "väčšie",
+ "greater_or_equal": "väčšie alebo rovné",
+ "between": "medzi",
+ "not_between": "nie medzi",
+ "begins_with": "začína na",
+ "not_begins_with": "nezačína na",
+ "contains": "obsahuje",
+ "not_contains": "neobsahuje",
+ "ends_with": "končí na",
+ "not_ends_with": "nekončí na",
+ "is_empty": "je prázdne",
+ "is_not_empty": "nie je prázdne",
+ "is_null": "je null",
+ "is_not_null": "nie je null"
+ },
+ "errors": {
+ "no_filter": "Nie je zvolený filter",
+ "empty_group": "Skupina je prázdna",
+ "radio_empty": "Nie je označená hodnota",
+ "checkbox_empty": "Nie je označená hodnota",
+ "select_empty": "Nie je označená hodnota",
+ "string_empty": "Prázdna hodnota",
+ "string_exceed_min_length": "Musí obsahovať aspon {0} znakov",
+ "string_exceed_max_length": "Nesmie obsahovať viac ako {0} znakov",
+ "string_invalid_format": "Chybný formát ({0})",
+ "number_nan": "Nie je číslo",
+ "number_not_integer": "Nie je celé číslo",
+ "number_not_double": "Nie je desatinné číslo",
+ "number_exceed_min": "Musí byť väčšie ako {0}",
+ "number_exceed_max": "Musí byť menšie ako {0}",
+ "number_wrong_step": "Musí byť násobkom čísla {0}",
+ "number_between_invalid": "Chybné hodnoty, {0} je väčšie ako {1}",
+ "datetime_empty": "Prázdna hodnota",
+ "datetime_invalid": "Chybný formát dátumu ({0})",
+ "datetime_exceed_min": "Musí byť neskôr ako {0}",
+ "datetime_exceed_max": "Musí byť skôr ako {0}",
+ "datetime_between_invalid": "Chybné hodnoty, {0} je neskôr ako {1}",
+ "boolean_not_valid": "Neplatné áno/nie",
+ "operator_not_multiple": "Operátor '{1}' nepodporuje viacero hodnôt"
+ },
+ "invert": "Invertný",
+ "NOT": "NIE"
+};
+
+QueryBuilder.defaults({ lang_code: 'sk' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.sq.js b/dist/i18n/query-builder.sq.js
new file mode 100644
index 00000000..10417066
--- /dev/null
+++ b/dist/i18n/query-builder.sq.js
@@ -0,0 +1,78 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Albanian (sq)
+ * Author: Tomor Pupovci
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['sq'] = {
+ "__locale": "Albanian (sq)",
+ "__author": "Tomor Pupovci",
+ "add_rule": "Shto rregull",
+ "add_group": "Shto grup",
+ "delete_rule": "Fshij",
+ "delete_group": "Fshij",
+ "conditions": {
+ "AND": "DHE",
+ "OR": "OSE"
+ },
+ "operators": {
+ "equal": "barabartë",
+ "not_equal": "e ndryshme prej",
+ "in": "në",
+ "not_in": "jo në",
+ "less": "më e vogël",
+ "less_or_equal": "më e vogël ose e barabartë me",
+ "greater": "më e madhe",
+ "greater_or_equal": "më e madhe ose e barabartë",
+ "between": "në mes",
+ "begins_with": "fillon me",
+ "not_begins_with": "nuk fillon me",
+ "contains": "përmban",
+ "not_contains": "nuk përmban",
+ "ends_with": "mbaron me",
+ "not_ends_with": "nuk mbaron me",
+ "is_empty": "është e zbrazët",
+ "is_not_empty": "nuk është e zbrazët",
+ "is_null": "është null",
+ "is_not_null": "nuk është null"
+ },
+ "errors": {
+ "no_filter": "Nuk ka filter të zgjedhur",
+ "empty_group": "Grupi është i zbrazët",
+ "radio_empty": "Nuk ka vlerë të zgjedhur",
+ "checkbox_empty": "Nuk ka vlerë të zgjedhur",
+ "select_empty": "Nuk ka vlerë të zgjedhur",
+ "string_empty": "Vlerë e zbrazët",
+ "string_exceed_min_length": "Duhet të përmbajë së paku {0} karaktere",
+ "string_exceed_max_length": "Nuk duhet të përmbajë më shumë se {0} karaktere",
+ "string_invalid_format": "Format i pasaktë ({0})",
+ "number_nan": "Nuk është numër",
+ "number_not_integer": "Nuk është numër i plotë",
+ "number_not_double": "Nuk është numër me presje",
+ "number_exceed_min": "Duhet të jetë më i madh se {0}",
+ "number_exceed_max": "Duhet të jetë më i vogël se {0}",
+ "number_wrong_step": "Duhet të jetë shumëfish i {0}",
+ "datetime_empty": "Vlerë e zbrazët",
+ "datetime_invalid": "Format i pasaktë i datës ({0})",
+ "datetime_exceed_min": "Duhet të jetë pas {0}",
+ "datetime_exceed_max": "Duhet të jetë para {0}",
+ "boolean_not_valid": "Nuk është boolean",
+ "operator_not_multiple": "Operatori \"{1}\" nuk mund të pranojë vlera të shumëfishta"
+ }
+};
+
+QueryBuilder.defaults({ lang_code: 'sq' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.sw.js b/dist/i18n/query-builder.sw.js
new file mode 100644
index 00000000..882cc3ee
--- /dev/null
+++ b/dist/i18n/query-builder.sw.js
@@ -0,0 +1,83 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Swahili (sw)
+ * Author: Timothy Anyona
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['sw'] = {
+ "__locale": "Swahili (sw)",
+ "__author": "Timothy Anyona",
+ "add_rule": "Ongeza kanuni",
+ "add_group": "Ongeza kikundi",
+ "delete_rule": "Futa",
+ "delete_group": "Futa",
+ "conditions": {
+ "AND": "NA",
+ "OR": "AU"
+ },
+ "operators": {
+ "equal": "ni",
+ "not_equal": "sio",
+ "in": "mojawapo ya",
+ "not_in": "sio mojawapo ya",
+ "less": "isiyozidi",
+ "less_or_equal": "isiyozidi au ni sawa na",
+ "greater": "inayozidi",
+ "greater_or_equal": "inayozidi au ni sawa na",
+ "between": "kati ya",
+ "not_between": "isiyo kati ya",
+ "begins_with": "inaanza na",
+ "not_begins_with": "isiyoanza na",
+ "contains": "ina",
+ "not_contains": "haina",
+ "ends_with": "inaisha na",
+ "not_ends_with": "isiyoisha na",
+ "is_empty": "ni tupu",
+ "is_not_empty": "sio tupu",
+ "is_null": "ni batili",
+ "is_not_null": "sio batili"
+ },
+ "errors": {
+ "no_filter": "Chujio halijachaguliwa",
+ "empty_group": "Kikundi ki tupu",
+ "radio_empty": "Thamani haijachaguliwa",
+ "checkbox_empty": "Thamani haijachaguliwa",
+ "select_empty": "Thamani haijachaguliwa",
+ "string_empty": "Thamani tupu",
+ "string_exceed_min_length": "Lazima iwe na vibambo visiopungua {0}",
+ "string_exceed_max_length": "Haifai kuwa na vibambo zaidi ya {0}",
+ "string_invalid_format": "Fomati batili ({0})",
+ "number_nan": "Sio nambari",
+ "number_not_integer": "Sio namba kamili",
+ "number_not_double": "Sio namba desimali",
+ "number_exceed_min": "Lazima iwe zaidi ya {0}",
+ "number_exceed_max": "Lazima iwe chini ya {0}",
+ "number_wrong_step": "Lazima iwe kigawe cha {0}",
+ "number_between_invalid": "Thamani batili, {0} ni kubwa kuliko {1}",
+ "datetime_empty": "Thamani tupu",
+ "datetime_invalid": "Fomati tarehe batili ({0})",
+ "datetime_exceed_min": "Lazima iwe baada ya {0}",
+ "datetime_exceed_max": "Lazima iwe kabla ya {0}",
+ "datetime_between_invalid": "Thamani batili, {0} ni baada ya {1}",
+ "boolean_not_valid": "Sio buleani",
+ "operator_not_multiple": "Opereta \"{1}\" haikubali thamani nyingi"
+ },
+ "invert": "Pindua",
+ "NOT": "SIO"
+};
+
+QueryBuilder.defaults({ lang_code: 'sw' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.tr.js b/dist/i18n/query-builder.tr.js
new file mode 100644
index 00000000..58c5f9d4
--- /dev/null
+++ b/dist/i18n/query-builder.tr.js
@@ -0,0 +1,82 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Turkish (tr)
+ * Author: Aykut Alpgiray Ateş
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['tr'] = {
+ "__locale": "Turkish (tr)",
+ "__author": "Aykut Alpgiray Ateş",
+ "add_rule": "Kural Ekle",
+ "add_group": "Grup Ekle",
+ "delete_rule": "Sil",
+ "delete_group": "Sil",
+ "conditions": {
+ "AND": "Ve",
+ "OR": "Veya"
+ },
+ "operators": {
+ "equal": "eşit",
+ "not_equal": "eşit değil",
+ "in": "içinde",
+ "not_in": "içinde değil",
+ "less": "küçük",
+ "less_or_equal": "küçük veya eşit",
+ "greater": "büyük",
+ "greater_or_equal": "büyük veya eşit",
+ "between": "arasında",
+ "not_between": "arasında değil",
+ "begins_with": "ile başlayan",
+ "not_begins_with": "ile başlamayan",
+ "contains": "içeren",
+ "not_contains": "içermeyen",
+ "ends_with": "ile biten",
+ "not_ends_with": "ile bitmeyen",
+ "is_empty": "boş ise",
+ "is_not_empty": "boş değil ise",
+ "is_null": "var ise",
+ "is_not_null": "yok ise"
+ },
+ "errors": {
+ "no_filter": "Bir filtre seçili değil",
+ "empty_group": "Grup bir eleman içermiyor",
+ "radio_empty": "Seçim yapılmalı",
+ "checkbox_empty": "Seçim yapılmalı",
+ "select_empty": "Seçim yapılmalı",
+ "string_empty": "Bir metin girilmeli",
+ "string_exceed_min_length": "En az {0} karakter girilmeli",
+ "string_exceed_max_length": "En fazla {0} karakter girilebilir",
+ "string_invalid_format": "Uyumsuz format ({0})",
+ "number_nan": "Sayı değil",
+ "number_not_integer": "Tam sayı değil",
+ "number_not_double": "Ondalıklı sayı değil",
+ "number_exceed_min": "Sayı {0}'den/dan daha büyük olmalı",
+ "number_exceed_max": "Sayı {0}'den/dan daha küçük olmalı",
+ "number_wrong_step": "{0} veya katı olmalı",
+ "number_between_invalid": "Geçersiz değerler, {0} değeri {1} değerinden büyük",
+ "datetime_empty": "Tarih Seçilmemiş",
+ "datetime_invalid": "Uygun olmayan tarih formatı ({0})",
+ "datetime_exceed_min": "{0} Tarihinden daha sonrası olmalı.",
+ "datetime_exceed_max": "{0} Tarihinden daha öncesi olmalı.",
+ "datetime_between_invalid": "Geçersiz değerler, {0} değeri {1} değerinden büyük",
+ "boolean_not_valid": "Değer Doğru/Yanlış(bool) olmalı",
+ "operator_not_multiple": "Operatör \"{1}\" birden fazla değer kabul etmiyor"
+ },
+ "invert": "Ters Çevir"
+};
+
+QueryBuilder.defaults({ lang_code: 'tr' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.ua.js b/dist/i18n/query-builder.ua.js
new file mode 100644
index 00000000..3925c29a
--- /dev/null
+++ b/dist/i18n/query-builder.ua.js
@@ -0,0 +1,79 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Ukrainian (ua)
+ * Author: Megaplan, mborisv
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['ua'] = {
+ "__locale": "Ukrainian (ua)",
+ "__author": "Megaplan, mborisv ",
+ "add_rule": "Додати",
+ "add_group": "Додати групу",
+ "delete_rule": "Видалити",
+ "delete_group": "Видалити",
+ "conditions": {
+ "AND": "І",
+ "OR": "АБО"
+ },
+ "operators": {
+ "equal": "дорівнює",
+ "not_equal": "не дорівнює",
+ "in": "з вказаних",
+ "not_in": "не з вказаних",
+ "less": "менше",
+ "less_or_equal": "менше або дорівнюж",
+ "greater": "більше",
+ "greater_or_equal": "більше або дорівнює",
+ "between": "між",
+ "begins_with": "починається з",
+ "not_begins_with": "не починається з",
+ "contains": "містить",
+ "not_contains": "не містить",
+ "ends_with": "закінчується на",
+ "not_ends_with": "не не закінчується на",
+ "is_empty": "порожній рядок",
+ "is_not_empty": "не порожній рядок",
+ "is_null": "порожньо",
+ "is_not_null": "не порожньо"
+ },
+ "errors": {
+ "no_filter": "Фільтр не вибраний",
+ "empty_group": "Група порожня",
+ "radio_empty": "Значення не вибрано",
+ "checkbox_empty": "Значення не вибрано",
+ "select_empty": "Значення не вибрано",
+ "string_empty": "Не заповнено",
+ "string_exceed_min_length": "Повинен містити більше {0} символів",
+ "string_exceed_max_length": "Повинен містити менше {0} символів",
+ "string_invalid_format": "Невірний формат ({0})",
+ "number_nan": "Не число",
+ "number_not_integer": "Не число",
+ "number_not_double": "Не число",
+ "number_exceed_min": "Повинне бути більше {0}",
+ "number_exceed_max": "Повинне бути менше, ніж {0}",
+ "number_wrong_step": "Повинне бути кратне {0}",
+ "datetime_empty": "Не заповнено",
+ "datetime_invalid": "Невірний формат дати ({0})",
+ "datetime_exceed_min": "Повинне бути, після {0}",
+ "datetime_exceed_max": "Повинне бути, до {0}",
+ "boolean_not_valid": "Не логічне",
+ "operator_not_multiple": "Оператор \"{1}\" не підтримує багато значень"
+ },
+ "invert": "інвертувати"
+};
+
+QueryBuilder.defaults({ lang_code: 'ua' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.zh-CN.js b/dist/i18n/query-builder.zh-CN.js
new file mode 100644
index 00000000..5c2784da
--- /dev/null
+++ b/dist/i18n/query-builder.zh-CN.js
@@ -0,0 +1,80 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: Simplified Chinese (zh_CN)
+ * Author: shadowwind, shatteredwindgo@gmail.com
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['zh-CN'] = {
+ "__locale": "Simplified Chinese (zh_CN)",
+ "__author": "shadowwind, shatteredwindgo@gmail.com",
+ "add_rule": "添加规则",
+ "add_group": "添加组",
+ "delete_rule": "删除",
+ "delete_group": "删除组",
+ "conditions": {
+ "AND": "和",
+ "OR": "或"
+ },
+ "operators": {
+ "equal": "等于",
+ "not_equal": "不等于",
+ "in": "在...之內",
+ "not_in": "不在...之內",
+ "less": "小于",
+ "less_or_equal": "小于或等于",
+ "greater": "大于",
+ "greater_or_equal": "大于或等于",
+ "between": "在...之间",
+ "not_between": "不在...之间",
+ "begins_with": "以...开始",
+ "not_begins_with": "不以...开始",
+ "contains": "包含以下内容",
+ "not_contains": "不包含以下内容",
+ "ends_with": "以...结束",
+ "not_ends_with": "不以...结束",
+ "is_empty": "为空",
+ "is_not_empty": "不为空",
+ "is_null": "为 null",
+ "is_not_null": "不为 null"
+ },
+ "errors": {
+ "no_filter": "没有选择过滤器",
+ "empty_group": "该组为空",
+ "radio_empty": "没有选中项",
+ "checkbox_empty": "没有选中项",
+ "select_empty": "没有选中项",
+ "string_empty": "没有输入值",
+ "string_exceed_min_length": "必须至少包含{0}个字符",
+ "string_exceed_max_length": "必须不超过{0}个字符",
+ "string_invalid_format": "无效格式({0})",
+ "number_nan": "值不是数字",
+ "number_not_integer": "不是整数",
+ "number_not_double": "不是浮点数",
+ "number_exceed_min": "必须大于{0}",
+ "number_exceed_max": "必须小于{0}",
+ "number_wrong_step": "必须是{0}的倍数",
+ "datetime_empty": "值为空",
+ "datetime_invalid": "不是有效日期({0})",
+ "datetime_exceed_min": "必须在{0}之后",
+ "datetime_exceed_max": "必须在{0}之前",
+ "boolean_not_valid": "不是布尔值",
+ "operator_not_multiple": "选项\"{1}\"无法接受多个值"
+ },
+ "invert": "倒置"
+};
+
+QueryBuilder.defaults({ lang_code: 'zh-CN' });
+}));
\ No newline at end of file
diff --git a/dist/js/query-builder.js b/dist/js/query-builder.js
new file mode 100644
index 00000000..6804d677
--- /dev/null
+++ b/dist/js/query-builder.js
@@ -0,0 +1,6200 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Copyright 2014-2020 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'dot/doT', 'jquery-extendext'], factory);
+ }
+ else if (typeof module === 'object' && module.exports) {
+ module.exports = factory(require('jquery'), require('dot/doT'), require('jquery-extendext'));
+ }
+ else {
+ factory(root.jQuery, root.doT);
+ }
+}(this, function($, doT) {
+"use strict";
+
+/**
+ * @typedef {object} Filter
+ * @memberof QueryBuilder
+ * @description See {@link http://querybuilder.js.org/index.html#filters}
+ */
+
+/**
+ * @typedef {object} Operator
+ * @memberof QueryBuilder
+ * @description See {@link http://querybuilder.js.org/index.html#operators}
+ */
+
+/**
+ * @param {jQuery} $el
+ * @param {object} options - see {@link http://querybuilder.js.org/#options}
+ * @constructor
+ */
+var QueryBuilder = function($el, options) {
+ $el[0].queryBuilder = this;
+
+ /**
+ * Element container
+ * @member {jQuery}
+ * @readonly
+ */
+ this.$el = $el;
+
+ /**
+ * Configuration object
+ * @member {object}
+ * @readonly
+ */
+ this.settings = $.extendext(true, 'replace', {}, QueryBuilder.DEFAULTS, options);
+
+ /**
+ * Internal model
+ * @member {Model}
+ * @readonly
+ */
+ this.model = new Model();
+
+ /**
+ * Internal status
+ * @member {object}
+ * @property {string} id - id of the container
+ * @property {boolean} generated_id - if the container id has been generated
+ * @property {int} group_id - current group id
+ * @property {int} rule_id - current rule id
+ * @property {boolean} has_optgroup - if filters have optgroups
+ * @property {boolean} has_operator_optgroup - if operators have optgroups
+ * @readonly
+ * @private
+ */
+ this.status = {
+ id: null,
+ generated_id: false,
+ group_id: 0,
+ rule_id: 0,
+ has_optgroup: false,
+ has_operator_optgroup: false
+ };
+
+ /**
+ * List of filters
+ * @member {QueryBuilder.Filter[]}
+ * @readonly
+ */
+ this.filters = this.settings.filters;
+
+ /**
+ * List of icons
+ * @member {object.}
+ * @readonly
+ */
+ this.icons = this.settings.icons;
+
+ /**
+ * List of operators
+ * @member {QueryBuilder.Operator[]}
+ * @readonly
+ */
+ this.operators = this.settings.operators;
+
+ /**
+ * List of templates
+ * @member {object.}
+ * @readonly
+ */
+ this.templates = this.settings.templates;
+
+ /**
+ * Plugins configuration
+ * @member {object.}
+ * @readonly
+ */
+ this.plugins = this.settings.plugins;
+
+ /**
+ * Translations object
+ * @member {object}
+ * @readonly
+ */
+ this.lang = null;
+
+ // translations : english << 'lang_code' << custom
+ if (QueryBuilder.regional['en'] === undefined) {
+ Utils.error('Config', '"i18n/en.js" not loaded.');
+ }
+ this.lang = $.extendext(true, 'replace', {}, QueryBuilder.regional['en'], QueryBuilder.regional[this.settings.lang_code], this.settings.lang);
+
+ // "allow_groups" can be boolean or int
+ if (this.settings.allow_groups === false) {
+ this.settings.allow_groups = 0;
+ }
+ else if (this.settings.allow_groups === true) {
+ this.settings.allow_groups = -1;
+ }
+
+ // init templates
+ Object.keys(this.templates).forEach(function(tpl) {
+ if (!this.templates[tpl]) {
+ this.templates[tpl] = QueryBuilder.templates[tpl];
+ }
+ if (typeof this.templates[tpl] == 'string') {
+ this.templates[tpl] = doT.template(this.templates[tpl]);
+ }
+ }, this);
+
+ // ensure we have a container id
+ if (!this.$el.attr('id')) {
+ this.$el.attr('id', 'qb_' + Math.floor(Math.random() * 99999));
+ this.status.generated_id = true;
+ }
+ this.status.id = this.$el.attr('id');
+
+ // INIT
+ this.$el.addClass('query-builder form-inline');
+
+ this.filters = this.checkFilters(this.filters);
+ this.operators = this.checkOperators(this.operators);
+ this.bindEvents();
+ this.initPlugins();
+};
+
+$.extend(QueryBuilder.prototype, /** @lends QueryBuilder.prototype */ {
+ /**
+ * Triggers an event on the builder container
+ * @param {string} type
+ * @returns {$.Event}
+ */
+ trigger: function(type) {
+ var event = new $.Event(this._tojQueryEvent(type), {
+ builder: this
+ });
+
+ this.$el.triggerHandler(event, Array.prototype.slice.call(arguments, 1));
+
+ return event;
+ },
+
+ /**
+ * Triggers an event on the builder container and returns the modified value
+ * @param {string} type
+ * @param {*} value
+ * @returns {*}
+ */
+ change: function(type, value) {
+ var event = new $.Event(this._tojQueryEvent(type, true), {
+ builder: this,
+ value: value
+ });
+
+ this.$el.triggerHandler(event, Array.prototype.slice.call(arguments, 2));
+
+ return event.value;
+ },
+
+ /**
+ * Attaches an event listener on the builder container
+ * @param {string} type
+ * @param {function} cb
+ * @returns {QueryBuilder}
+ */
+ on: function(type, cb) {
+ this.$el.on(this._tojQueryEvent(type), cb);
+ return this;
+ },
+
+ /**
+ * Removes an event listener from the builder container
+ * @param {string} type
+ * @param {function} [cb]
+ * @returns {QueryBuilder}
+ */
+ off: function(type, cb) {
+ this.$el.off(this._tojQueryEvent(type), cb);
+ return this;
+ },
+
+ /**
+ * Attaches an event listener called once on the builder container
+ * @param {string} type
+ * @param {function} cb
+ * @returns {QueryBuilder}
+ */
+ once: function(type, cb) {
+ this.$el.one(this._tojQueryEvent(type), cb);
+ return this;
+ },
+
+ /**
+ * Appends `.queryBuilder` and optionally `.filter` to the events names
+ * @param {string} name
+ * @param {boolean} [filter=false]
+ * @returns {string}
+ * @private
+ */
+ _tojQueryEvent: function(name, filter) {
+ return name.split(' ').map(function(type) {
+ return type + '.queryBuilder' + (filter ? '.filter' : '');
+ }).join(' ');
+ }
+});
+
+
+/**
+ * Allowed types and their internal representation
+ * @type {object.}
+ * @readonly
+ * @private
+ */
+QueryBuilder.types = {
+ 'string': 'string',
+ 'integer': 'number',
+ 'double': 'number',
+ 'date': 'datetime',
+ 'time': 'datetime',
+ 'datetime': 'datetime',
+ 'boolean': 'boolean'
+};
+
+/**
+ * Allowed inputs
+ * @type {string[]}
+ * @readonly
+ * @private
+ */
+QueryBuilder.inputs = [
+ 'text',
+ 'number',
+ 'textarea',
+ 'radio',
+ 'checkbox',
+ 'select'
+];
+
+/**
+ * Runtime modifiable options with `setOptions` method
+ * @type {string[]}
+ * @readonly
+ * @private
+ */
+QueryBuilder.modifiable_options = [
+ 'display_errors',
+ 'allow_groups',
+ 'allow_empty',
+ 'default_condition',
+ 'default_filter'
+];
+
+/**
+ * CSS selectors for common components
+ * @type {object.}
+ * @readonly
+ */
+QueryBuilder.selectors = {
+ group_container: '.rules-group-container',
+ rule_container: '.rule-container',
+ filter_container: '.rule-filter-container',
+ operator_container: '.rule-operator-container',
+ value_container: '.rule-value-container',
+ error_container: '.error-container',
+ condition_container: '.rules-group-header .group-conditions',
+
+ rule_header: '.rule-header',
+ group_header: '.rules-group-header',
+ group_actions: '.group-actions',
+ rule_actions: '.rule-actions',
+
+ rules_list: '.rules-group-body>.rules-list',
+
+ group_condition: '.rules-group-header [name$=_cond]',
+ rule_filter: '.rule-filter-container [name$=_filter]',
+ rule_operator: '.rule-operator-container [name$=_operator]',
+ rule_value: '.rule-value-container [name*=_value_]',
+
+ add_rule: '[data-add=rule]',
+ delete_rule: '[data-delete=rule]',
+ add_group: '[data-add=group]',
+ delete_group: '[data-delete=group]'
+};
+
+/**
+ * Template strings (see template.js)
+ * @type {object.}
+ * @readonly
+ */
+QueryBuilder.templates = {};
+
+/**
+ * Localized strings (see i18n/)
+ * @type {object.}
+ * @readonly
+ */
+QueryBuilder.regional = {};
+
+/**
+ * Default operators
+ * @type {object.}
+ * @readonly
+ */
+QueryBuilder.OPERATORS = {
+ equal: { type: 'equal', nb_inputs: 1, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean'] },
+ not_equal: { type: 'not_equal', nb_inputs: 1, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean'] },
+ in: { type: 'in', nb_inputs: 1, multiple: true, apply_to: ['string', 'number', 'datetime'] },
+ not_in: { type: 'not_in', nb_inputs: 1, multiple: true, apply_to: ['string', 'number', 'datetime'] },
+ less: { type: 'less', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime'] },
+ less_or_equal: { type: 'less_or_equal', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime'] },
+ greater: { type: 'greater', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime'] },
+ greater_or_equal: { type: 'greater_or_equal', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime'] },
+ between: { type: 'between', nb_inputs: 2, multiple: false, apply_to: ['number', 'datetime'] },
+ not_between: { type: 'not_between', nb_inputs: 2, multiple: false, apply_to: ['number', 'datetime'] },
+ begins_with: { type: 'begins_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ not_begins_with: { type: 'not_begins_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ contains: { type: 'contains', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ not_contains: { type: 'not_contains', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ ends_with: { type: 'ends_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ not_ends_with: { type: 'not_ends_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ is_empty: { type: 'is_empty', nb_inputs: 0, multiple: false, apply_to: ['string'] },
+ is_not_empty: { type: 'is_not_empty', nb_inputs: 0, multiple: false, apply_to: ['string'] },
+ is_null: { type: 'is_null', nb_inputs: 0, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean'] },
+ is_not_null: { type: 'is_not_null', nb_inputs: 0, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean'] }
+};
+
+/**
+ * Default configuration
+ * @type {object}
+ * @readonly
+ */
+QueryBuilder.DEFAULTS = {
+ filters: [],
+ plugins: [],
+
+ sort_filters: false,
+ display_errors: true,
+ allow_groups: -1,
+ allow_empty: false,
+ conditions: ['AND', 'OR'],
+ default_condition: 'AND',
+ inputs_separator: ' , ',
+ select_placeholder: '------',
+ display_empty_filter: true,
+ default_filter: null,
+ optgroups: {},
+
+ default_rule_flags: {
+ filter_readonly: false,
+ operator_readonly: false,
+ value_readonly: false,
+ no_delete: false
+ },
+
+ default_group_flags: {
+ condition_readonly: false,
+ no_add_rule: false,
+ no_add_group: false,
+ no_delete: false
+ },
+
+ templates: {
+ group: null,
+ rule: null,
+ filterSelect: null,
+ operatorSelect: null,
+ ruleValueSelect: null
+ },
+
+ lang_code: 'en',
+ lang: {},
+
+ operators: [
+ 'equal',
+ 'not_equal',
+ 'in',
+ 'not_in',
+ 'less',
+ 'less_or_equal',
+ 'greater',
+ 'greater_or_equal',
+ 'between',
+ 'not_between',
+ 'begins_with',
+ 'not_begins_with',
+ 'contains',
+ 'not_contains',
+ 'ends_with',
+ 'not_ends_with',
+ 'is_empty',
+ 'is_not_empty',
+ 'is_null',
+ 'is_not_null'
+ ],
+
+ icons: {
+ add_group: 'fas fa-plus-circle',
+ add_rule: 'fas fa-plus',
+ remove_group: 'fas fa-times',
+ remove_rule: 'fas fa-times',
+ error: 'fas fa-exclamation-triangle'
+ }
+};
+
+
+/**
+ * @module plugins
+ */
+
+/**
+ * Definition of available plugins
+ * @type {object.}
+ */
+QueryBuilder.plugins = {};
+
+/**
+ * Gets or extends the default configuration
+ * @param {object} [options] - new configuration
+ * @returns {undefined|object} nothing or configuration object (copy)
+ */
+QueryBuilder.defaults = function(options) {
+ if (typeof options == 'object') {
+ $.extendext(true, 'replace', QueryBuilder.DEFAULTS, options);
+ }
+ else if (typeof options == 'string') {
+ if (typeof QueryBuilder.DEFAULTS[options] == 'object') {
+ return $.extend(true, {}, QueryBuilder.DEFAULTS[options]);
+ }
+ else {
+ return QueryBuilder.DEFAULTS[options];
+ }
+ }
+ else {
+ return $.extend(true, {}, QueryBuilder.DEFAULTS);
+ }
+};
+
+/**
+ * Registers a new plugin
+ * @param {string} name
+ * @param {function} fct - init function
+ * @param {object} [def] - default options
+ */
+QueryBuilder.define = function(name, fct, def) {
+ QueryBuilder.plugins[name] = {
+ fct: fct,
+ def: def || {}
+ };
+};
+
+/**
+ * Adds new methods to QueryBuilder prototype
+ * @param {object.} methods
+ */
+QueryBuilder.extend = function(methods) {
+ $.extend(QueryBuilder.prototype, methods);
+};
+
+/**
+ * Initializes plugins for an instance
+ * @throws ConfigError
+ * @private
+ */
+QueryBuilder.prototype.initPlugins = function() {
+ if (!this.plugins) {
+ return;
+ }
+
+ if ($.isArray(this.plugins)) {
+ var tmp = {};
+ this.plugins.forEach(function(plugin) {
+ tmp[plugin] = null;
+ });
+ this.plugins = tmp;
+ }
+
+ Object.keys(this.plugins).forEach(function(plugin) {
+ if (plugin in QueryBuilder.plugins) {
+ this.plugins[plugin] = $.extend(true, {},
+ QueryBuilder.plugins[plugin].def,
+ this.plugins[plugin] || {}
+ );
+
+ QueryBuilder.plugins[plugin].fct.call(this, this.plugins[plugin]);
+ }
+ else {
+ Utils.error('Config', 'Unable to find plugin "{0}"', plugin);
+ }
+ }, this);
+};
+
+/**
+ * Returns the config of a plugin, if the plugin is not loaded, returns the default config.
+ * @param {string} name
+ * @param {string} [property]
+ * @throws ConfigError
+ * @returns {*}
+ */
+QueryBuilder.prototype.getPluginOptions = function(name, property) {
+ var plugin;
+ if (this.plugins && this.plugins[name]) {
+ plugin = this.plugins[name];
+ }
+ else if (QueryBuilder.plugins[name]) {
+ plugin = QueryBuilder.plugins[name].def;
+ }
+
+ if (plugin) {
+ if (property) {
+ return plugin[property];
+ }
+ else {
+ return plugin;
+ }
+ }
+ else {
+ Utils.error('Config', 'Unable to find plugin "{0}"', name);
+ }
+};
+
+
+/**
+ * Final initialisation of the builder
+ * @param {object} [rules]
+ * @fires QueryBuilder.afterInit
+ * @private
+ */
+QueryBuilder.prototype.init = function(rules) {
+ /**
+ * When the initilization is done, just before creating the root group
+ * @event afterInit
+ * @memberof QueryBuilder
+ */
+ this.trigger('afterInit');
+
+ if (rules) {
+ this.setRules(rules);
+ delete this.settings.rules;
+ }
+ else {
+ this.setRoot(true);
+ }
+};
+
+/**
+ * Checks the configuration of each filter
+ * @param {QueryBuilder.Filter[]} filters
+ * @returns {QueryBuilder.Filter[]}
+ * @throws ConfigError
+ */
+QueryBuilder.prototype.checkFilters = function(filters) {
+ var definedFilters = [];
+
+ if (!filters || filters.length === 0) {
+ Utils.error('Config', 'Missing filters list');
+ }
+
+ filters.forEach(function(filter, i) {
+ if (!filter.id) {
+ Utils.error('Config', 'Missing filter {0} id', i);
+ }
+ if (definedFilters.indexOf(filter.id) != -1) {
+ Utils.error('Config', 'Filter "{0}" already defined', filter.id);
+ }
+ definedFilters.push(filter.id);
+
+ if (!filter.type) {
+ filter.type = 'string';
+ }
+ else if (!QueryBuilder.types[filter.type]) {
+ Utils.error('Config', 'Invalid type "{0}"', filter.type);
+ }
+
+ if (!filter.input) {
+ filter.input = QueryBuilder.types[filter.type] === 'number' ? 'number' : 'text';
+ }
+ else if (typeof filter.input != 'function' && QueryBuilder.inputs.indexOf(filter.input) == -1) {
+ Utils.error('Config', 'Invalid input "{0}"', filter.input);
+ }
+
+ if (filter.operators) {
+ filter.operators.forEach(function(operator) {
+ if (typeof operator != 'string') {
+ Utils.error('Config', 'Filter operators must be global operators types (string)');
+ }
+ });
+ }
+
+ if (!filter.field) {
+ filter.field = filter.id;
+ }
+ if (!filter.label) {
+ filter.label = filter.field;
+ }
+
+ if (!filter.optgroup) {
+ filter.optgroup = null;
+ }
+ else {
+ this.status.has_optgroup = true;
+
+ // register optgroup if needed
+ if (!this.settings.optgroups[filter.optgroup]) {
+ this.settings.optgroups[filter.optgroup] = filter.optgroup;
+ }
+ }
+
+ switch (filter.input) {
+ case 'radio':
+ case 'checkbox':
+ if (!filter.values || filter.values.length < 1) {
+ Utils.error('Config', 'Missing filter "{0}" values', filter.id);
+ }
+ break;
+
+ case 'select':
+ var cleanValues = [];
+ filter.has_optgroup = false;
+
+ Utils.iterateOptions(filter.values, function(value, label, optgroup) {
+ cleanValues.push({
+ value: value,
+ label: label,
+ optgroup: optgroup || null
+ });
+
+ if (optgroup) {
+ filter.has_optgroup = true;
+
+ // register optgroup if needed
+ if (!this.settings.optgroups[optgroup]) {
+ this.settings.optgroups[optgroup] = optgroup;
+ }
+ }
+ }.bind(this));
+
+ if (filter.has_optgroup) {
+ filter.values = Utils.groupSort(cleanValues, 'optgroup');
+ }
+ else {
+ filter.values = cleanValues;
+ }
+
+ if (filter.placeholder) {
+ if (filter.placeholder_value === undefined) {
+ filter.placeholder_value = -1;
+ }
+
+ filter.values.forEach(function(entry) {
+ if (entry.value == filter.placeholder_value) {
+ Utils.error('Config', 'Placeholder of filter "{0}" overlaps with one of its values', filter.id);
+ }
+ });
+ }
+ break;
+ }
+ }, this);
+
+ if (this.settings.sort_filters) {
+ if (typeof this.settings.sort_filters == 'function') {
+ filters.sort(this.settings.sort_filters);
+ }
+ else {
+ var self = this;
+ filters.sort(function(a, b) {
+ return self.translate(a.label).localeCompare(self.translate(b.label));
+ });
+ }
+ }
+
+ if (this.status.has_optgroup) {
+ filters = Utils.groupSort(filters, 'optgroup');
+ }
+
+ return filters;
+};
+
+/**
+ * Checks the configuration of each operator
+ * @param {QueryBuilder.Operator[]} operators
+ * @returns {QueryBuilder.Operator[]}
+ * @throws ConfigError
+ */
+QueryBuilder.prototype.checkOperators = function(operators) {
+ var definedOperators = [];
+
+ operators.forEach(function(operator, i) {
+ if (typeof operator == 'string') {
+ if (!QueryBuilder.OPERATORS[operator]) {
+ Utils.error('Config', 'Unknown operator "{0}"', operator);
+ }
+
+ operators[i] = operator = $.extendext(true, 'replace', {}, QueryBuilder.OPERATORS[operator]);
+ }
+ else {
+ if (!operator.type) {
+ Utils.error('Config', 'Missing "type" for operator {0}', i);
+ }
+
+ if (QueryBuilder.OPERATORS[operator.type]) {
+ operators[i] = operator = $.extendext(true, 'replace', {}, QueryBuilder.OPERATORS[operator.type], operator);
+ }
+
+ if (operator.nb_inputs === undefined || operator.apply_to === undefined) {
+ Utils.error('Config', 'Missing "nb_inputs" and/or "apply_to" for operator "{0}"', operator.type);
+ }
+ }
+
+ if (definedOperators.indexOf(operator.type) != -1) {
+ Utils.error('Config', 'Operator "{0}" already defined', operator.type);
+ }
+ definedOperators.push(operator.type);
+
+ if (!operator.optgroup) {
+ operator.optgroup = null;
+ }
+ else {
+ this.status.has_operator_optgroup = true;
+
+ // register optgroup if needed
+ if (!this.settings.optgroups[operator.optgroup]) {
+ this.settings.optgroups[operator.optgroup] = operator.optgroup;
+ }
+ }
+ }, this);
+
+ if (this.status.has_operator_optgroup) {
+ operators = Utils.groupSort(operators, 'optgroup');
+ }
+
+ return operators;
+};
+
+/**
+ * Adds all events listeners to the builder
+ * @private
+ */
+QueryBuilder.prototype.bindEvents = function() {
+ var self = this;
+ var Selectors = QueryBuilder.selectors;
+
+ // group condition change
+ this.$el.on('change.queryBuilder', Selectors.group_condition, function() {
+ if ($(this).is(':checked')) {
+ var $group = $(this).closest(Selectors.group_container);
+ self.getModel($group).condition = $(this).val();
+ }
+ });
+
+ // rule filter change
+ this.$el.on('change.queryBuilder', Selectors.rule_filter, function() {
+ var $rule = $(this).closest(Selectors.rule_container);
+ self.getModel($rule).filter = self.getFilterById($(this).val());
+ });
+
+ // rule operator change
+ this.$el.on('change.queryBuilder', Selectors.rule_operator, function() {
+ var $rule = $(this).closest(Selectors.rule_container);
+ self.getModel($rule).operator = self.getOperatorByType($(this).val());
+ });
+
+ // add rule button
+ this.$el.on('click.queryBuilder', Selectors.add_rule, function() {
+ var $group = $(this).closest(Selectors.group_container);
+ self.addRule(self.getModel($group));
+ });
+
+ // delete rule button
+ this.$el.on('click.queryBuilder', Selectors.delete_rule, function() {
+ var $rule = $(this).closest(Selectors.rule_container);
+ self.deleteRule(self.getModel($rule));
+ });
+
+ if (this.settings.allow_groups !== 0) {
+ // add group button
+ this.$el.on('click.queryBuilder', Selectors.add_group, function() {
+ var $group = $(this).closest(Selectors.group_container);
+ self.addGroup(self.getModel($group));
+ });
+
+ // delete group button
+ this.$el.on('click.queryBuilder', Selectors.delete_group, function() {
+ var $group = $(this).closest(Selectors.group_container);
+ self.deleteGroup(self.getModel($group));
+ });
+ }
+
+ // model events
+ this.model.on({
+ 'drop': function(e, node) {
+ node.$el.remove();
+ self.refreshGroupsConditions();
+ },
+ 'add': function(e, parent, node, index) {
+ if (index === 0) {
+ node.$el.prependTo(parent.$el.find('>' + QueryBuilder.selectors.rules_list));
+ }
+ else {
+ node.$el.insertAfter(parent.rules[index - 1].$el);
+ }
+ self.refreshGroupsConditions();
+ },
+ 'move': function(e, node, group, index) {
+ node.$el.detach();
+
+ if (index === 0) {
+ node.$el.prependTo(group.$el.find('>' + QueryBuilder.selectors.rules_list));
+ }
+ else {
+ node.$el.insertAfter(group.rules[index - 1].$el);
+ }
+ self.refreshGroupsConditions();
+ },
+ 'update': function(e, node, field, value, oldValue) {
+ if (node instanceof Rule) {
+ switch (field) {
+ case 'error':
+ self.updateError(node);
+ break;
+
+ case 'flags':
+ self.applyRuleFlags(node);
+ break;
+
+ case 'filter':
+ self.updateRuleFilter(node, oldValue);
+ break;
+
+ case 'operator':
+ self.updateRuleOperator(node, oldValue);
+ break;
+
+ case 'value':
+ self.updateRuleValue(node, oldValue);
+ break;
+ }
+ }
+ else {
+ switch (field) {
+ case 'error':
+ self.updateError(node);
+ break;
+
+ case 'flags':
+ self.applyGroupFlags(node);
+ break;
+
+ case 'condition':
+ self.updateGroupCondition(node, oldValue);
+ break;
+ }
+ }
+ }
+ });
+};
+
+/**
+ * Creates the root group
+ * @param {boolean} [addRule=true] - adds a default empty rule
+ * @param {object} [data] - group custom data
+ * @param {object} [flags] - flags to apply to the group
+ * @returns {Group} root group
+ * @fires QueryBuilder.afterAddGroup
+ */
+QueryBuilder.prototype.setRoot = function(addRule, data, flags) {
+ addRule = (addRule === undefined || addRule === true);
+
+ var group_id = this.nextGroupId();
+ var $group = $(this.getGroupTemplate(group_id, 1));
+
+ this.$el.append($group);
+ this.model.root = new Group(null, $group);
+ this.model.root.model = this.model;
+
+ this.model.root.data = data;
+ this.model.root.flags = $.extend({}, this.settings.default_group_flags, flags);
+ this.model.root.condition = this.settings.default_condition;
+
+ this.trigger('afterAddGroup', this.model.root);
+
+ if (addRule) {
+ this.addRule(this.model.root);
+ }
+
+ return this.model.root;
+};
+
+/**
+ * Adds a new group
+ * @param {Group} parent
+ * @param {boolean} [addRule=true] - adds a default empty rule
+ * @param {object} [data] - group custom data
+ * @param {object} [flags] - flags to apply to the group
+ * @returns {Group}
+ * @fires QueryBuilder.beforeAddGroup
+ * @fires QueryBuilder.afterAddGroup
+ */
+QueryBuilder.prototype.addGroup = function(parent, addRule, data, flags) {
+ addRule = (addRule === undefined || addRule === true);
+
+ var level = parent.level + 1;
+
+ /**
+ * Just before adding a group, can be prevented.
+ * @event beforeAddGroup
+ * @memberof QueryBuilder
+ * @param {Group} parent
+ * @param {boolean} addRule - if an empty rule will be added in the group
+ * @param {int} level - nesting level of the group, 1 is the root group
+ */
+ var e = this.trigger('beforeAddGroup', parent, addRule, level);
+ if (e.isDefaultPrevented()) {
+ return null;
+ }
+
+ var group_id = this.nextGroupId();
+ var $group = $(this.getGroupTemplate(group_id, level));
+ var model = parent.addGroup($group);
+
+ model.data = data;
+ model.flags = $.extend({}, this.settings.default_group_flags, flags);
+ model.condition = this.settings.default_condition;
+
+ /**
+ * Just after adding a group
+ * @event afterAddGroup
+ * @memberof QueryBuilder
+ * @param {Group} group
+ */
+ this.trigger('afterAddGroup', model);
+
+ /**
+ * After any change in the rules
+ * @event rulesChanged
+ * @memberof QueryBuilder
+ */
+ this.trigger('rulesChanged');
+
+ if (addRule) {
+ this.addRule(model);
+ }
+
+ return model;
+};
+
+/**
+ * Tries to delete a group. The group is not deleted if at least one rule is flagged `no_delete`.
+ * @param {Group} group
+ * @returns {boolean} if the group has been deleted
+ * @fires QueryBuilder.beforeDeleteGroup
+ * @fires QueryBuilder.afterDeleteGroup
+ */
+QueryBuilder.prototype.deleteGroup = function(group) {
+ if (group.isRoot()) {
+ return false;
+ }
+
+ /**
+ * Just before deleting a group, can be prevented
+ * @event beforeDeleteGroup
+ * @memberof QueryBuilder
+ * @param {Group} parent
+ */
+ var e = this.trigger('beforeDeleteGroup', group);
+ if (e.isDefaultPrevented()) {
+ return false;
+ }
+
+ var del = true;
+
+ group.each('reverse', function(rule) {
+ del &= this.deleteRule(rule);
+ }, function(group) {
+ del &= this.deleteGroup(group);
+ }, this);
+
+ if (del) {
+ group.drop();
+
+ /**
+ * Just after deleting a group
+ * @event afterDeleteGroup
+ * @memberof QueryBuilder
+ */
+ this.trigger('afterDeleteGroup');
+
+ this.trigger('rulesChanged');
+ }
+
+ return del;
+};
+
+/**
+ * Performs actions when a group's condition changes
+ * @param {Group} group
+ * @param {object} previousCondition
+ * @fires QueryBuilder.afterUpdateGroupCondition
+ * @private
+ */
+QueryBuilder.prototype.updateGroupCondition = function(group, previousCondition) {
+ group.$el.find('>' + QueryBuilder.selectors.group_condition).each(function() {
+ var $this = $(this);
+ $this.prop('checked', $this.val() === group.condition);
+ $this.parent().toggleClass('active', $this.val() === group.condition);
+ });
+
+ /**
+ * After the group condition has been modified
+ * @event afterUpdateGroupCondition
+ * @memberof QueryBuilder
+ * @param {Group} group
+ * @param {object} previousCondition
+ */
+ this.trigger('afterUpdateGroupCondition', group, previousCondition);
+
+ this.trigger('rulesChanged');
+};
+
+/**
+ * Updates the visibility of conditions based on number of rules inside each group
+ * @private
+ */
+QueryBuilder.prototype.refreshGroupsConditions = function() {
+ (function walk(group) {
+ if (!group.flags || (group.flags && !group.flags.condition_readonly)) {
+ group.$el.find('>' + QueryBuilder.selectors.group_condition).prop('disabled', group.rules.length <= 1)
+ .parent().toggleClass('disabled', group.rules.length <= 1);
+ }
+
+ group.each(null, function(group) {
+ walk(group);
+ }, this);
+ }(this.model.root));
+};
+
+/**
+ * Adds a new rule
+ * @param {Group} parent
+ * @param {object} [data] - rule custom data
+ * @param {object} [flags] - flags to apply to the rule
+ * @returns {Rule}
+ * @fires QueryBuilder.beforeAddRule
+ * @fires QueryBuilder.afterAddRule
+ * @fires QueryBuilder.changer:getDefaultFilter
+ */
+QueryBuilder.prototype.addRule = function(parent, data, flags) {
+ /**
+ * Just before adding a rule, can be prevented
+ * @event beforeAddRule
+ * @memberof QueryBuilder
+ * @param {Group} parent
+ */
+ var e = this.trigger('beforeAddRule', parent);
+ if (e.isDefaultPrevented()) {
+ return null;
+ }
+
+ var rule_id = this.nextRuleId();
+ var $rule = $(this.getRuleTemplate(rule_id));
+ var model = parent.addRule($rule);
+
+ model.data = data;
+ model.flags = $.extend({}, this.settings.default_rule_flags, flags);
+
+ /**
+ * Just after adding a rule
+ * @event afterAddRule
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ */
+ this.trigger('afterAddRule', model);
+
+ this.trigger('rulesChanged');
+
+ this.createRuleFilters(model);
+
+ if (this.settings.default_filter || !this.settings.display_empty_filter) {
+ /**
+ * Modifies the default filter for a rule
+ * @event changer:getDefaultFilter
+ * @memberof QueryBuilder
+ * @param {QueryBuilder.Filter} filter
+ * @param {Rule} rule
+ * @returns {QueryBuilder.Filter}
+ */
+ model.filter = this.change('getDefaultFilter',
+ this.getFilterById(this.settings.default_filter || this.filters[0].id),
+ model
+ );
+ }
+
+ return model;
+};
+
+/**
+ * Tries to delete a rule
+ * @param {Rule} rule
+ * @returns {boolean} if the rule has been deleted
+ * @fires QueryBuilder.beforeDeleteRule
+ * @fires QueryBuilder.afterDeleteRule
+ */
+QueryBuilder.prototype.deleteRule = function(rule) {
+ if (rule.flags.no_delete) {
+ return false;
+ }
+
+ /**
+ * Just before deleting a rule, can be prevented
+ * @event beforeDeleteRule
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ */
+ var e = this.trigger('beforeDeleteRule', rule);
+ if (e.isDefaultPrevented()) {
+ return false;
+ }
+
+ rule.drop();
+
+ /**
+ * Just after deleting a rule
+ * @event afterDeleteRule
+ * @memberof QueryBuilder
+ */
+ this.trigger('afterDeleteRule');
+
+ this.trigger('rulesChanged');
+
+ return true;
+};
+
+/**
+ * Creates the filters for a rule
+ * @param {Rule} rule
+ * @fires QueryBuilder.changer:getRuleFilters
+ * @fires QueryBuilder.afterCreateRuleFilters
+ * @private
+ */
+QueryBuilder.prototype.createRuleFilters = function(rule) {
+ /**
+ * Modifies the list a filters available for a rule
+ * @event changer:getRuleFilters
+ * @memberof QueryBuilder
+ * @param {QueryBuilder.Filter[]} filters
+ * @param {Rule} rule
+ * @returns {QueryBuilder.Filter[]}
+ */
+ var filters = this.change('getRuleFilters', this.filters, rule);
+ var $filterSelect = $(this.getRuleFilterSelect(rule, filters));
+
+ rule.$el.find(QueryBuilder.selectors.filter_container).html($filterSelect);
+
+ /**
+ * After creating the dropdown for filters
+ * @event afterCreateRuleFilters
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ */
+ this.trigger('afterCreateRuleFilters', rule);
+
+ this.applyRuleFlags(rule);
+};
+
+/**
+ * Creates the operators for a rule and init the rule operator
+ * @param {Rule} rule
+ * @fires QueryBuilder.afterCreateRuleOperators
+ * @private
+ */
+QueryBuilder.prototype.createRuleOperators = function(rule) {
+ var $operatorContainer = rule.$el.find(QueryBuilder.selectors.operator_container).empty();
+
+ if (!rule.filter) {
+ return;
+ }
+
+ var operators = this.getOperators(rule.filter);
+ var $operatorSelect = $(this.getRuleOperatorSelect(rule, operators));
+
+ $operatorContainer.html($operatorSelect);
+
+ // set the operator without triggering update event
+ if (rule.filter.default_operator) {
+ rule.__.operator = this.getOperatorByType(rule.filter.default_operator);
+ }
+ else {
+ rule.__.operator = operators[0];
+ }
+
+ rule.$el.find(QueryBuilder.selectors.rule_operator).val(rule.operator.type);
+
+ /**
+ * After creating the dropdown for operators
+ * @event afterCreateRuleOperators
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ * @param {QueryBuilder.Operator[]} operators - allowed operators for this rule
+ */
+ this.trigger('afterCreateRuleOperators', rule, operators);
+
+ this.applyRuleFlags(rule);
+};
+
+/**
+ * Creates the main input for a rule
+ * @param {Rule} rule
+ * @fires QueryBuilder.afterCreateRuleInput
+ * @private
+ */
+QueryBuilder.prototype.createRuleInput = function(rule) {
+ var $valueContainer = rule.$el.find(QueryBuilder.selectors.value_container).empty();
+
+ rule.__.value = undefined;
+
+ if (!rule.filter || !rule.operator || rule.operator.nb_inputs === 0) {
+ return;
+ }
+
+ var self = this;
+ var $inputs = $();
+ var filter = rule.filter;
+
+ for (var i = 0; i < rule.operator.nb_inputs; i++) {
+ var $ruleInput = $(this.getRuleInput(rule, i));
+ if (i > 0) $valueContainer.append(this.settings.inputs_separator);
+ $valueContainer.append($ruleInput);
+ $inputs = $inputs.add($ruleInput);
+ }
+
+ $valueContainer.css('display', '');
+
+ $inputs.on('change ' + (filter.input_event || ''), function() {
+ if (!rule._updating_input) {
+ rule._updating_value = true;
+ rule.value = self.getRuleInputValue(rule);
+ rule._updating_value = false;
+ }
+ });
+
+ if (filter.plugin) {
+ $inputs[filter.plugin](filter.plugin_config || {});
+ }
+
+ /**
+ * After creating the input for a rule and initializing optional plugin
+ * @event afterCreateRuleInput
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ */
+ this.trigger('afterCreateRuleInput', rule);
+
+ if (filter.default_value !== undefined) {
+ rule.value = filter.default_value;
+ }
+ else {
+ rule._updating_value = true;
+ rule.value = self.getRuleInputValue(rule);
+ rule._updating_value = false;
+ }
+
+ this.applyRuleFlags(rule);
+};
+
+/**
+ * Performs action when a rule's filter changes
+ * @param {Rule} rule
+ * @param {object} previousFilter
+ * @fires QueryBuilder.afterUpdateRuleFilter
+ * @private
+ */
+QueryBuilder.prototype.updateRuleFilter = function(rule, previousFilter) {
+ this.createRuleOperators(rule);
+ this.createRuleInput(rule);
+
+ rule.$el.find(QueryBuilder.selectors.rule_filter).val(rule.filter ? rule.filter.id : '-1');
+
+ // clear rule data if the filter changed
+ if (previousFilter && rule.filter && previousFilter.id !== rule.filter.id) {
+ rule.data = undefined;
+ }
+
+ /**
+ * After the filter has been updated and the operators and input re-created
+ * @event afterUpdateRuleFilter
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ * @param {object} previousFilter
+ */
+ this.trigger('afterUpdateRuleFilter', rule, previousFilter);
+
+ this.trigger('rulesChanged');
+};
+
+/**
+ * Performs actions when a rule's operator changes
+ * @param {Rule} rule
+ * @param {object} previousOperator
+ * @fires QueryBuilder.afterUpdateRuleOperator
+ * @private
+ */
+QueryBuilder.prototype.updateRuleOperator = function(rule, previousOperator) {
+ var $valueContainer = rule.$el.find(QueryBuilder.selectors.value_container);
+
+ if (!rule.operator || rule.operator.nb_inputs === 0) {
+ $valueContainer.hide();
+
+ rule.__.value = undefined;
+ }
+ else {
+ $valueContainer.css('display', '');
+
+ if ($valueContainer.is(':empty') || !previousOperator ||
+ rule.operator.nb_inputs !== previousOperator.nb_inputs ||
+ rule.operator.optgroup !== previousOperator.optgroup
+ ) {
+ this.createRuleInput(rule);
+ }
+ }
+
+ if (rule.operator) {
+ rule.$el.find(QueryBuilder.selectors.rule_operator).val(rule.operator.type);
+
+ // refresh value if the format changed for this operator
+ rule.__.value = this.getRuleInputValue(rule);
+ }
+
+ /**
+ * After the operator has been updated and the input optionally re-created
+ * @event afterUpdateRuleOperator
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ * @param {object} previousOperator
+ */
+ this.trigger('afterUpdateRuleOperator', rule, previousOperator);
+
+ this.trigger('rulesChanged');
+};
+
+/**
+ * Performs actions when rule's value changes
+ * @param {Rule} rule
+ * @param {object} previousValue
+ * @fires QueryBuilder.afterUpdateRuleValue
+ * @private
+ */
+QueryBuilder.prototype.updateRuleValue = function(rule, previousValue) {
+ if (!rule._updating_value) {
+ this.setRuleInputValue(rule, rule.value);
+ }
+
+ /**
+ * After the rule value has been modified
+ * @event afterUpdateRuleValue
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ * @param {*} previousValue
+ */
+ this.trigger('afterUpdateRuleValue', rule, previousValue);
+
+ this.trigger('rulesChanged');
+};
+
+/**
+ * Changes a rule's properties depending on its flags
+ * @param {Rule} rule
+ * @fires QueryBuilder.afterApplyRuleFlags
+ * @private
+ */
+QueryBuilder.prototype.applyRuleFlags = function(rule) {
+ var flags = rule.flags;
+ var Selectors = QueryBuilder.selectors;
+
+ rule.$el.find(Selectors.rule_filter).prop('disabled', flags.filter_readonly);
+ rule.$el.find(Selectors.rule_operator).prop('disabled', flags.operator_readonly);
+ rule.$el.find(Selectors.rule_value).prop('disabled', flags.value_readonly);
+
+ if (flags.no_delete) {
+ rule.$el.find(Selectors.delete_rule).remove();
+ }
+
+ /**
+ * After rule's flags has been applied
+ * @event afterApplyRuleFlags
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ */
+ this.trigger('afterApplyRuleFlags', rule);
+};
+
+/**
+ * Changes group's properties depending on its flags
+ * @param {Group} group
+ * @fires QueryBuilder.afterApplyGroupFlags
+ * @private
+ */
+QueryBuilder.prototype.applyGroupFlags = function(group) {
+ var flags = group.flags;
+ var Selectors = QueryBuilder.selectors;
+
+ group.$el.find('>' + Selectors.group_condition).prop('disabled', flags.condition_readonly)
+ .parent().toggleClass('readonly', flags.condition_readonly);
+
+ if (flags.no_add_rule) {
+ group.$el.find(Selectors.add_rule).remove();
+ }
+ if (flags.no_add_group) {
+ group.$el.find(Selectors.add_group).remove();
+ }
+ if (flags.no_delete) {
+ group.$el.find(Selectors.delete_group).remove();
+ }
+
+ /**
+ * After group's flags has been applied
+ * @event afterApplyGroupFlags
+ * @memberof QueryBuilder
+ * @param {Group} group
+ */
+ this.trigger('afterApplyGroupFlags', group);
+};
+
+/**
+ * Clears all errors markers
+ * @param {Node} [node] default is root Group
+ */
+QueryBuilder.prototype.clearErrors = function(node) {
+ node = node || this.model.root;
+
+ if (!node) {
+ return;
+ }
+
+ node.error = null;
+
+ if (node instanceof Group) {
+ node.each(function(rule) {
+ rule.error = null;
+ }, function(group) {
+ this.clearErrors(group);
+ }, this);
+ }
+};
+
+/**
+ * Adds/Removes error on a Rule or Group
+ * @param {Node} node
+ * @fires QueryBuilder.changer:displayError
+ * @private
+ */
+QueryBuilder.prototype.updateError = function(node) {
+ if (this.settings.display_errors) {
+ if (node.error === null) {
+ node.$el.removeClass('has-error');
+ }
+ else {
+ var errorMessage = this.translate('errors', node.error[0]);
+ errorMessage = Utils.fmt(errorMessage, node.error.slice(1));
+
+ /**
+ * Modifies an error message before display
+ * @event changer:displayError
+ * @memberof QueryBuilder
+ * @param {string} errorMessage - the error message (translated and formatted)
+ * @param {array} error - the raw error array (error code and optional arguments)
+ * @param {Node} node
+ * @returns {string}
+ */
+ errorMessage = this.change('displayError', errorMessage, node.error, node);
+
+ node.$el.addClass('has-error')
+ .find(QueryBuilder.selectors.error_container).eq(0)
+ .attr('title', errorMessage);
+ }
+ }
+};
+
+/**
+ * Triggers a validation error event
+ * @param {Node} node
+ * @param {string|array} error
+ * @param {*} value
+ * @fires QueryBuilder.validationError
+ * @private
+ */
+QueryBuilder.prototype.triggerValidationError = function(node, error, value) {
+ if (!$.isArray(error)) {
+ error = [error];
+ }
+
+ /**
+ * Fired when a validation error occurred, can be prevented
+ * @event validationError
+ * @memberof QueryBuilder
+ * @param {Node} node
+ * @param {string} error
+ * @param {*} value
+ */
+ var e = this.trigger('validationError', node, error, value);
+ if (!e.isDefaultPrevented()) {
+ node.error = error;
+ }
+};
+
+
+/**
+ * Destroys the builder
+ * @fires QueryBuilder.beforeDestroy
+ */
+QueryBuilder.prototype.destroy = function() {
+ /**
+ * Before the {@link QueryBuilder#destroy} method
+ * @event beforeDestroy
+ * @memberof QueryBuilder
+ */
+ this.trigger('beforeDestroy');
+
+ if (this.status.generated_id) {
+ this.$el.removeAttr('id');
+ }
+
+ this.clear();
+ this.model = null;
+
+ this.$el
+ .off('.queryBuilder')
+ .removeClass('query-builder')
+ .removeData('queryBuilder');
+
+ delete this.$el[0].queryBuilder;
+};
+
+/**
+ * Clear all rules and resets the root group
+ * @fires QueryBuilder.beforeReset
+ * @fires QueryBuilder.afterReset
+ */
+QueryBuilder.prototype.reset = function() {
+ /**
+ * Before the {@link QueryBuilder#reset} method, can be prevented
+ * @event beforeReset
+ * @memberof QueryBuilder
+ */
+ var e = this.trigger('beforeReset');
+ if (e.isDefaultPrevented()) {
+ return;
+ }
+
+ this.status.group_id = 1;
+ this.status.rule_id = 0;
+
+ this.model.root.empty();
+
+ this.model.root.data = undefined;
+ this.model.root.flags = $.extend({}, this.settings.default_group_flags);
+ this.model.root.condition = this.settings.default_condition;
+
+ this.addRule(this.model.root);
+
+ /**
+ * After the {@link QueryBuilder#reset} method
+ * @event afterReset
+ * @memberof QueryBuilder
+ */
+ this.trigger('afterReset');
+
+ this.trigger('rulesChanged');
+};
+
+/**
+ * Clears all rules and removes the root group
+ * @fires QueryBuilder.beforeClear
+ * @fires QueryBuilder.afterClear
+ */
+QueryBuilder.prototype.clear = function() {
+ /**
+ * Before the {@link QueryBuilder#clear} method, can be prevented
+ * @event beforeClear
+ * @memberof QueryBuilder
+ */
+ var e = this.trigger('beforeClear');
+ if (e.isDefaultPrevented()) {
+ return;
+ }
+
+ this.status.group_id = 0;
+ this.status.rule_id = 0;
+
+ if (this.model.root) {
+ this.model.root.drop();
+ this.model.root = null;
+ }
+
+ /**
+ * After the {@link QueryBuilder#clear} method
+ * @event afterClear
+ * @memberof QueryBuilder
+ */
+ this.trigger('afterClear');
+
+ this.trigger('rulesChanged');
+};
+
+/**
+ * Modifies the builder configuration.
+ * Only options defined in QueryBuilder.modifiable_options are modifiable
+ * @param {object} options
+ */
+QueryBuilder.prototype.setOptions = function(options) {
+ $.each(options, function(opt, value) {
+ if (QueryBuilder.modifiable_options.indexOf(opt) !== -1) {
+ this.settings[opt] = value;
+ }
+ }.bind(this));
+};
+
+/**
+ * Returns the model associated to a DOM object, or the root model
+ * @param {jQuery} [target]
+ * @returns {Node}
+ */
+QueryBuilder.prototype.getModel = function(target) {
+ if (!target) {
+ return this.model.root;
+ }
+ else if (target instanceof Node) {
+ return target;
+ }
+ else {
+ return $(target).data('queryBuilderModel');
+ }
+};
+
+/**
+ * Validates the whole builder
+ * @param {object} [options]
+ * @param {boolean} [options.skip_empty=false] - skips validating rules that have no filter selected
+ * @returns {boolean}
+ * @fires QueryBuilder.changer:validate
+ */
+QueryBuilder.prototype.validate = function(options) {
+ options = $.extend({
+ skip_empty: false
+ }, options);
+
+ this.clearErrors();
+
+ var self = this;
+
+ var valid = (function parse(group) {
+ var done = 0;
+ var errors = 0;
+
+ group.each(function(rule) {
+ if (!rule.filter && options.skip_empty) {
+ return;
+ }
+
+ if (!rule.filter) {
+ self.triggerValidationError(rule, 'no_filter', null);
+ errors++;
+ return;
+ }
+
+ if (!rule.operator) {
+ self.triggerValidationError(rule, 'no_operator', null);
+ errors++;
+ return;
+ }
+
+ if (rule.operator.nb_inputs !== 0) {
+ var valid = self.validateValue(rule, rule.value);
+
+ if (valid !== true) {
+ self.triggerValidationError(rule, valid, rule.value);
+ errors++;
+ return;
+ }
+ }
+
+ done++;
+
+ }, function(group) {
+ var res = parse(group);
+ if (res === true) {
+ done++;
+ }
+ else if (res === false) {
+ errors++;
+ }
+ });
+
+ if (errors > 0) {
+ return false;
+ }
+ else if (done === 0 && !group.isRoot() && options.skip_empty) {
+ return null;
+ }
+ else if (done === 0 && (!self.settings.allow_empty || !group.isRoot())) {
+ self.triggerValidationError(group, 'empty_group', null);
+ return false;
+ }
+
+ return true;
+
+ }(this.model.root));
+
+ /**
+ * Modifies the result of the {@link QueryBuilder#validate} method
+ * @event changer:validate
+ * @memberof QueryBuilder
+ * @param {boolean} valid
+ * @returns {boolean}
+ */
+ return this.change('validate', valid);
+};
+
+/**
+ * Gets an object representing current rules
+ * @param {object} [options]
+ * @param {boolean|string} [options.get_flags=false] - export flags, true: only changes from default flags or 'all'
+ * @param {boolean} [options.allow_invalid=false] - returns rules even if they are invalid
+ * @param {boolean} [options.skip_empty=false] - remove rules that have no filter selected
+ * @returns {object}
+ * @fires QueryBuilder.changer:ruleToJson
+ * @fires QueryBuilder.changer:groupToJson
+ * @fires QueryBuilder.changer:getRules
+ */
+QueryBuilder.prototype.getRules = function(options) {
+ options = $.extend({
+ get_flags: false,
+ allow_invalid: false,
+ skip_empty: false
+ }, options);
+
+ var valid = this.validate(options);
+ if (!valid && !options.allow_invalid) {
+ return null;
+ }
+
+ var self = this;
+
+ var out = (function parse(group) {
+ var groupData = {
+ condition: group.condition,
+ rules: []
+ };
+
+ if (group.data) {
+ groupData.data = $.extendext(true, 'replace', {}, group.data);
+ }
+
+ if (options.get_flags) {
+ var flags = self.getGroupFlags(group.flags, options.get_flags === 'all');
+ if (!$.isEmptyObject(flags)) {
+ groupData.flags = flags;
+ }
+ }
+
+ group.each(function(rule) {
+ if (!rule.filter && options.skip_empty) {
+ return;
+ }
+
+ var value = null;
+ if (!rule.operator || rule.operator.nb_inputs !== 0) {
+ value = rule.value;
+ }
+
+ var ruleData = {
+ id: rule.filter ? rule.filter.id : null,
+ field: rule.filter ? rule.filter.field : null,
+ type: rule.filter ? rule.filter.type : null,
+ input: rule.filter ? rule.filter.input : null,
+ operator: rule.operator ? rule.operator.type : null,
+ value: value
+ };
+
+ if (rule.filter && rule.filter.data || rule.data) {
+ ruleData.data = $.extendext(true, 'replace', {}, rule.filter.data, rule.data);
+ }
+
+ if (options.get_flags) {
+ var flags = self.getRuleFlags(rule.flags, options.get_flags === 'all');
+ if (!$.isEmptyObject(flags)) {
+ ruleData.flags = flags;
+ }
+ }
+
+ /**
+ * Modifies the JSON generated from a Rule object
+ * @event changer:ruleToJson
+ * @memberof QueryBuilder
+ * @param {object} json
+ * @param {Rule} rule
+ * @returns {object}
+ */
+ groupData.rules.push(self.change('ruleToJson', ruleData, rule));
+
+ }, function(model) {
+ var data = parse(model);
+ if (data.rules.length !== 0 || !options.skip_empty) {
+ groupData.rules.push(data);
+ }
+ }, this);
+
+ /**
+ * Modifies the JSON generated from a Group object
+ * @event changer:groupToJson
+ * @memberof QueryBuilder
+ * @param {object} json
+ * @param {Group} group
+ * @returns {object}
+ */
+ return self.change('groupToJson', groupData, group);
+
+ }(this.model.root));
+
+ out.valid = valid;
+
+ /**
+ * Modifies the result of the {@link QueryBuilder#getRules} method
+ * @event changer:getRules
+ * @memberof QueryBuilder
+ * @param {object} json
+ * @returns {object}
+ */
+ return this.change('getRules', out);
+};
+
+/**
+ * Sets rules from object
+ * @param {object} data
+ * @param {object} [options]
+ * @param {boolean} [options.allow_invalid=false] - silent-fail if the data are invalid
+ * @throws RulesError, UndefinedConditionError
+ * @fires QueryBuilder.changer:setRules
+ * @fires QueryBuilder.changer:jsonToRule
+ * @fires QueryBuilder.changer:jsonToGroup
+ * @fires QueryBuilder.afterSetRules
+ */
+QueryBuilder.prototype.setRules = function(data, options) {
+ options = $.extend({
+ allow_invalid: false
+ }, options);
+
+ if ($.isArray(data)) {
+ data = {
+ condition: this.settings.default_condition,
+ rules: data
+ };
+ }
+
+ if (!data || !data.rules || (data.rules.length === 0 && !this.settings.allow_empty)) {
+ Utils.error('RulesParse', 'Incorrect data object passed');
+ }
+
+ this.clear();
+ this.setRoot(false, data.data, this.parseGroupFlags(data));
+
+ /**
+ * Modifies data before the {@link QueryBuilder#setRules} method
+ * @event changer:setRules
+ * @memberof QueryBuilder
+ * @param {object} json
+ * @param {object} options
+ * @returns {object}
+ */
+ data = this.change('setRules', data, options);
+
+ var self = this;
+
+ (function add(data, group) {
+ if (group === null) {
+ return;
+ }
+
+ if (data.condition === undefined) {
+ data.condition = self.settings.default_condition;
+ }
+ else if (self.settings.conditions.indexOf(data.condition) == -1) {
+ Utils.error(!options.allow_invalid, 'UndefinedCondition', 'Invalid condition "{0}"', data.condition);
+ data.condition = self.settings.default_condition;
+ }
+
+ group.condition = data.condition;
+
+ data.rules.forEach(function(item) {
+ var model;
+
+ if (item.rules !== undefined) {
+ if (self.settings.allow_groups !== -1 && self.settings.allow_groups < group.level) {
+ Utils.error(!options.allow_invalid, 'RulesParse', 'No more than {0} groups are allowed', self.settings.allow_groups);
+ self.reset();
+ }
+ else {
+ model = self.addGroup(group, false, item.data, self.parseGroupFlags(item));
+ if (model === null) {
+ return;
+ }
+
+ add(item, model);
+ }
+ }
+ else {
+ if (!item.empty) {
+ if (item.id === undefined) {
+ Utils.error(!options.allow_invalid, 'RulesParse', 'Missing rule field id');
+ item.empty = true;
+ }
+ if (item.operator === undefined) {
+ item.operator = 'equal';
+ }
+ }
+
+ model = self.addRule(group, item.data, self.parseRuleFlags(item));
+ if (model === null) {
+ return;
+ }
+
+ if (!item.empty) {
+ model.filter = self.getFilterById(item.id, !options.allow_invalid);
+ }
+
+ if (model.filter) {
+ model.operator = self.getOperatorByType(item.operator, !options.allow_invalid);
+
+ if (!model.operator) {
+ model.operator = self.getOperators(model.filter)[0];
+ }
+ }
+
+ if (model.operator && model.operator.nb_inputs !== 0) {
+ if (item.value !== undefined) {
+ model.value = item.value;
+ }
+ else if (model.filter.default_value !== undefined) {
+ model.value = model.filter.default_value;
+ }
+ }
+
+ /**
+ * Modifies the Rule object generated from the JSON
+ * @event changer:jsonToRule
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ * @param {object} json
+ * @returns {Rule} the same rule
+ */
+ if (self.change('jsonToRule', model, item) != model) {
+ Utils.error('RulesParse', 'Plugin tried to change rule reference');
+ }
+ }
+ });
+
+ /**
+ * Modifies the Group object generated from the JSON
+ * @event changer:jsonToGroup
+ * @memberof QueryBuilder
+ * @param {Group} group
+ * @param {object} json
+ * @returns {Group} the same group
+ */
+ if (self.change('jsonToGroup', group, data) != group) {
+ Utils.error('RulesParse', 'Plugin tried to change group reference');
+ }
+
+ }(data, this.model.root));
+
+ /**
+ * After the {@link QueryBuilder#setRules} method
+ * @event afterSetRules
+ * @memberof QueryBuilder
+ */
+ this.trigger('afterSetRules');
+};
+
+
+/**
+ * Performs value validation
+ * @param {Rule} rule
+ * @param {string|string[]} value
+ * @returns {array|boolean} true or error array
+ * @fires QueryBuilder.changer:validateValue
+ */
+QueryBuilder.prototype.validateValue = function(rule, value) {
+ var validation = rule.filter.validation || {};
+ var result = true;
+
+ if (validation.callback) {
+ result = validation.callback.call(this, value, rule);
+ }
+ else {
+ result = this._validateValue(rule, value);
+ }
+
+ /**
+ * Modifies the result of the rule validation method
+ * @event changer:validateValue
+ * @memberof QueryBuilder
+ * @param {array|boolean} result - true or an error array
+ * @param {*} value
+ * @param {Rule} rule
+ * @returns {array|boolean}
+ */
+ return this.change('validateValue', result, value, rule);
+};
+
+/**
+ * Default validation function
+ * @param {Rule} rule
+ * @param {string|string[]} value
+ * @returns {array|boolean} true or error array
+ * @throws ConfigError
+ * @private
+ */
+QueryBuilder.prototype._validateValue = function(rule, value) {
+ var filter = rule.filter;
+ var operator = rule.operator;
+ var validation = filter.validation || {};
+ var result = true;
+ var tmp, tempValue;
+
+ if (rule.operator.nb_inputs === 1) {
+ value = [value];
+ }
+
+ for (var i = 0; i < operator.nb_inputs; i++) {
+ if (!operator.multiple && $.isArray(value[i]) && value[i].length > 1) {
+ result = ['operator_not_multiple', operator.type, this.translate('operators', operator.type)];
+ break;
+ }
+
+ switch (filter.input) {
+ case 'radio':
+ if (value[i] === undefined || value[i].length === 0) {
+ if (!validation.allow_empty_value) {
+ result = ['radio_empty'];
+ }
+ break;
+ }
+ break;
+
+ case 'checkbox':
+ if (value[i] === undefined || value[i].length === 0) {
+ if (!validation.allow_empty_value) {
+ result = ['checkbox_empty'];
+ }
+ break;
+ }
+ break;
+
+ case 'select':
+ if (value[i] === undefined || value[i].length === 0 || (filter.placeholder && value[i] == filter.placeholder_value)) {
+ if (!validation.allow_empty_value) {
+ result = ['select_empty'];
+ }
+ break;
+ }
+ break;
+
+ default:
+ tempValue = $.isArray(value[i]) ? value[i] : [value[i]];
+
+ for (var j = 0; j < tempValue.length; j++) {
+ switch (QueryBuilder.types[filter.type]) {
+ case 'string':
+ if (tempValue[j] === undefined || tempValue[j].length === 0) {
+ if (!validation.allow_empty_value) {
+ result = ['string_empty'];
+ }
+ break;
+ }
+ if (validation.min !== undefined) {
+ if (tempValue[j].length < parseInt(validation.min)) {
+ result = [this.getValidationMessage(validation, 'min', 'string_exceed_min_length'), validation.min];
+ break;
+ }
+ }
+ if (validation.max !== undefined) {
+ if (tempValue[j].length > parseInt(validation.max)) {
+ result = [this.getValidationMessage(validation, 'max', 'string_exceed_max_length'), validation.max];
+ break;
+ }
+ }
+ if (validation.format) {
+ if (typeof validation.format == 'string') {
+ validation.format = new RegExp(validation.format);
+ }
+ if (!validation.format.test(tempValue[j])) {
+ result = [this.getValidationMessage(validation, 'format', 'string_invalid_format'), validation.format];
+ break;
+ }
+ }
+ break;
+
+ case 'number':
+ if (tempValue[j] === undefined || tempValue[j].length === 0) {
+ if (!validation.allow_empty_value) {
+ result = ['number_nan'];
+ }
+ break;
+ }
+ if (isNaN(tempValue[j])) {
+ result = ['number_nan'];
+ break;
+ }
+ if (filter.type == 'integer') {
+ if (parseInt(tempValue[j]) != tempValue[j]) {
+ result = ['number_not_integer'];
+ break;
+ }
+ }
+ else {
+ if (parseFloat(tempValue[j]) != tempValue[j]) {
+ result = ['number_not_double'];
+ break;
+ }
+ }
+ if (validation.min !== undefined) {
+ if (tempValue[j] < parseFloat(validation.min)) {
+ result = [this.getValidationMessage(validation, 'min', 'number_exceed_min'), validation.min];
+ break;
+ }
+ }
+ if (validation.max !== undefined) {
+ if (tempValue[j] > parseFloat(validation.max)) {
+ result = [this.getValidationMessage(validation, 'max', 'number_exceed_max'), validation.max];
+ break;
+ }
+ }
+ if (validation.step !== undefined && validation.step !== 'any') {
+ var v = (tempValue[j] / validation.step).toPrecision(14);
+ if (parseInt(v) != v) {
+ result = [this.getValidationMessage(validation, 'step', 'number_wrong_step'), validation.step];
+ break;
+ }
+ }
+ break;
+
+ case 'datetime':
+ if (tempValue[j] === undefined || tempValue[j].length === 0) {
+ if (!validation.allow_empty_value) {
+ result = ['datetime_empty'];
+ }
+ break;
+ }
+
+ // we need MomentJS
+ if (validation.format) {
+ if (!('moment' in window)) {
+ Utils.error('MissingLibrary', 'MomentJS is required for Date/Time validation. Get it here http://momentjs.com');
+ }
+
+ var datetime = moment(tempValue[j], validation.format);
+ if (!datetime.isValid()) {
+ result = [this.getValidationMessage(validation, 'format', 'datetime_invalid'), validation.format];
+ break;
+ }
+ else {
+ if (validation.min) {
+ if (datetime < moment(validation.min, validation.format)) {
+ result = [this.getValidationMessage(validation, 'min', 'datetime_exceed_min'), validation.min];
+ break;
+ }
+ }
+ if (validation.max) {
+ if (datetime > moment(validation.max, validation.format)) {
+ result = [this.getValidationMessage(validation, 'max', 'datetime_exceed_max'), validation.max];
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case 'boolean':
+ if (tempValue[j] === undefined || tempValue[j].length === 0) {
+ if (!validation.allow_empty_value) {
+ result = ['boolean_not_valid'];
+ }
+ break;
+ }
+ tmp = ('' + tempValue[j]).trim().toLowerCase();
+ if (tmp !== 'true' && tmp !== 'false' && tmp !== '1' && tmp !== '0' && tempValue[j] !== 1 && tempValue[j] !== 0) {
+ result = ['boolean_not_valid'];
+ break;
+ }
+ }
+
+ if (result !== true) {
+ break;
+ }
+ }
+ }
+
+ if (result !== true) {
+ break;
+ }
+ }
+
+ if ((rule.operator.type === 'between' || rule.operator.type === 'not_between') && value.length === 2) {
+ switch (QueryBuilder.types[filter.type]) {
+ case 'number':
+ if (value[0] > value[1]) {
+ result = ['number_between_invalid', value[0], value[1]];
+ }
+ break;
+
+ case 'datetime':
+ // we need MomentJS
+ if (validation.format) {
+ if (!('moment' in window)) {
+ Utils.error('MissingLibrary', 'MomentJS is required for Date/Time validation. Get it here http://momentjs.com');
+ }
+
+ if (moment(value[0], validation.format).isAfter(moment(value[1], validation.format))) {
+ result = ['datetime_between_invalid', value[0], value[1]];
+ }
+ }
+ break;
+ }
+ }
+
+ return result;
+};
+
+/**
+ * Returns an incremented group ID
+ * @returns {string}
+ * @private
+ */
+QueryBuilder.prototype.nextGroupId = function() {
+ return this.status.id + '_group_' + (this.status.group_id++);
+};
+
+/**
+ * Returns an incremented rule ID
+ * @returns {string}
+ * @private
+ */
+QueryBuilder.prototype.nextRuleId = function() {
+ return this.status.id + '_rule_' + (this.status.rule_id++);
+};
+
+/**
+ * Returns the operators for a filter
+ * @param {string|object} filter - filter id or filter object
+ * @returns {object[]}
+ * @fires QueryBuilder.changer:getOperators
+ */
+QueryBuilder.prototype.getOperators = function(filter) {
+ if (typeof filter == 'string') {
+ filter = this.getFilterById(filter);
+ }
+
+ var result = [];
+
+ for (var i = 0, l = this.operators.length; i < l; i++) {
+ // filter operators check
+ if (filter.operators) {
+ if (filter.operators.indexOf(this.operators[i].type) == -1) {
+ continue;
+ }
+ }
+ // type check
+ else if (this.operators[i].apply_to.indexOf(QueryBuilder.types[filter.type]) == -1) {
+ continue;
+ }
+
+ result.push(this.operators[i]);
+ }
+
+ // keep sort order defined for the filter
+ if (filter.operators) {
+ result.sort(function(a, b) {
+ return filter.operators.indexOf(a.type) - filter.operators.indexOf(b.type);
+ });
+ }
+
+ /**
+ * Modifies the operators available for a filter
+ * @event changer:getOperators
+ * @memberof QueryBuilder
+ * @param {QueryBuilder.Operator[]} operators
+ * @param {QueryBuilder.Filter} filter
+ * @returns {QueryBuilder.Operator[]}
+ */
+ return this.change('getOperators', result, filter);
+};
+
+/**
+ * Returns a particular filter by its id
+ * @param {string} id
+ * @param {boolean} [doThrow=true]
+ * @returns {object|null}
+ * @throws UndefinedFilterError
+ */
+QueryBuilder.prototype.getFilterById = function(id, doThrow) {
+ if (id == '-1') {
+ return null;
+ }
+
+ for (var i = 0, l = this.filters.length; i < l; i++) {
+ if (this.filters[i].id == id) {
+ return this.filters[i];
+ }
+ }
+
+ Utils.error(doThrow !== false, 'UndefinedFilter', 'Undefined filter "{0}"', id);
+
+ return null;
+};
+
+/**
+ * Returns a particular operator by its type
+ * @param {string} type
+ * @param {boolean} [doThrow=true]
+ * @returns {object|null}
+ * @throws UndefinedOperatorError
+ */
+QueryBuilder.prototype.getOperatorByType = function(type, doThrow) {
+ if (type == '-1') {
+ return null;
+ }
+
+ for (var i = 0, l = this.operators.length; i < l; i++) {
+ if (this.operators[i].type == type) {
+ return this.operators[i];
+ }
+ }
+
+ Utils.error(doThrow !== false, 'UndefinedOperator', 'Undefined operator "{0}"', type);
+
+ return null;
+};
+
+/**
+ * Returns rule's current input value
+ * @param {Rule} rule
+ * @returns {*}
+ * @fires QueryBuilder.changer:getRuleValue
+ * @private
+ */
+QueryBuilder.prototype.getRuleInputValue = function(rule) {
+ var filter = rule.filter;
+ var operator = rule.operator;
+ var value = [];
+
+ if (filter.valueGetter) {
+ value = filter.valueGetter.call(this, rule);
+ }
+ else {
+ var $value = rule.$el.find(QueryBuilder.selectors.value_container);
+
+ for (var i = 0; i < operator.nb_inputs; i++) {
+ var name = Utils.escapeElementId(rule.id + '_value_' + i);
+ var tmp;
+
+ switch (filter.input) {
+ case 'radio':
+ value.push($value.find('[name=' + name + ']:checked').val());
+ break;
+
+ case 'checkbox':
+ tmp = [];
+ // jshint loopfunc:true
+ $value.find('[name=' + name + ']:checked').each(function() {
+ tmp.push($(this).val());
+ });
+ // jshint loopfunc:false
+ value.push(tmp);
+ break;
+
+ case 'select':
+ if (filter.multiple) {
+ tmp = [];
+ // jshint loopfunc:true
+ $value.find('[name=' + name + '] option:selected').each(function() {
+ tmp.push($(this).val());
+ });
+ // jshint loopfunc:false
+ value.push(tmp);
+ }
+ else {
+ value.push($value.find('[name=' + name + '] option:selected').val());
+ }
+ break;
+
+ default:
+ value.push($value.find('[name=' + name + ']').val());
+ }
+ }
+
+ value = value.map(function(val) {
+ if (operator.multiple && filter.value_separator && typeof val == 'string') {
+ val = val.split(filter.value_separator);
+ }
+
+ if ($.isArray(val)) {
+ return val.map(function(subval) {
+ return Utils.changeType(subval, filter.type);
+ });
+ }
+ else {
+ return Utils.changeType(val, filter.type);
+ }
+ });
+
+ if (operator.nb_inputs === 1) {
+ value = value[0];
+ }
+
+ // @deprecated
+ if (filter.valueParser) {
+ value = filter.valueParser.call(this, rule, value);
+ }
+ }
+
+ /**
+ * Modifies the rule's value grabbed from the DOM
+ * @event changer:getRuleValue
+ * @memberof QueryBuilder
+ * @param {*} value
+ * @param {Rule} rule
+ * @returns {*}
+ */
+ return this.change('getRuleValue', value, rule);
+};
+
+/**
+ * Sets the value of a rule's input
+ * @param {Rule} rule
+ * @param {*} value
+ * @private
+ */
+QueryBuilder.prototype.setRuleInputValue = function(rule, value) {
+ var filter = rule.filter;
+ var operator = rule.operator;
+
+ if (!filter || !operator) {
+ return;
+ }
+
+ rule._updating_input = true;
+
+ if (filter.valueSetter) {
+ filter.valueSetter.call(this, rule, value);
+ }
+ else {
+ var $value = rule.$el.find(QueryBuilder.selectors.value_container);
+
+ if (operator.nb_inputs == 1) {
+ value = [value];
+ }
+
+ for (var i = 0; i < operator.nb_inputs; i++) {
+ var name = Utils.escapeElementId(rule.id + '_value_' + i);
+
+ switch (filter.input) {
+ case 'radio':
+ $value.find('[name=' + name + '][value="' + value[i] + '"]').prop('checked', true).trigger('change');
+ break;
+
+ case 'checkbox':
+ if (!$.isArray(value[i])) {
+ value[i] = [value[i]];
+ }
+ // jshint loopfunc:true
+ value[i].forEach(function(value) {
+ $value.find('[name=' + name + '][value="' + value + '"]').prop('checked', true).trigger('change');
+ });
+ // jshint loopfunc:false
+ break;
+
+ default:
+ if (operator.multiple && filter.value_separator && $.isArray(value[i])) {
+ value[i] = value[i].join(filter.value_separator);
+ }
+ $value.find('[name=' + name + ']').val(value[i]).trigger('change');
+ break;
+ }
+ }
+ }
+
+ rule._updating_input = false;
+};
+
+/**
+ * Parses rule flags
+ * @param {object} rule
+ * @returns {object}
+ * @fires QueryBuilder.changer:parseRuleFlags
+ * @private
+ */
+QueryBuilder.prototype.parseRuleFlags = function(rule) {
+ var flags = $.extend({}, this.settings.default_rule_flags);
+
+ if (rule.readonly) {
+ $.extend(flags, {
+ filter_readonly: true,
+ operator_readonly: true,
+ value_readonly: true,
+ no_delete: true
+ });
+ }
+
+ if (rule.flags) {
+ $.extend(flags, rule.flags);
+ }
+
+ /**
+ * Modifies the consolidated rule's flags
+ * @event changer:parseRuleFlags
+ * @memberof QueryBuilder
+ * @param {object} flags
+ * @param {object} rule - not a Rule object
+ * @returns {object}
+ */
+ return this.change('parseRuleFlags', flags, rule);
+};
+
+/**
+ * Gets a copy of flags of a rule
+ * @param {object} flags
+ * @param {boolean} [all=false] - return all flags or only changes from default flags
+ * @returns {object}
+ * @private
+ */
+QueryBuilder.prototype.getRuleFlags = function(flags, all) {
+ if (all) {
+ return $.extend({}, flags);
+ }
+ else {
+ var ret = {};
+ $.each(this.settings.default_rule_flags, function(key, value) {
+ if (flags[key] !== value) {
+ ret[key] = flags[key];
+ }
+ });
+ return ret;
+ }
+};
+
+/**
+ * Parses group flags
+ * @param {object} group
+ * @returns {object}
+ * @fires QueryBuilder.changer:parseGroupFlags
+ * @private
+ */
+QueryBuilder.prototype.parseGroupFlags = function(group) {
+ var flags = $.extend({}, this.settings.default_group_flags);
+
+ if (group.readonly) {
+ $.extend(flags, {
+ condition_readonly: true,
+ no_add_rule: true,
+ no_add_group: true,
+ no_delete: true
+ });
+ }
+
+ if (group.flags) {
+ $.extend(flags, group.flags);
+ }
+
+ /**
+ * Modifies the consolidated group's flags
+ * @event changer:parseGroupFlags
+ * @memberof QueryBuilder
+ * @param {object} flags
+ * @param {object} group - not a Group object
+ * @returns {object}
+ */
+ return this.change('parseGroupFlags', flags, group);
+};
+
+/**
+ * Gets a copy of flags of a group
+ * @param {object} flags
+ * @param {boolean} [all=false] - return all flags or only changes from default flags
+ * @returns {object}
+ * @private
+ */
+QueryBuilder.prototype.getGroupFlags = function(flags, all) {
+ if (all) {
+ return $.extend({}, flags);
+ }
+ else {
+ var ret = {};
+ $.each(this.settings.default_group_flags, function(key, value) {
+ if (flags[key] !== value) {
+ ret[key] = flags[key];
+ }
+ });
+ return ret;
+ }
+};
+
+/**
+ * Translate a label either by looking in the `lang` object or in itself if it's an object where keys are language codes
+ * @param {string} [category]
+ * @param {string|object} key
+ * @returns {string}
+ * @fires QueryBuilder.changer:translate
+ */
+QueryBuilder.prototype.translate = function(category, key) {
+ if (!key) {
+ key = category;
+ category = undefined;
+ }
+
+ var translation;
+ if (typeof key === 'object') {
+ translation = key[this.settings.lang_code] || key['en'];
+ }
+ else {
+ translation = (category ? this.lang[category] : this.lang)[key] || key;
+ }
+
+ /**
+ * Modifies the translated label
+ * @event changer:translate
+ * @memberof QueryBuilder
+ * @param {string} translation
+ * @param {string|object} key
+ * @param {string} [category]
+ * @returns {string}
+ */
+ return this.change('translate', translation, key, category);
+};
+
+/**
+ * Returns a validation message
+ * @param {object} validation
+ * @param {string} type
+ * @param {string} def
+ * @returns {string}
+ * @private
+ */
+QueryBuilder.prototype.getValidationMessage = function(validation, type, def) {
+ return validation.messages && validation.messages[type] || def;
+};
+
+
+QueryBuilder.templates.group = '\
+';
+
+QueryBuilder.templates.rule = '\
+ \
+ \
+ {{? it.settings.display_errors }} \
+
\
+ {{?}} \
+
\
+
\
+
\
+
';
+
+QueryBuilder.templates.filterSelect = '\
+{{ var optgroup = null; }} \
+ \
+ {{? it.settings.display_empty_filter }} \
+ {{= it.settings.select_placeholder }} \
+ {{?}} \
+ {{~ it.filters: filter }} \
+ {{? optgroup !== filter.optgroup }} \
+ {{? optgroup !== null }}{{?}} \
+ {{? (optgroup = filter.optgroup) !== null }} \
+ \
+ {{?}} \
+ {{?}} \
+ {{= it.translate(filter.label) }} \
+ {{~}} \
+ {{? optgroup !== null }} {{?}} \
+ ';
+
+QueryBuilder.templates.operatorSelect = '\
+{{? it.operators.length === 1 }} \
+ \
+{{= it.translate("operators", it.operators[0].type) }} \
+ \
+{{?}} \
+{{ var optgroup = null; }} \
+ \
+ {{~ it.operators: operator }} \
+ {{? optgroup !== operator.optgroup }} \
+ {{? optgroup !== null }}{{?}} \
+ {{? (optgroup = operator.optgroup) !== null }} \
+ \
+ {{?}} \
+ {{?}} \
+ {{= it.translate("operators", operator.type) }} \
+ {{~}} \
+ {{? optgroup !== null }} {{?}} \
+ ';
+
+QueryBuilder.templates.ruleValueSelect = '\
+{{ var optgroup = null; }} \
+ \
+ {{? it.rule.filter.placeholder }} \
+ {{= it.rule.filter.placeholder }} \
+ {{?}} \
+ {{~ it.rule.filter.values: entry }} \
+ {{? optgroup !== entry.optgroup }} \
+ {{? optgroup !== null }}{{?}} \
+ {{? (optgroup = entry.optgroup) !== null }} \
+ \
+ {{?}} \
+ {{?}} \
+ {{= entry.label }} \
+ {{~}} \
+ {{? optgroup !== null }} {{?}} \
+ ';
+
+/**
+ * Returns group's HTML
+ * @param {string} group_id
+ * @param {int} level
+ * @returns {string}
+ * @fires QueryBuilder.changer:getGroupTemplate
+ * @private
+ */
+QueryBuilder.prototype.getGroupTemplate = function(group_id, level) {
+ var h = this.templates.group({
+ builder: this,
+ group_id: group_id,
+ level: level,
+ conditions: this.settings.conditions,
+ icons: this.icons,
+ settings: this.settings,
+ translate: this.translate.bind(this)
+ });
+
+ /**
+ * Modifies the raw HTML of a group
+ * @event changer:getGroupTemplate
+ * @memberof QueryBuilder
+ * @param {string} html
+ * @param {int} level
+ * @returns {string}
+ */
+ return this.change('getGroupTemplate', h, level);
+};
+
+/**
+ * Returns rule's HTML
+ * @param {string} rule_id
+ * @returns {string}
+ * @fires QueryBuilder.changer:getRuleTemplate
+ * @private
+ */
+QueryBuilder.prototype.getRuleTemplate = function(rule_id) {
+ var h = this.templates.rule({
+ builder: this,
+ rule_id: rule_id,
+ icons: this.icons,
+ settings: this.settings,
+ translate: this.translate.bind(this)
+ });
+
+ /**
+ * Modifies the raw HTML of a rule
+ * @event changer:getRuleTemplate
+ * @memberof QueryBuilder
+ * @param {string} html
+ * @returns {string}
+ */
+ return this.change('getRuleTemplate', h);
+};
+
+/**
+ * Returns rule's filter HTML
+ * @param {Rule} rule
+ * @param {object[]} filters
+ * @returns {string}
+ * @fires QueryBuilder.changer:getRuleFilterTemplate
+ * @private
+ */
+QueryBuilder.prototype.getRuleFilterSelect = function(rule, filters) {
+ var h = this.templates.filterSelect({
+ builder: this,
+ rule: rule,
+ filters: filters,
+ icons: this.icons,
+ settings: this.settings,
+ translate: this.translate.bind(this)
+ });
+
+ /**
+ * Modifies the raw HTML of the rule's filter dropdown
+ * @event changer:getRuleFilterSelect
+ * @memberof QueryBuilder
+ * @param {string} html
+ * @param {Rule} rule
+ * @param {QueryBuilder.Filter[]} filters
+ * @returns {string}
+ */
+ return this.change('getRuleFilterSelect', h, rule, filters);
+};
+
+/**
+ * Returns rule's operator HTML
+ * @param {Rule} rule
+ * @param {object[]} operators
+ * @returns {string}
+ * @fires QueryBuilder.changer:getRuleOperatorTemplate
+ * @private
+ */
+QueryBuilder.prototype.getRuleOperatorSelect = function(rule, operators) {
+ var h = this.templates.operatorSelect({
+ builder: this,
+ rule: rule,
+ operators: operators,
+ icons: this.icons,
+ settings: this.settings,
+ translate: this.translate.bind(this)
+ });
+
+ /**
+ * Modifies the raw HTML of the rule's operator dropdown
+ * @event changer:getRuleOperatorSelect
+ * @memberof QueryBuilder
+ * @param {string} html
+ * @param {Rule} rule
+ * @param {QueryBuilder.Operator[]} operators
+ * @returns {string}
+ */
+ return this.change('getRuleOperatorSelect', h, rule, operators);
+};
+
+/**
+ * Returns the rule's value select HTML
+ * @param {string} name
+ * @param {Rule} rule
+ * @returns {string}
+ * @fires QueryBuilder.changer:getRuleValueSelect
+ * @private
+ */
+QueryBuilder.prototype.getRuleValueSelect = function(name, rule) {
+ var h = this.templates.ruleValueSelect({
+ builder: this,
+ name: name,
+ rule: rule,
+ icons: this.icons,
+ settings: this.settings,
+ translate: this.translate.bind(this)
+ });
+
+ /**
+ * Modifies the raw HTML of the rule's value dropdown (in case of a "select filter)
+ * @event changer:getRuleValueSelect
+ * @memberof QueryBuilder
+ * @param {string} html
+ * @param [string} name
+ * @param {Rule} rule
+ * @returns {string}
+ */
+ return this.change('getRuleValueSelect', h, name, rule);
+};
+
+/**
+ * Returns the rule's value HTML
+ * @param {Rule} rule
+ * @param {int} value_id
+ * @returns {string}
+ * @fires QueryBuilder.changer:getRuleInput
+ * @private
+ */
+QueryBuilder.prototype.getRuleInput = function(rule, value_id) {
+ var filter = rule.filter;
+ var validation = rule.filter.validation || {};
+ var name = rule.id + '_value_' + value_id;
+ var c = filter.vertical ? ' class=block' : '';
+ var h = '';
+ var placeholder = Array.isArray(filter.placeholder) ? filter.placeholder[value_id] : filter.placeholder;
+
+ if (typeof filter.input == 'function') {
+ h = filter.input.call(this, rule, name);
+ }
+ else {
+ switch (filter.input) {
+ case 'radio':
+ case 'checkbox':
+ Utils.iterateOptions(filter.values, function(key, val) {
+ h += ' ' + val + ' ';
+ });
+ break;
+
+ case 'select':
+ h = this.getRuleValueSelect(name, rule);
+ break;
+
+ case 'textarea':
+ h += '" ; + break + + case number : + h +=' " ; + break + + default + h +=' " ; + } + } + + + * Modifies the raw HTML of the rule s input + * @event changer:getRuleInput + * @memberof QueryBuilder + * @param {string html + * @param {Rule rule + * @param {string name - the name that the input must have + * @returns {string + * + return this.change getRuleInput , h rule name + + + + + * @namespace + * +var Utils="{};" + + + * @member {object + * @memberof QueryBuilder + * @see Utils + * +QueryBuilder.utils="Utils;" + + + * @callback Utils#OptionsIteratee + * @param {string key + * @param {string value + * @param {string [optgroup + * + + + * Iterates over radio/checkbox/selection options it accept four formats + * + * @example + * array of values + * options="['one'," two , three ] + * @example + * simple key-value map + * options="{1:" one , 2 two , 3 three } + * @example + * array of 1-element maps + * options="[{1:" one } {2 two } {3 three } + * @example + * array of elements + * options="[{value:" 1 label one , optgroup group } {value 2 label two } + * + * @param {object|array options + * @param {Utils#OptionsIteratee tpl + * +Utils.iterateOptions="function(options," tpl { + if (options { + if ($.isArray(options { + options.forEach(function(entry { + if ($.isPlainObject(entry { + array of elements + if ( value in entry { + tpl(entry.value entry.label | entry.value entry.optgroup + } + array of one-element maps + else { + $.each(entry function(key val { + tpl(key val + return false break after first entry + } + } + } + array of values + else { + tpl(entry entry + } + } + } + unordered map + else { + $.each(options function(key val { + tpl(key val + } + } + } + + + + * Replaces {0 {1 . in a string + * @param {string str + * @param { args + * @returns {string + * +Utils.fmt="function(str," args { + if (!Array.isArray(args { + args="Array.prototype.slice.call(arguments," 1 + } + + return str.replace(/{([0-9]+)}/g function(m i { + return args[parseInt(i + } + + + + * Throws an Error object with custom name or logs an error + * @param {boolean [doThrow="true]" + * @param {string type + * @param {string message + * @param { args + * +Utils.error="function()" { + var i="0;" + var doThrow="typeof" arguments[i="==" boolean ? arguments[i : true + var type="arguments[i++];" + var message="arguments[i++];" + var args="Array.isArray(arguments[i])" ? arguments[i : Array.prototype.slice.call(arguments i + + if (doThrow { + var err="new" Error(Utils.fmt(message args + err.name="type" + Error ; + err.args="args;" + throw err + } + else { + console.error(type + Error + Utils.fmt(message args + } + + + + * Changes the type of a value to int float or bool + * @param { value + * @param {string type - integer , double , boolean or anything else (passthrough + * @returns { + * +Utils.changeType="function(value," type { + if (value="==" | value="==" undefined { + return undefined + } + + switch (type { + @formatter:off + case integer : + if (typeof value="==" string & !/^-?\d+$/.test(value { + return value + } + return parseInt(value + case double : + if (typeof value="==" string & !/^-?\d+\.?\d*$/.test(value { + return value + } + return parseFloat(value + case boolean : + if (typeof value="==" string & !/^(0|1|true|false){1}$/i.test(value { + return value + } + return value="==" true | value="==" 1 | value.toLowerCase="==" true | value="==" 1 ; + default return value + @formatter:on + } + + + + * Escapes a string like PHP s mysql_real_escape_string does + * @param {string value + * @returns {string + * +Utils.escapeString="function(value)" { + if (typeof value !="string" ) { + return value + } + + return value + .replace(/[\0\n\r\b \ ]/g function(s { + switch (s { + @formatter:off + case \0 : return \\0 ; + case \n : return \\n ; + case \r : return \\r ; + case \b : return \\b ; + default return \ + s + @formatter:off + } + } + uglify compliant + .replace(/\t/g \\t ) + .replace(/\x1a/g \\Z ) + + + + * Escapes a string for use in regex + * @param {string str + * @returns {string + * +Utils.escapeRegExp="function(str)" { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g \ ) + + + + * Escapes a string for use in HTML element id + * @param {string str + * @returns {string + * +Utils.escapeElementId="function(str)" { + Regex based on that suggested by + https://learn.jquery.com/using-jquery-core/faq/how-do-i-select-an-element-by-an-id-that-has-characters-used-in-css-notation + - escapes : . [ ] , + - avoids escaping already escaped values + return (str ? str.replace(/(\\)?([:.\[\],])/g + function $0 $1 $2 ) { return $1 ? $0 : \ + $2 } : str + + + + * Sorts objects by grouping them by `key preserving initial order when possible + * @param {object items + * @param {string key + * @returns {object + * +Utils.groupSort="function(items," key { + var optgroups="[];" + var newItems="[];" + + items.forEach(function(item { + var idx + + if (item[key { + idx="optgroups.lastIndexOf(item[key]);" + + if (idx="=" -1 { + idx="optgroups.length;" + } + else { + idx + } + } + else { + idx="optgroups.length;" + } + + optgroups.splice(idx 0 item[key + newItems.splice(idx 0 item + } + + return newItems + + + + * Defines properties on an Node prototype with getter and setter />
+ * Update events are emitted in the setter through root Model (if any).
+ * The object must have a `__` object, non enumerable property to store values.
+ * @param {function} obj
+ * @param {string[]} fields
+ */
+Utils.defineModelProperties = function(obj, fields) {
+ fields.forEach(function(field) {
+ Object.defineProperty(obj.prototype, field, {
+ enumerable: true,
+ get: function() {
+ return this.__[field];
+ },
+ set: function(value) {
+ var previousValue = (this.__[field] !== null && typeof this.__[field] == 'object') ?
+ $.extend({}, this.__[field]) :
+ this.__[field];
+
+ this.__[field] = value;
+
+ if (this.model !== null) {
+ /**
+ * After a value of the model changed
+ * @event model:update
+ * @memberof Model
+ * @param {Node} node
+ * @param {string} field
+ * @param {*} value
+ * @param {*} previousValue
+ */
+ this.model.trigger('update', this, field, value, previousValue);
+ }
+ }
+ });
+ });
+};
+
+
+/**
+ * Main object storing data model and emitting model events
+ * @constructor
+ */
+function Model() {
+ /**
+ * @member {Group}
+ * @readonly
+ */
+ this.root = null;
+
+ /**
+ * Base for event emitting
+ * @member {jQuery}
+ * @readonly
+ * @private
+ */
+ this.$ = $(this);
+}
+
+$.extend(Model.prototype, /** @lends Model.prototype */ {
+ /**
+ * Triggers an event on the model
+ * @param {string} type
+ * @returns {$.Event}
+ */
+ trigger: function(type) {
+ var event = new $.Event(type);
+ this.$.triggerHandler(event, Array.prototype.slice.call(arguments, 1));
+ return event;
+ },
+
+ /**
+ * Attaches an event listener on the model
+ * @param {string} type
+ * @param {function} cb
+ * @returns {Model}
+ */
+ on: function() {
+ this.$.on.apply(this.$, Array.prototype.slice.call(arguments));
+ return this;
+ },
+
+ /**
+ * Removes an event listener from the model
+ * @param {string} type
+ * @param {function} [cb]
+ * @returns {Model}
+ */
+ off: function() {
+ this.$.off.apply(this.$, Array.prototype.slice.call(arguments));
+ return this;
+ },
+
+ /**
+ * Attaches an event listener called once on the model
+ * @param {string} type
+ * @param {function} cb
+ * @returns {Model}
+ */
+ once: function() {
+ this.$.one.apply(this.$, Array.prototype.slice.call(arguments));
+ return this;
+ }
+});
+
+
+/**
+ * Root abstract object
+ * @constructor
+ * @param {Node} [parent]
+ * @param {jQuery} $el
+ */
+var Node = function(parent, $el) {
+ if (!(this instanceof Node)) {
+ return new Node(parent, $el);
+ }
+
+ Object.defineProperty(this, '__', { value: {} });
+
+ $el.data('queryBuilderModel', this);
+
+ /**
+ * @name level
+ * @member {int}
+ * @memberof Node
+ * @instance
+ * @readonly
+ */
+ this.__.level = 1;
+
+ /**
+ * @name error
+ * @member {string}
+ * @memberof Node
+ * @instance
+ */
+ this.__.error = null;
+
+ /**
+ * @name flags
+ * @member {object}
+ * @memberof Node
+ * @instance
+ * @readonly
+ */
+ this.__.flags = {};
+
+ /**
+ * @name data
+ * @member {object}
+ * @memberof Node
+ * @instance
+ */
+ this.__.data = undefined;
+
+ /**
+ * @member {jQuery}
+ * @readonly
+ */
+ this.$el = $el;
+
+ /**
+ * @member {string}
+ * @readonly
+ */
+ this.id = $el[0].id;
+
+ /**
+ * @member {Model}
+ * @readonly
+ */
+ this.model = null;
+
+ /**
+ * @member {Group}
+ * @readonly
+ */
+ this.parent = parent;
+};
+
+Utils.defineModelProperties(Node, ['level', 'error', 'data', 'flags']);
+
+Object.defineProperty(Node.prototype, 'parent', {
+ enumerable: true,
+ get: function() {
+ return this.__.parent;
+ },
+ set: function(value) {
+ this.__.parent = value;
+ this.level = value === null ? 1 : value.level + 1;
+ this.model = value === null ? null : value.model;
+ }
+});
+
+/**
+ * Checks if this Node is the root
+ * @returns {boolean}
+ */
+Node.prototype.isRoot = function() {
+ return (this.level === 1);
+};
+
+/**
+ * Returns the node position inside its parent
+ * @returns {int}
+ */
+Node.prototype.getPos = function() {
+ if (this.isRoot()) {
+ return -1;
+ }
+ else {
+ return this.parent.getNodePos(this);
+ }
+};
+
+/**
+ * Deletes self
+ * @fires Model.model:drop
+ */
+Node.prototype.drop = function() {
+ var model = this.model;
+
+ if (!!this.parent) {
+ this.parent.removeNode(this);
+ }
+
+ this.$el.removeData('queryBuilderModel');
+
+ if (model !== null) {
+ /**
+ * After a node of the model has been removed
+ * @event model:drop
+ * @memberof Model
+ * @param {Node} node
+ */
+ model.trigger('drop', this);
+ }
+};
+
+/**
+ * Moves itself after another Node
+ * @param {Node} target
+ * @fires Model.model:move
+ */
+Node.prototype.moveAfter = function(target) {
+ if (!this.isRoot()) {
+ this.move(target.parent, target.getPos() + 1);
+ }
+};
+
+/**
+ * Moves itself at the beginning of parent or another Group
+ * @param {Group} [target]
+ * @fires Model.model:move
+ */
+Node.prototype.moveAtBegin = function(target) {
+ if (!this.isRoot()) {
+ if (target === undefined) {
+ target = this.parent;
+ }
+
+ this.move(target, 0);
+ }
+};
+
+/**
+ * Moves itself at the end of parent or another Group
+ * @param {Group} [target]
+ * @fires Model.model:move
+ */
+Node.prototype.moveAtEnd = function(target) {
+ if (!this.isRoot()) {
+ if (target === undefined) {
+ target = this.parent;
+ }
+
+ this.move(target, target.length() === 0 ? 0 : target.length() - 1);
+ }
+};
+
+/**
+ * Moves itself at specific position of Group
+ * @param {Group} target
+ * @param {int} index
+ * @fires Model.model:move
+ */
+Node.prototype.move = function(target, index) {
+ if (!this.isRoot()) {
+ if (typeof target === 'number') {
+ index = target;
+ target = this.parent;
+ }
+
+ this.parent.removeNode(this);
+ target.insertNode(this, index, false);
+
+ if (this.model !== null) {
+ /**
+ * After a node of the model has been moved
+ * @event model:move
+ * @memberof Model
+ * @param {Node} node
+ * @param {Node} target
+ * @param {int} index
+ */
+ this.model.trigger('move', this, target, index);
+ }
+ }
+};
+
+
+/**
+ * Group object
+ * @constructor
+ * @extends Node
+ * @param {Group} [parent]
+ * @param {jQuery} $el
+ */
+var Group = function(parent, $el) {
+ if (!(this instanceof Group)) {
+ return new Group(parent, $el);
+ }
+
+ Node.call(this, parent, $el);
+
+ /**
+ * @member {object[]}
+ * @readonly
+ */
+ this.rules = [];
+
+ /**
+ * @name condition
+ * @member {string}
+ * @memberof Group
+ * @instance
+ */
+ this.__.condition = null;
+};
+
+Group.prototype = Object.create(Node.prototype);
+Group.prototype.constructor = Group;
+
+Utils.defineModelProperties(Group, ['condition']);
+
+/**
+ * Removes group's content
+ */
+Group.prototype.empty = function() {
+ this.each('reverse', function(rule) {
+ rule.drop();
+ }, function(group) {
+ group.drop();
+ });
+};
+
+/**
+ * Deletes self
+ */
+Group.prototype.drop = function() {
+ this.empty();
+ Node.prototype.drop.call(this);
+};
+
+/**
+ * Returns the number of children
+ * @returns {int}
+ */
+Group.prototype.length = function() {
+ return this.rules.length;
+};
+
+/**
+ * Adds a Node at specified index
+ * @param {Node} node
+ * @param {int} [index=end]
+ * @param {boolean} [trigger=false] - fire 'add' event
+ * @returns {Node} the inserted node
+ * @fires Model.model:add
+ */
+Group.prototype.insertNode = function(node, index, trigger) {
+ if (index === undefined) {
+ index = this.length();
+ }
+
+ this.rules.splice(index, 0, node);
+ node.parent = this;
+
+ if (trigger && this.model !== null) {
+ /**
+ * After a node of the model has been added
+ * @event model:add
+ * @memberof Model
+ * @param {Node} parent
+ * @param {Node} node
+ * @param {int} index
+ */
+ this.model.trigger('add', this, node, index);
+ }
+
+ return node;
+};
+
+/**
+ * Adds a new Group at specified index
+ * @param {jQuery} $el
+ * @param {int} [index=end]
+ * @returns {Group}
+ * @fires Model.model:add
+ */
+Group.prototype.addGroup = function($el, index) {
+ return this.insertNode(new Group(this, $el), index, true);
+};
+
+/**
+ * Adds a new Rule at specified index
+ * @param {jQuery} $el
+ * @param {int} [index=end]
+ * @returns {Rule}
+ * @fires Model.model:add
+ */
+Group.prototype.addRule = function($el, index) {
+ return this.insertNode(new Rule(this, $el), index, true);
+};
+
+/**
+ * Deletes a specific Node
+ * @param {Node} node
+ */
+Group.prototype.removeNode = function(node) {
+ var index = this.getNodePos(node);
+ if (index !== -1) {
+ node.parent = null;
+ this.rules.splice(index, 1);
+ }
+};
+
+/**
+ * Returns the position of a child Node
+ * @param {Node} node
+ * @returns {int}
+ */
+Group.prototype.getNodePos = function(node) {
+ return this.rules.indexOf(node);
+};
+
+/**
+ * @callback Model#GroupIteratee
+ * @param {Node} node
+ * @returns {boolean} stop the iteration
+ */
+
+/**
+ * Iterate over all Nodes
+ * @param {boolean} [reverse=false] - iterate in reverse order, required if you delete nodes
+ * @param {Model#GroupIteratee} cbRule - callback for Rules (can be `null` but not omitted)
+ * @param {Model#GroupIteratee} [cbGroup] - callback for Groups
+ * @param {object} [context] - context for callbacks
+ * @returns {boolean} if the iteration has been stopped by a callback
+ */
+Group.prototype.each = function(reverse, cbRule, cbGroup, context) {
+ if (typeof reverse !== 'boolean' && typeof reverse !== 'string') {
+ context = cbGroup;
+ cbGroup = cbRule;
+ cbRule = reverse;
+ reverse = false;
+ }
+ context = context === undefined ? null : context;
+
+ var i = reverse ? this.rules.length - 1 : 0;
+ var l = reverse ? 0 : this.rules.length - 1;
+ var c = reverse ? -1 : 1;
+ var next = function() {
+ return reverse ? i >= l : i <= l;
+ };
+ var stop = false;
+
+ for (; next(); i += c) {
+ if (this.rules[i] instanceof Group) {
+ if (!!cbGroup) {
+ stop = cbGroup.call(context, this.rules[i]) === false;
+ }
+ }
+ else if (!!cbRule) {
+ stop = cbRule.call(context, this.rules[i]) === false;
+ }
+
+ if (stop) {
+ break;
+ }
+ }
+
+ return !stop;
+};
+
+/**
+ * Checks if the group contains a particular Node
+ * @param {Node} node
+ * @param {boolean} [recursive=false]
+ * @returns {boolean}
+ */
+Group.prototype.contains = function(node, recursive) {
+ if (this.getNodePos(node) !== -1) {
+ return true;
+ }
+ else if (!recursive) {
+ return false;
+ }
+ else {
+ // the loop will return with false as soon as the Node is found
+ return !this.each(function() {
+ return true;
+ }, function(group) {
+ return !group.contains(node, true);
+ });
+ }
+};
+
+
+/**
+ * Rule object
+ * @constructor
+ * @extends Node
+ * @param {Group} parent
+ * @param {jQuery} $el
+ */
+var Rule = function(parent, $el) {
+ if (!(this instanceof Rule)) {
+ return new Rule(parent, $el);
+ }
+
+ Node.call(this, parent, $el);
+
+ this._updating_value = false;
+ this._updating_input = false;
+
+ /**
+ * @name filter
+ * @member {QueryBuilder.Filter}
+ * @memberof Rule
+ * @instance
+ */
+ this.__.filter = null;
+
+ /**
+ * @name operator
+ * @member {QueryBuilder.Operator}
+ * @memberof Rule
+ * @instance
+ */
+ this.__.operator = null;
+
+ /**
+ * @name value
+ * @member {*}
+ * @memberof Rule
+ * @instance
+ */
+ this.__.value = undefined;
+};
+
+Rule.prototype = Object.create(Node.prototype);
+Rule.prototype.constructor = Rule;
+
+Utils.defineModelProperties(Rule, ['filter', 'operator', 'value']);
+
+/**
+ * Checks if this Node is the root
+ * @returns {boolean} always false
+ */
+Rule.prototype.isRoot = function() {
+ return false;
+};
+
+
+/**
+ * @member {function}
+ * @memberof QueryBuilder
+ * @see Group
+ */
+QueryBuilder.Group = Group;
+
+/**
+ * @member {function}
+ * @memberof QueryBuilder
+ * @see Rule
+ */
+QueryBuilder.Rule = Rule;
+
+
+/**
+ * The {@link http://learn.jquery.com/plugins/|jQuery Plugins} namespace
+ * @external "jQuery.fn"
+ */
+
+/**
+ * Instanciates or accesses the {@link QueryBuilder} on an element
+ * @function
+ * @memberof external:"jQuery.fn"
+ * @param {*} option - initial configuration or method name
+ * @param {...*} args - method arguments
+ *
+ * @example
+ * $('#builder').queryBuilder({ /** configuration object *\/ });
+ * @example
+ * $('#builder').queryBuilder('methodName', methodParam1, methodParam2);
+ */
+$.fn.queryBuilder = function(option) {
+ if (this.length === 0) {
+ Utils.error('Config', 'No target defined');
+ }
+ if (this.length > 1) {
+ Utils.error('Config', 'Unable to initialize on multiple target');
+ }
+
+ var data = this.data('queryBuilder');
+ var options = (typeof option == 'object' && option) || {};
+
+ if (!data && option == 'destroy') {
+ return this;
+ }
+ if (!data) {
+ var builder = new QueryBuilder(this, options);
+ this.data('queryBuilder', builder);
+ builder.init(options.rules);
+ }
+ if (typeof option == 'string') {
+ return data[option].apply(data, Array.prototype.slice.call(arguments, 1));
+ }
+
+ return this;
+};
+
+/**
+ * @function
+ * @memberof external:"jQuery.fn"
+ * @see QueryBuilder
+ */
+$.fn.queryBuilder.constructor = QueryBuilder;
+
+/**
+ * @function
+ * @memberof external:"jQuery.fn"
+ * @see QueryBuilder.defaults
+ */
+$.fn.queryBuilder.defaults = QueryBuilder.defaults;
+
+/**
+ * @function
+ * @memberof external:"jQuery.fn"
+ * @see QueryBuilder.defaults
+ */
+$.fn.queryBuilder.extend = QueryBuilder.extend;
+
+/**
+ * @function
+ * @memberof external:"jQuery.fn"
+ * @see QueryBuilder.define
+ */
+$.fn.queryBuilder.define = QueryBuilder.define;
+
+/**
+ * @function
+ * @memberof external:"jQuery.fn"
+ * @see QueryBuilder.regional
+ */
+$.fn.queryBuilder.regional = QueryBuilder.regional;
+
+
+/**
+ * @class BtCheckbox
+ * @memberof module:plugins
+ * @description Applies Awesome Bootstrap Checkbox for checkbox and radio inputs.
+ * @param {object} [options]
+ * @param {string} [options.font='glyphicons']
+ * @param {string} [options.color='default']
+ */
+QueryBuilder.define('bt-checkbox', function(options) {
+ if (options.font == 'glyphicons') {
+ this.$el.addClass('bt-checkbox-glyphicons');
+ }
+
+ this.on('getRuleInput.filter', function(h, rule, name) {
+ var filter = rule.filter;
+
+ if ((filter.input === 'radio' || filter.input === 'checkbox') && !filter.plugin) {
+ h.value = '';
+
+ if (!filter.colors) {
+ filter.colors = {};
+ }
+ if (filter.color) {
+ filter.colors._def_ = filter.color;
+ }
+
+ var style = filter.vertical ? ' style="display:block"' : '';
+ var i = 0;
+
+ Utils.iterateOptions(filter.values, function(key, val) {
+ var color = filter.colors[key] || filter.colors._def_ || options.color;
+ var id = name + '_' + (i++);
+
+ h.value+= '\
+ \
+ \
+ ' + val + ' \
+
';
+ });
+ }
+ });
+}, {
+ font: 'glyphicons',
+ color: 'default'
+});
+
+
+/**
+ * @class BtSelectpicker
+ * @memberof module:plugins
+ * @descriptioon Applies Bootstrap Select on filters and operators combo-boxes.
+ * @param {object} [options]
+ * @param {string} [options.container='body']
+ * @param {string} [options.style='btn-inverse btn-sm']
+ * @param {int|string} [options.width='auto']
+ * @param {boolean} [options.showIcon=false]
+ * @throws MissingLibraryError
+ */
+QueryBuilder.define('bt-selectpicker', function(options) {
+ if (!$.fn.selectpicker || !$.fn.selectpicker.Constructor) {
+ Utils.error('MissingLibrary', 'Bootstrap Select is required to use "bt-selectpicker" plugin. Get it here: http://silviomoreto.github.io/bootstrap-select');
+ }
+
+ var Selectors = QueryBuilder.selectors;
+
+ // init selectpicker
+ this.on('afterCreateRuleFilters', function(e, rule) {
+ rule.$el.find(Selectors.rule_filter).removeClass('form-control').selectpicker(options);
+ });
+
+ this.on('afterCreateRuleOperators', function(e, rule) {
+ rule.$el.find(Selectors.rule_operator).removeClass('form-control').selectpicker(options);
+ });
+
+ // update selectpicker on change
+ this.on('afterUpdateRuleFilter', function(e, rule) {
+ rule.$el.find(Selectors.rule_filter).selectpicker('render');
+ });
+
+ this.on('afterUpdateRuleOperator', function(e, rule) {
+ rule.$el.find(Selectors.rule_operator).selectpicker('render');
+ });
+
+ this.on('beforeDeleteRule', function(e, rule) {
+ rule.$el.find(Selectors.rule_filter).selectpicker('destroy');
+ rule.$el.find(Selectors.rule_operator).selectpicker('destroy');
+ });
+}, {
+ container: 'body',
+ style: 'btn-inverse btn-sm',
+ width: 'auto',
+ showIcon: false
+});
+
+
+/**
+ * @class BtTooltipErrors
+ * @memberof module:plugins
+ * @description Applies Bootstrap Tooltips on validation error messages.
+ * @param {object} [options]
+ * @param {string} [options.placement='right']
+ * @throws MissingLibraryError
+ */
+QueryBuilder.define('bt-tooltip-errors', function(options) {
+ if (!$.fn.tooltip || !$.fn.tooltip.Constructor || !$.fn.tooltip.Constructor.prototype.fixTitle) {
+ Utils.error('MissingLibrary', 'Bootstrap Tooltip is required to use "bt-tooltip-errors" plugin. Get it here: http://getbootstrap.com');
+ }
+
+ var self = this;
+
+ // add BT Tooltip data
+ this.on('getRuleTemplate.filter getGroupTemplate.filter', function(h) {
+ var $h = $(h.value);
+ $h.find(QueryBuilder.selectors.error_container).attr('data-toggle', 'tooltip');
+ h.value = $h.prop('outerHTML');
+ });
+
+ // init/refresh tooltip when title changes
+ this.model.on('update', function(e, node, field) {
+ if (field == 'error' && self.settings.display_errors) {
+ node.$el.find(QueryBuilder.selectors.error_container).eq(0)
+ .tooltip(options)
+ .tooltip('hide')
+ .tooltip('fixTitle');
+ }
+ });
+}, {
+ placement: 'right'
+});
+
+
+/**
+ * @class ChangeFilters
+ * @memberof module:plugins
+ * @description Allows to change available filters after plugin initialization.
+ */
+
+QueryBuilder.extend(/** @lends module:plugins.ChangeFilters.prototype */ {
+ /**
+ * Change the filters of the builder
+ * @param {boolean} [deleteOrphans=false] - delete rules using old filters
+ * @param {QueryBuilder[]} filters
+ * @fires module:plugins.ChangeFilters.changer:setFilters
+ * @fires module:plugins.ChangeFilters.afterSetFilters
+ * @throws ChangeFilterError
+ */
+ setFilters: function(deleteOrphans, filters) {
+ var self = this;
+
+ if (filters === undefined) {
+ filters = deleteOrphans;
+ deleteOrphans = false;
+ }
+
+ filters = this.checkFilters(filters);
+
+ /**
+ * Modifies the filters before {@link module:plugins.ChangeFilters.setFilters} method
+ * @event changer:setFilters
+ * @memberof module:plugins.ChangeFilters
+ * @param {QueryBuilder.Filter[]} filters
+ * @returns {QueryBuilder.Filter[]}
+ */
+ filters = this.change('setFilters', filters);
+
+ var filtersIds = filters.map(function(filter) {
+ return filter.id;
+ });
+
+ // check for orphans
+ if (!deleteOrphans) {
+ (function checkOrphans(node) {
+ node.each(
+ function(rule) {
+ if (rule.filter && filtersIds.indexOf(rule.filter.id) === -1) {
+ Utils.error('ChangeFilter', 'A rule is using filter "{0}"', rule.filter.id);
+ }
+ },
+ checkOrphans
+ );
+ }(this.model.root));
+ }
+
+ // replace filters
+ this.filters = filters;
+
+ // apply on existing DOM
+ (function updateBuilder(node) {
+ node.each(true,
+ function(rule) {
+ if (rule.filter && filtersIds.indexOf(rule.filter.id) === -1) {
+ rule.drop();
+
+ self.trigger('rulesChanged');
+ }
+ else {
+ self.createRuleFilters(rule);
+
+ rule.$el.find(QueryBuilder.selectors.rule_filter).val(rule.filter ? rule.filter.id : '-1');
+ self.trigger('afterUpdateRuleFilter', rule);
+ }
+ },
+ updateBuilder
+ );
+ }(this.model.root));
+
+ // update plugins
+ if (this.settings.plugins) {
+ if (this.settings.plugins['unique-filter']) {
+ this.updateDisabledFilters();
+ }
+ if (this.settings.plugins['bt-selectpicker']) {
+ this.$el.find(QueryBuilder.selectors.rule_filter).selectpicker('render');
+ }
+ }
+
+ // reset the default_filter if does not exist anymore
+ if (this.settings.default_filter) {
+ try {
+ this.getFilterById(this.settings.default_filter);
+ }
+ catch (e) {
+ this.settings.default_filter = null;
+ }
+ }
+
+ /**
+ * After {@link module:plugins.ChangeFilters.setFilters} method
+ * @event afterSetFilters
+ * @memberof module:plugins.ChangeFilters
+ * @param {QueryBuilder.Filter[]} filters
+ */
+ this.trigger('afterSetFilters', filters);
+ },
+
+ /**
+ * Adds a new filter to the builder
+ * @param {QueryBuilder.Filter|Filter[]} newFilters
+ * @param {int|string} [position=#end] - index or '#start' or '#end'
+ * @fires module:plugins.ChangeFilters.changer:setFilters
+ * @fires module:plugins.ChangeFilters.afterSetFilters
+ * @throws ChangeFilterError
+ */
+ addFilter: function(newFilters, position) {
+ if (position === undefined || position == '#end') {
+ position = this.filters.length;
+ }
+ else if (position == '#start') {
+ position = 0;
+ }
+
+ if (!$.isArray(newFilters)) {
+ newFilters = [newFilters];
+ }
+
+ var filters = $.extend(true, [], this.filters);
+
+ // numeric position
+ if (parseInt(position) == position) {
+ Array.prototype.splice.apply(filters, [position, 0].concat(newFilters));
+ }
+ else {
+ // after filter by its id
+ if (this.filters.some(function(filter, index) {
+ if (filter.id == position) {
+ position = index + 1;
+ return true;
+ }
+ })
+ ) {
+ Array.prototype.splice.apply(filters, [position, 0].concat(newFilters));
+ }
+ // defaults to end of list
+ else {
+ Array.prototype.push.apply(filters, newFilters);
+ }
+ }
+
+ this.setFilters(filters);
+ },
+
+ /**
+ * Removes a filter from the builder
+ * @param {string|string[]} filterIds
+ * @param {boolean} [deleteOrphans=false] delete rules using old filters
+ * @fires module:plugins.ChangeFilters.changer:setFilters
+ * @fires module:plugins.ChangeFilters.afterSetFilters
+ * @throws ChangeFilterError
+ */
+ removeFilter: function(filterIds, deleteOrphans) {
+ var filters = $.extend(true, [], this.filters);
+ if (typeof filterIds === 'string') {
+ filterIds = [filterIds];
+ }
+
+ filters = filters.filter(function(filter) {
+ return filterIds.indexOf(filter.id) === -1;
+ });
+
+ this.setFilters(deleteOrphans, filters);
+ }
+});
+
+
+/**
+ * @class ChosenSelectpicker
+ * @memberof module:plugins
+ * @descriptioon Applies chosen-js Select on filters and operators combo-boxes.
+ * @param {object} [options] Supports all the options for chosen
+ * @throws MissingLibraryError
+ */
+QueryBuilder.define('chosen-selectpicker', function(options) {
+
+ if (!$.fn.chosen) {
+ Utils.error('MissingLibrary', 'chosen is required to use "chosen-selectpicker" plugin. Get it here: https://github.com/harvesthq/chosen');
+ }
+
+ if (this.settings.plugins['bt-selectpicker']) {
+ Utils.error('Conflict', 'bt-selectpicker is already selected as the dropdown plugin. Please remove chosen-selectpicker from the plugin list');
+ }
+
+ var Selectors = QueryBuilder.selectors;
+
+ // init selectpicker
+ this.on('afterCreateRuleFilters', function(e, rule) {
+ rule.$el.find(Selectors.rule_filter).removeClass('form-control').chosen(options);
+ });
+
+ this.on('afterCreateRuleOperators', function(e, rule) {
+ if (e.builder.getOperators(rule.filter).length > 1) {
+ rule.$el.find(Selectors.rule_operator).removeClass('form-control').chosen(options);
+ }
+ });
+
+ // update selectpicker on change
+ this.on('afterUpdateRuleFilter', function(e, rule) {
+ rule.$el.find(Selectors.rule_filter).trigger('chosen:updated');
+ });
+
+ this.on('afterUpdateRuleOperator', function(e, rule) {
+ rule.$el.find(Selectors.rule_operator).trigger('chosen:updated');
+ });
+
+ this.on('beforeDeleteRule', function(e, rule) {
+ rule.$el.find(Selectors.rule_filter).chosen('destroy');
+ rule.$el.find(Selectors.rule_operator).chosen('destroy');
+ });
+});
+
+
+/**
+ * @class FilterDescription
+ * @memberof module:plugins
+ * @description Provides three ways to display a description about a filter: inline, Bootsrap Popover or Bootbox.
+ * @param {object} [options]
+ * @param {string} [options.icon='glyphicon glyphicon-info-sign']
+ * @param {string} [options.mode='popover'] - inline, popover or bootbox
+ * @throws ConfigError
+ */
+QueryBuilder.define('filter-description', function(options) {
+ // INLINE
+ if (options.mode === 'inline') {
+ this.on('afterUpdateRuleFilter afterUpdateRuleOperator', function(e, rule) {
+ var $p = rule.$el.find('p.filter-description');
+ var description = e.builder.getFilterDescription(rule.filter, rule);
+
+ if (!description) {
+ $p.hide();
+ }
+ else {
+ if ($p.length === 0) {
+ $p = $('
');
+ $p.appendTo(rule.$el);
+ }
+ else {
+ $p.css('display', '');
+ }
+
+ $p.html(' ' + description);
+ }
+ });
+ }
+ // POPOVER
+ else if (options.mode === 'popover') {
+ if (!$.fn.popover || !$.fn.popover.Constructor || !$.fn.popover.Constructor.prototype.fixTitle) {
+ Utils.error('MissingLibrary', 'Bootstrap Popover is required to use "filter-description" plugin. Get it here: http://getbootstrap.com');
+ }
+
+ this.on('afterUpdateRuleFilter afterUpdateRuleOperator', function(e, rule) {
+ var $b = rule.$el.find('button.filter-description');
+ var description = e.builder.getFilterDescription(rule.filter, rule);
+
+ if (!description) {
+ $b.hide();
+
+ if ($b.data('bs.popover')) {
+ $b.popover('hide');
+ }
+ }
+ else {
+ if ($b.length === 0) {
+ $b = $(' ');
+ $b.prependTo(rule.$el.find(QueryBuilder.selectors.rule_actions));
+
+ $b.popover({
+ placement: 'left',
+ container: 'body',
+ html: true
+ });
+
+ $b.on('mouseout', function() {
+ $b.popover('hide');
+ });
+ }
+ else {
+ $b.css('display', '');
+ }
+
+ $b.data('bs.popover').options.content = description;
+
+ if ($b.attr('aria-describedby')) {
+ $b.popover('show');
+ }
+ }
+ });
+ }
+ // BOOTBOX
+ else if (options.mode === 'bootbox') {
+ if (!('bootbox' in window)) {
+ Utils.error('MissingLibrary', 'Bootbox is required to use "filter-description" plugin. Get it here: http://bootboxjs.com');
+ }
+
+ this.on('afterUpdateRuleFilter afterUpdateRuleOperator', function(e, rule) {
+ var $b = rule.$el.find('button.filter-description');
+ var description = e.builder.getFilterDescription(rule.filter, rule);
+
+ if (!description) {
+ $b.hide();
+ }
+ else {
+ if ($b.length === 0) {
+ $b = $(' ');
+ $b.prependTo(rule.$el.find(QueryBuilder.selectors.rule_actions));
+
+ $b.on('click', function() {
+ bootbox.alert($b.data('description'));
+ });
+ }
+ else {
+ $b.css('display', '');
+ }
+
+ $b.data('description', description);
+ }
+ });
+ }
+}, {
+ icon: 'glyphicon glyphicon-info-sign',
+ mode: 'popover'
+});
+
+QueryBuilder.extend(/** @lends module:plugins.FilterDescription.prototype */ {
+ /**
+ * Returns the description of a filter for a particular rule (if present)
+ * @param {object} filter
+ * @param {Rule} [rule]
+ * @returns {string}
+ * @private
+ */
+ getFilterDescription: function(filter, rule) {
+ if (!filter) {
+ return undefined;
+ }
+ else if (typeof filter.description == 'function') {
+ return filter.description.call(this, rule);
+ }
+ else {
+ return filter.description;
+ }
+ }
+});
+
+
+/**
+ * @class Invert
+ * @memberof module:plugins
+ * @description Allows to invert a rule operator, a group condition or the entire builder.
+ * @param {object} [options]
+ * @param {string} [options.icon='glyphicon glyphicon-random']
+ * @param {boolean} [options.recursive=true]
+ * @param {boolean} [options.invert_rules=true]
+ * @param {boolean} [options.display_rules_button=false]
+ * @param {boolean} [options.silent_fail=false]
+ */
+QueryBuilder.define('invert', function(options) {
+ var self = this;
+ var Selectors = QueryBuilder.selectors;
+
+ // Bind events
+ this.on('afterInit', function() {
+ self.$el.on('click.queryBuilder', '[data-invert=group]', function() {
+ var $group = $(this).closest(Selectors.group_container);
+ self.invert(self.getModel($group), options);
+ });
+
+ if (options.display_rules_button && options.invert_rules) {
+ self.$el.on('click.queryBuilder', '[data-invert=rule]', function() {
+ var $rule = $(this).closest(Selectors.rule_container);
+ self.invert(self.getModel($rule), options);
+ });
+ }
+ });
+
+ // Modify templates
+ if (!options.disable_template) {
+ this.on('getGroupTemplate.filter', function(h) {
+ var $h = $(h.value);
+ $h.find(Selectors.condition_container).after(
+ '' +
+ ' ' + self.translate('invert') +
+ ' '
+ );
+ h.value = $h.prop('outerHTML');
+ });
+
+ if (options.display_rules_button && options.invert_rules) {
+ this.on('getRuleTemplate.filter', function(h) {
+ var $h = $(h.value);
+ $h.find(Selectors.rule_actions).prepend(
+ '' +
+ ' ' + self.translate('invert') +
+ ' '
+ );
+ h.value = $h.prop('outerHTML');
+ });
+ }
+ }
+}, {
+ icon: 'glyphicon glyphicon-random',
+ recursive: true,
+ invert_rules: true,
+ display_rules_button: false,
+ silent_fail: false,
+ disable_template: false
+});
+
+QueryBuilder.defaults({
+ operatorOpposites: {
+ 'equal': 'not_equal',
+ 'not_equal': 'equal',
+ 'in': 'not_in',
+ 'not_in': 'in',
+ 'less': 'greater_or_equal',
+ 'less_or_equal': 'greater',
+ 'greater': 'less_or_equal',
+ 'greater_or_equal': 'less',
+ 'between': 'not_between',
+ 'not_between': 'between',
+ 'begins_with': 'not_begins_with',
+ 'not_begins_with': 'begins_with',
+ 'contains': 'not_contains',
+ 'not_contains': 'contains',
+ 'ends_with': 'not_ends_with',
+ 'not_ends_with': 'ends_with',
+ 'is_empty': 'is_not_empty',
+ 'is_not_empty': 'is_empty',
+ 'is_null': 'is_not_null',
+ 'is_not_null': 'is_null'
+ },
+
+ conditionOpposites: {
+ 'AND': 'OR',
+ 'OR': 'AND'
+ }
+});
+
+QueryBuilder.extend(/** @lends module:plugins.Invert.prototype */ {
+ /**
+ * Invert a Group, a Rule or the whole builder
+ * @param {Node} [node]
+ * @param {object} [options] {@link module:plugins.Invert}
+ * @fires module:plugins.Invert.afterInvert
+ * @throws InvertConditionError, InvertOperatorError
+ */
+ invert: function(node, options) {
+ if (!(node instanceof Node)) {
+ if (!this.model.root) return;
+ options = node;
+ node = this.model.root;
+ }
+
+ if (typeof options != 'object') options = {};
+ if (options.recursive === undefined) options.recursive = true;
+ if (options.invert_rules === undefined) options.invert_rules = true;
+ if (options.silent_fail === undefined) options.silent_fail = false;
+ if (options.trigger === undefined) options.trigger = true;
+
+ if (node instanceof Group) {
+ // invert group condition
+ if (this.settings.conditionOpposites[node.condition]) {
+ node.condition = this.settings.conditionOpposites[node.condition];
+ }
+ else if (!options.silent_fail) {
+ Utils.error('InvertCondition', 'Unknown inverse of condition "{0}"', node.condition);
+ }
+
+ // recursive call
+ if (options.recursive) {
+ var tempOpts = $.extend({}, options, { trigger: false });
+ node.each(function(rule) {
+ if (options.invert_rules) {
+ this.invert(rule, tempOpts);
+ }
+ }, function(group) {
+ this.invert(group, tempOpts);
+ }, this);
+ }
+ }
+ else if (node instanceof Rule) {
+ if (node.operator && !node.filter.no_invert) {
+ // invert rule operator
+ if (this.settings.operatorOpposites[node.operator.type]) {
+ var invert = this.settings.operatorOpposites[node.operator.type];
+ // check if the invert is "authorized"
+ if (!node.filter.operators || node.filter.operators.indexOf(invert) != -1) {
+ node.operator = this.getOperatorByType(invert);
+ }
+ }
+ else if (!options.silent_fail) {
+ Utils.error('InvertOperator', 'Unknown inverse of operator "{0}"', node.operator.type);
+ }
+ }
+ }
+
+ if (options.trigger) {
+ /**
+ * After {@link module:plugins.Invert.invert} method
+ * @event afterInvert
+ * @memberof module:plugins.Invert
+ * @param {Node} node - the main group or rule that has been modified
+ * @param {object} options
+ */
+ this.trigger('afterInvert', node, options);
+
+ this.trigger('rulesChanged');
+ }
+ }
+});
+
+
+/**
+ * @class MongoDbSupport
+ * @memberof module:plugins
+ * @description Allows to export rules as a MongoDB find object as well as populating the builder from a MongoDB object.
+ */
+
+QueryBuilder.defaults({
+ mongoOperators: {
+ // @formatter:off
+ equal: function(v) { return v[0]; },
+ not_equal: function(v) { return { '$ne': v[0] }; },
+ in: function(v) { return { '$in': v }; },
+ not_in: function(v) { return { '$nin': v }; },
+ less: function(v) { return { '$lt': v[0] }; },
+ less_or_equal: function(v) { return { '$lte': v[0] }; },
+ greater: function(v) { return { '$gt': v[0] }; },
+ greater_or_equal: function(v) { return { '$gte': v[0] }; },
+ between: function(v) { return { '$gte': v[0], '$lte': v[1] }; },
+ not_between: function(v) { return { '$lt': v[0], '$gt': v[1] }; },
+ begins_with: function(v) { return { '$regex': '^' + Utils.escapeRegExp(v[0]) }; },
+ not_begins_with: function(v) { return { '$regex': '^(?!' + Utils.escapeRegExp(v[0]) + ')' }; },
+ contains: function(v) { return { '$regex': Utils.escapeRegExp(v[0]) }; },
+ not_contains: function(v) { return { '$regex': '^((?!' + Utils.escapeRegExp(v[0]) + ').)*$', '$options': 's' }; },
+ ends_with: function(v) { return { '$regex': Utils.escapeRegExp(v[0]) + '$' }; },
+ not_ends_with: function(v) { return { '$regex': '(? 0) {
+ parts.push(parse(rule));
+ }
+ else {
+ var mdb = self.settings.mongoOperators[rule.operator];
+ var ope = self.getOperatorByType(rule.operator);
+
+ if (mdb === undefined) {
+ Utils.error('UndefinedMongoOperator', 'Unknown MongoDB operation for operator "{0}"', rule.operator);
+ }
+
+ if (ope.nb_inputs !== 0) {
+ if (!(rule.value instanceof Array)) {
+ rule.value = [rule.value];
+ }
+ }
+
+ /**
+ * Modifies the MongoDB field used by a rule
+ * @event changer:getMongoDBField
+ * @memberof module:plugins.MongoDbSupport
+ * @param {string} field
+ * @param {Rule} rule
+ * @returns {string}
+ */
+ var field = self.change('getMongoDBField', rule.field, rule);
+
+ var ruleExpression = {};
+ ruleExpression[field] = mdb.call(self, rule.value);
+
+ /**
+ * Modifies the MongoDB expression generated for a rul
+ * @event changer:ruleToMongo
+ * @memberof module:plugins.MongoDbSupport
+ * @param {object} expression
+ * @param {Rule} rule
+ * @param {*} value
+ * @param {function} valueWrapper - function that takes the value and adds the operator
+ * @returns {object}
+ */
+ parts.push(self.change('ruleToMongo', ruleExpression, rule, rule.value, mdb));
+ }
+ });
+
+ var groupExpression = {};
+ groupExpression['$' + group.condition.toLowerCase()] = parts;
+
+ /**
+ * Modifies the MongoDB expression generated for a group
+ * @event changer:groupToMongo
+ * @memberof module:plugins.MongoDbSupport
+ * @param {object} expression
+ * @param {Group} group
+ * @returns {object}
+ */
+ return self.change('groupToMongo', groupExpression, group);
+ }(data));
+ },
+
+ /**
+ * Converts a MongoDB query to rules
+ * @param {object} query
+ * @returns {object}
+ * @fires module:plugins.MongoDbSupport.changer:parseMongoNode
+ * @fires module:plugins.MongoDbSupport.changer:getMongoDBFieldID
+ * @fires module:plugins.MongoDbSupport.changer:mongoToRule
+ * @fires module:plugins.MongoDbSupport.changer:mongoToGroup
+ * @throws MongoParseError, UndefinedMongoConditionError, UndefinedMongoOperatorError
+ */
+ getRulesFromMongo: function(query) {
+ if (query === undefined || query === null) {
+ return null;
+ }
+
+ var self = this;
+
+ /**
+ * Custom parsing of a MongoDB expression, you can return a sub-part of the expression, or a well formed group or rule JSON
+ * @event changer:parseMongoNode
+ * @memberof module:plugins.MongoDbSupport
+ * @param {object} expression
+ * @returns {object} expression, rule or group
+ */
+ query = self.change('parseMongoNode', query);
+
+ // a plugin returned a group
+ if ('rules' in query && 'condition' in query) {
+ return query;
+ }
+
+ // a plugin returned a rule
+ if ('id' in query && 'operator' in query && 'value' in query) {
+ return {
+ condition: this.settings.default_condition,
+ rules: [query]
+ };
+ }
+
+ var key = self.getMongoCondition(query);
+ if (!key) {
+ Utils.error('MongoParse', 'Invalid MongoDB query format');
+ }
+
+ return (function parse(data, topKey) {
+ var rules = data[topKey];
+ var parts = [];
+
+ rules.forEach(function(data) {
+ // allow plugins to manually parse or handle special cases
+ data = self.change('parseMongoNode', data);
+
+ // a plugin returned a group
+ if ('rules' in data && 'condition' in data) {
+ parts.push(data);
+ return;
+ }
+
+ // a plugin returned a rule
+ if ('id' in data && 'operator' in data && 'value' in data) {
+ parts.push(data);
+ return;
+ }
+
+ var key = self.getMongoCondition(data);
+ if (key) {
+ parts.push(parse(data, key));
+ }
+ else {
+ var field = Object.keys(data)[0];
+ var value = data[field];
+
+ var operator = self.getMongoOperator(value);
+ if (operator === undefined) {
+ Utils.error('MongoParse', 'Invalid MongoDB query format');
+ }
+
+ var mdbrl = self.settings.mongoRuleOperators[operator];
+ if (mdbrl === undefined) {
+ Utils.error('UndefinedMongoOperator', 'JSON Rule operation unknown for operator "{0}"', operator);
+ }
+
+ var opVal = mdbrl.call(self, value);
+
+ var id = self.getMongoDBFieldID(field, value);
+
+ /**
+ * Modifies the rule generated from the MongoDB expression
+ * @event changer:mongoToRule
+ * @memberof module:plugins.MongoDbSupport
+ * @param {object} rule
+ * @param {object} expression
+ * @returns {object}
+ */
+ var rule = self.change('mongoToRule', {
+ id: id,
+ field: field,
+ operator: opVal.op,
+ value: opVal.val
+ }, data);
+
+ parts.push(rule);
+ }
+ });
+
+ /**
+ * Modifies the group generated from the MongoDB expression
+ * @event changer:mongoToGroup
+ * @memberof module:plugins.MongoDbSupport
+ * @param {object} group
+ * @param {object} expression
+ * @returns {object}
+ */
+ return self.change('mongoToGroup', {
+ condition: topKey.replace('$', '').toUpperCase(),
+ rules: parts
+ }, data);
+ }(query, key));
+ },
+
+ /**
+ * Sets rules a from MongoDB query
+ * @see module:plugins.MongoDbSupport.getRulesFromMongo
+ */
+ setRulesFromMongo: function(query) {
+ this.setRules(this.getRulesFromMongo(query));
+ },
+
+ /**
+ * Returns a filter identifier from the MongoDB field.
+ * Automatically use the only one filter with a matching field, fires a changer otherwise.
+ * @param {string} field
+ * @param {*} value
+ * @fires module:plugins.MongoDbSupport:changer:getMongoDBFieldID
+ * @returns {string}
+ * @private
+ */
+ getMongoDBFieldID: function(field, value) {
+ var matchingFilters = this.filters.filter(function(filter) {
+ return filter.field === field;
+ });
+
+ var id;
+ if (matchingFilters.length === 1) {
+ id = matchingFilters[0].id;
+ }
+ else {
+ /**
+ * Returns a filter identifier from the MongoDB field
+ * @event changer:getMongoDBFieldID
+ * @memberof module:plugins.MongoDbSupport
+ * @param {string} field
+ * @param {*} value
+ * @returns {string}
+ */
+ id = this.change('getMongoDBFieldID', field, value);
+ }
+
+ return id;
+ },
+
+ /**
+ * Finds which operator is used in a MongoDB sub-object
+ * @param {*} data
+ * @returns {string|undefined}
+ * @private
+ */
+ getMongoOperator: function(data) {
+ if (data !== null && typeof data === 'object') {
+ if (data.$gte !== undefined && data.$lte !== undefined) {
+ return 'between';
+ }
+ if (data.$lt !== undefined && data.$gt !== undefined) {
+ return 'not_between';
+ }
+
+ var knownKeys = Object.keys(data).filter(function(key) {
+ return !!this.settings.mongoRuleOperators[key];
+ }.bind(this));
+
+ if (knownKeys.length === 1) {
+ return knownKeys[0];
+ }
+ }
+ else {
+ return '$eq';
+ }
+ },
+
+
+ /**
+ * Returns the key corresponding to "$or" or "$and"
+ * @param {object} data
+ * @returns {string|undefined}
+ * @private
+ */
+ getMongoCondition: function(data) {
+ var keys = Object.keys(data);
+
+ for (var i = 0, l = keys.length; i < l; i++) {
+ if (keys[i].toLowerCase() === '$or' || keys[i].toLowerCase() === '$and') {
+ return keys[i];
+ }
+ }
+ }
+});
+
+
+/**
+ * @class NotGroup
+ * @memberof module:plugins
+ * @description Adds a "Not" checkbox in front of group conditions.
+ * @param {object} [options]
+ * @param {string} [options.icon_checked='glyphicon glyphicon-checked']
+ * @param {string} [options.icon_unchecked='glyphicon glyphicon-unchecked']
+ */
+QueryBuilder.define('not-group', function(options) {
+ var self = this;
+
+ // Bind events
+ this.on('afterInit', function() {
+ self.$el.on('click.queryBuilder', '[data-not=group]', function() {
+ var $group = $(this).closest(QueryBuilder.selectors.group_container);
+ var group = self.getModel($group);
+ group.not = !group.not;
+ });
+
+ self.model.on('update', function(e, node, field) {
+ if (node instanceof Group && field === 'not') {
+ self.updateGroupNot(node);
+ }
+ });
+ });
+
+ // Init "not" property
+ this.on('afterAddGroup', function(e, group) {
+ group.__.not = false;
+ });
+
+ // Modify templates
+ if (!options.disable_template) {
+ this.on('getGroupTemplate.filter', function(h) {
+ var $h = $(h.value);
+ $h.find(QueryBuilder.selectors.condition_container).prepend(
+ '' +
+ ' ' + self.translate('NOT') +
+ ' '
+ );
+ h.value = $h.prop('outerHTML');
+ });
+ }
+
+ // Export "not" to JSON
+ this.on('groupToJson.filter', function(e, group) {
+ e.value.not = group.not;
+ });
+
+ // Read "not" from JSON
+ this.on('jsonToGroup.filter', function(e, json) {
+ e.value.not = !!json.not;
+ });
+
+ // Export "not" to SQL
+ this.on('groupToSQL.filter', function(e, group) {
+ if (group.not) {
+ e.value = 'NOT ( ' + e.value + ' )';
+ }
+ });
+
+ // Parse "NOT" function from sqlparser
+ this.on('parseSQLNode.filter', function(e) {
+ if (e.value.name && e.value.name.toUpperCase() == 'NOT') {
+ e.value = e.value.arguments.value[0];
+
+ // if the there is no sub-group, create one
+ if (['AND', 'OR'].indexOf(e.value.operation.toUpperCase()) === -1) {
+ e.value = new SQLParser.nodes.Op(
+ self.settings.default_condition,
+ e.value,
+ null
+ );
+ }
+
+ e.value.not = true;
+ }
+ });
+
+ // Request to create sub-group if the "not" flag is set
+ this.on('sqlGroupsDistinct.filter', function(e, group, data, i) {
+ if (data.not && i > 0) {
+ e.value = true;
+ }
+ });
+
+ // Read "not" from parsed SQL
+ this.on('sqlToGroup.filter', function(e, data) {
+ e.value.not = !!data.not;
+ });
+
+ // Export "not" to Mongo
+ this.on('groupToMongo.filter', function(e, group) {
+ var key = '$' + group.condition.toLowerCase();
+ if (group.not && e.value[key]) {
+ e.value = { '$nor': [e.value] };
+ }
+ });
+
+ // Parse "$nor" operator from Mongo
+ this.on('parseMongoNode.filter', function(e) {
+ var keys = Object.keys(e.value);
+
+ if (keys[0] == '$nor') {
+ e.value = e.value[keys[0]][0];
+ e.value.not = true;
+ }
+ });
+
+ // Read "not" from parsed Mongo
+ this.on('mongoToGroup.filter', function(e, data) {
+ e.value.not = !!data.not;
+ });
+}, {
+ icon_unchecked: 'glyphicon glyphicon-unchecked',
+ icon_checked: 'glyphicon glyphicon-check',
+ disable_template: false
+});
+
+/**
+ * From {@link module:plugins.NotGroup}
+ * @name not
+ * @member {boolean}
+ * @memberof Group
+ * @instance
+ */
+Utils.defineModelProperties(Group, ['not']);
+
+QueryBuilder.selectors.group_not = QueryBuilder.selectors.group_header + ' [data-not=group]';
+
+QueryBuilder.extend(/** @lends module:plugins.NotGroup.prototype */ {
+ /**
+ * Performs actions when a group's not changes
+ * @param {Group} group
+ * @fires module:plugins.NotGroup.afterUpdateGroupNot
+ * @private
+ */
+ updateGroupNot: function(group) {
+ var options = this.plugins['not-group'];
+ group.$el.find('>' + QueryBuilder.selectors.group_not)
+ .toggleClass('active', group.not)
+ .find('i').attr('class', group.not ? options.icon_checked : options.icon_unchecked);
+
+ /**
+ * After the group's not flag has been modified
+ * @event afterUpdateGroupNot
+ * @memberof module:plugins.NotGroup
+ * @param {Group} group
+ */
+ this.trigger('afterUpdateGroupNot', group);
+
+ this.trigger('rulesChanged');
+ }
+});
+
+
+/**
+ * @class Sortable
+ * @memberof module:plugins
+ * @description Enables drag & drop sort of rules.
+ * @param {object} [options]
+ * @param {boolean} [options.inherit_no_drop=true]
+ * @param {boolean} [options.inherit_no_sortable=true]
+ * @param {string} [options.icon='glyphicon glyphicon-sort']
+ * @throws MissingLibraryError, ConfigError
+ */
+QueryBuilder.define('sortable', function(options) {
+ if (!('interact' in window)) {
+ Utils.error('MissingLibrary', 'interact.js is required to use "sortable" plugin. Get it here: http://interactjs.io');
+ }
+
+ if (options.default_no_sortable !== undefined) {
+ Utils.error(false, 'Config', 'Sortable plugin : "default_no_sortable" options is deprecated, use standard "default_rule_flags" and "default_group_flags" instead');
+ this.settings.default_rule_flags.no_sortable = this.settings.default_group_flags.no_sortable = options.default_no_sortable;
+ }
+
+ // recompute drop-zones during drag (when a rule is hidden)
+ interact.dynamicDrop(true);
+
+ // set move threshold to 10px
+ interact.pointerMoveTolerance(10);
+
+ var placeholder;
+ var ghost;
+ var src;
+ var moved;
+
+ // Init drag and drop
+ this.on('afterAddRule afterAddGroup', function(e, node) {
+ if (node == placeholder) {
+ return;
+ }
+
+ var self = e.builder;
+
+ // Inherit flags
+ if (options.inherit_no_sortable && node.parent && node.parent.flags.no_sortable) {
+ node.flags.no_sortable = true;
+ }
+ if (options.inherit_no_drop && node.parent && node.parent.flags.no_drop) {
+ node.flags.no_drop = true;
+ }
+
+ // Configure drag
+ if (!node.flags.no_sortable) {
+ interact(node.$el[0])
+ .draggable({
+ allowFrom: QueryBuilder.selectors.drag_handle,
+ onstart: function(event) {
+ moved = false;
+
+ // get model of dragged element
+ src = self.getModel(event.target);
+
+ // create ghost
+ ghost = src.$el.clone()
+ .appendTo(src.$el.parent())
+ .width(src.$el.outerWidth())
+ .addClass('dragging');
+
+ // create drop placeholder
+ var ph = $('
')
+ .height(src.$el.outerHeight());
+
+ placeholder = src.parent.addRule(ph, src.getPos());
+
+ // hide dragged element
+ src.$el.hide();
+ },
+ onmove: function(event) {
+ // make the ghost follow the cursor
+ ghost[0].style.top = event.clientY - 15 + 'px';
+ ghost[0].style.left = event.clientX - 15 + 'px';
+ },
+ onend: function(event) {
+ // starting from Interact 1.3.3, onend is called before ondrop
+ if (event.dropzone) {
+ moveSortableToTarget(src, $(event.relatedTarget), self);
+ moved = true;
+ }
+
+ // remove ghost
+ ghost.remove();
+ ghost = undefined;
+
+ // remove placeholder
+ placeholder.drop();
+ placeholder = undefined;
+
+ // show element
+ src.$el.css('display', '');
+
+ /**
+ * After a node has been moved with {@link module:plugins.Sortable}
+ * @event afterMove
+ * @memberof module:plugins.Sortable
+ * @param {Node} node
+ */
+ self.trigger('afterMove', src);
+
+ self.trigger('rulesChanged');
+ }
+ });
+ }
+
+ if (!node.flags.no_drop) {
+ // Configure drop on groups and rules
+ interact(node.$el[0])
+ .dropzone({
+ accept: QueryBuilder.selectors.rule_and_group_containers,
+ ondragenter: function(event) {
+ moveSortableToTarget(placeholder, $(event.target), self);
+ },
+ ondrop: function(event) {
+ if (!moved) {
+ moveSortableToTarget(src, $(event.target), self);
+ }
+ }
+ });
+
+ // Configure drop on group headers
+ if (node instanceof Group) {
+ interact(node.$el.find(QueryBuilder.selectors.group_header)[0])
+ .dropzone({
+ accept: QueryBuilder.selectors.rule_and_group_containers,
+ ondragenter: function(event) {
+ moveSortableToTarget(placeholder, $(event.target), self);
+ },
+ ondrop: function(event) {
+ if (!moved) {
+ moveSortableToTarget(src, $(event.target), self);
+ }
+ }
+ });
+ }
+ }
+ });
+
+ // Detach interactables
+ this.on('beforeDeleteRule beforeDeleteGroup', function(e, node) {
+ if (!e.isDefaultPrevented()) {
+ interact(node.$el[0]).unset();
+
+ if (node instanceof Group) {
+ interact(node.$el.find(QueryBuilder.selectors.group_header)[0]).unset();
+ }
+ }
+ });
+
+ // Remove drag handle from non-sortable items
+ this.on('afterApplyRuleFlags afterApplyGroupFlags', function(e, node) {
+ if (node.flags.no_sortable) {
+ node.$el.find('.drag-handle').remove();
+ }
+ });
+
+ // Modify templates
+ if (!options.disable_template) {
+ this.on('getGroupTemplate.filter', function(h, level) {
+ if (level > 1) {
+ var $h = $(h.value);
+ $h.find(QueryBuilder.selectors.condition_container).after('
');
+ h.value = $h.prop('outerHTML');
+ }
+ });
+
+ this.on('getRuleTemplate.filter', function(h) {
+ var $h = $(h.value);
+ $h.find(QueryBuilder.selectors.rule_header).after('
');
+ h.value = $h.prop('outerHTML');
+ });
+ }
+}, {
+ inherit_no_sortable: true,
+ inherit_no_drop: true,
+ icon: 'glyphicon glyphicon-sort',
+ disable_template: false
+});
+
+QueryBuilder.selectors.rule_and_group_containers = QueryBuilder.selectors.rule_container + ', ' + QueryBuilder.selectors.group_container;
+QueryBuilder.selectors.drag_handle = '.drag-handle';
+
+QueryBuilder.defaults({
+ default_rule_flags: {
+ no_sortable: false,
+ no_drop: false
+ },
+ default_group_flags: {
+ no_sortable: false,
+ no_drop: false
+ }
+});
+
+/**
+ * Moves an element (placeholder or actual object) depending on active target
+ * @memberof module:plugins.Sortable
+ * @param {Node} node
+ * @param {jQuery} target
+ * @param {QueryBuilder} [builder]
+ * @private
+ */
+function moveSortableToTarget(node, target, builder) {
+ var parent, method;
+ var Selectors = QueryBuilder.selectors;
+
+ // on rule
+ parent = target.closest(Selectors.rule_container);
+ if (parent.length) {
+ method = 'moveAfter';
+ }
+
+ // on group header
+ if (!method) {
+ parent = target.closest(Selectors.group_header);
+ if (parent.length) {
+ parent = target.closest(Selectors.group_container);
+ method = 'moveAtBegin';
+ }
+ }
+
+ // on group
+ if (!method) {
+ parent = target.closest(Selectors.group_container);
+ if (parent.length) {
+ method = 'moveAtEnd';
+ }
+ }
+
+ if (method) {
+ node[method](builder.getModel(parent));
+
+ // refresh radio value
+ if (builder && node instanceof Rule) {
+ builder.setRuleInputValue(node, node.value);
+ }
+ }
+}
+
+
+/**
+ * @class SqlSupport
+ * @memberof module:plugins
+ * @description Allows to export rules as a SQL WHERE statement as well as populating the builder from an SQL query.
+ * @param {object} [options]
+ * @param {boolean} [options.boolean_as_integer=true] - `true` to convert boolean values to integer in the SQL output
+ */
+QueryBuilder.define('sql-support', function(options) {
+
+}, {
+ boolean_as_integer: true
+});
+
+QueryBuilder.defaults({
+ // operators for internal -> SQL conversion
+ sqlOperators: {
+ equal: { op: '= ?' },
+ not_equal: { op: '!= ?' },
+ in: { op: 'IN(?)', sep: ', ' },
+ not_in: { op: 'NOT IN(?)', sep: ', ' },
+ less: { op: '< ?' },
+ less_or_equal: { op: '<= ?' },
+ greater: { op: '> ?' },
+ greater_or_equal: { op: '>= ?' },
+ between: { op: 'BETWEEN ?', sep: ' AND ' },
+ not_between: { op: 'NOT BETWEEN ?', sep: ' AND ' },
+ begins_with: { op: 'LIKE(?)', mod: '{0}%' },
+ not_begins_with: { op: 'NOT LIKE(?)', mod: '{0}%' },
+ contains: { op: 'LIKE(?)', mod: '%{0}%' },
+ not_contains: { op: 'NOT LIKE(?)', mod: '%{0}%' },
+ ends_with: { op: 'LIKE(?)', mod: '%{0}' },
+ not_ends_with: { op: 'NOT LIKE(?)', mod: '%{0}' },
+ is_empty: { op: '= \'\'' },
+ is_not_empty: { op: '!= \'\'' },
+ is_null: { op: 'IS NULL' },
+ is_not_null: { op: 'IS NOT NULL' }
+ },
+
+ // operators for SQL -> internal conversion
+ sqlRuleOperator: {
+ '=': function(v) {
+ return {
+ val: v,
+ op: v === '' ? 'is_empty' : 'equal'
+ };
+ },
+ '!=': function(v) {
+ return {
+ val: v,
+ op: v === '' ? 'is_not_empty' : 'not_equal'
+ };
+ },
+ 'LIKE': function(v) {
+ if (v.slice(0, 1) == '%' && v.slice(-1) == '%') {
+ return {
+ val: v.slice(1, -1),
+ op: 'contains'
+ };
+ }
+ else if (v.slice(0, 1) == '%') {
+ return {
+ val: v.slice(1),
+ op: 'ends_with'
+ };
+ }
+ else if (v.slice(-1) == '%') {
+ return {
+ val: v.slice(0, -1),
+ op: 'begins_with'
+ };
+ }
+ else {
+ Utils.error('SQLParse', 'Invalid value for LIKE operator "{0}"', v);
+ }
+ },
+ 'NOT LIKE': function(v) {
+ if (v.slice(0, 1) == '%' && v.slice(-1) == '%') {
+ return {
+ val: v.slice(1, -1),
+ op: 'not_contains'
+ };
+ }
+ else if (v.slice(0, 1) == '%') {
+ return {
+ val: v.slice(1),
+ op: 'not_ends_with'
+ };
+ }
+ else if (v.slice(-1) == '%') {
+ return {
+ val: v.slice(0, -1),
+ op: 'not_begins_with'
+ };
+ }
+ else {
+ Utils.error('SQLParse', 'Invalid value for NOT LIKE operator "{0}"', v);
+ }
+ },
+ 'IN': function(v) {
+ return { val: v, op: 'in' };
+ },
+ 'NOT IN': function(v) {
+ return { val: v, op: 'not_in' };
+ },
+ '<': function(v) {
+ return { val: v, op: 'less' };
+ },
+ '<=': function(v) {
+ return { val: v, op: 'less_or_equal' };
+ },
+ '>': function(v) {
+ return { val: v, op: 'greater' };
+ },
+ '>=': function(v) {
+ return { val: v, op: 'greater_or_equal' };
+ },
+ 'BETWEEN': function(v) {
+ return { val: v, op: 'between' };
+ },
+ 'NOT BETWEEN': function(v) {
+ return { val: v, op: 'not_between' };
+ },
+ 'IS': function(v) {
+ if (v !== null) {
+ Utils.error('SQLParse', 'Invalid value for IS operator');
+ }
+ return { val: null, op: 'is_null' };
+ },
+ 'IS NOT': function(v) {
+ if (v !== null) {
+ Utils.error('SQLParse', 'Invalid value for IS operator');
+ }
+ return { val: null, op: 'is_not_null' };
+ }
+ },
+
+ // statements for internal -> SQL conversion
+ sqlStatements: {
+ 'question_mark': function() {
+ var params = [];
+ return {
+ add: function(rule, value) {
+ params.push(value);
+ return '?';
+ },
+ run: function() {
+ return params;
+ }
+ };
+ },
+
+ 'numbered': function(char) {
+ if (!char || char.length > 1) char = '$';
+ var index = 0;
+ var params = [];
+ return {
+ add: function(rule, value) {
+ params.push(value);
+ index++;
+ return char + index;
+ },
+ run: function() {
+ return params;
+ }
+ };
+ },
+
+ 'named': function(char) {
+ if (!char || char.length > 1) char = ':';
+ var indexes = {};
+ var params = {};
+ return {
+ add: function(rule, value) {
+ if (!indexes[rule.field]) indexes[rule.field] = 1;
+ var key = rule.field + '_' + (indexes[rule.field]++);
+ params[key] = value;
+ return char + key;
+ },
+ run: function() {
+ return params;
+ }
+ };
+ }
+ },
+
+ // statements for SQL -> internal conversion
+ sqlRuleStatement: {
+ 'question_mark': function(values) {
+ var index = 0;
+ return {
+ parse: function(v) {
+ return v == '?' ? values[index++] : v;
+ },
+ esc: function(sql) {
+ return sql.replace(/\?/g, '\'?\'');
+ }
+ };
+ },
+
+ 'numbered': function(values, char) {
+ if (!char || char.length > 1) char = '$';
+ var regex1 = new RegExp('^\\' + char + '[0-9]+$');
+ var regex2 = new RegExp('\\' + char + '([0-9]+)', 'g');
+ return {
+ parse: function(v) {
+ return regex1.test(v) ? values[v.slice(1) - 1] : v;
+ },
+ esc: function(sql) {
+ return sql.replace(regex2, '\'' + (char == '$' ? '$$' : char) + '$1\'');
+ }
+ };
+ },
+
+ 'named': function(values, char) {
+ if (!char || char.length > 1) char = ':';
+ var regex1 = new RegExp('^\\' + char);
+ var regex2 = new RegExp('\\' + char + '(' + Object.keys(values).join('|') + ')', 'g');
+ return {
+ parse: function(v) {
+ return regex1.test(v) ? values[v.slice(1)] : v;
+ },
+ esc: function(sql) {
+ return sql.replace(regex2, '\'' + (char == '$' ? '$$' : char) + '$1\'');
+ }
+ };
+ }
+ }
+});
+
+/**
+ * @typedef {object} SqlQuery
+ * @memberof module:plugins.SqlSupport
+ * @property {string} sql
+ * @property {object} params
+ */
+
+QueryBuilder.extend(/** @lends module:plugins.SqlSupport.prototype */ {
+ /**
+ * Returns rules as a SQL query
+ * @param {boolean|string} [stmt] - use prepared statements: false, 'question_mark', 'numbered', 'numbered(@)', 'named', 'named(@)'
+ * @param {boolean} [nl=false] output with new lines
+ * @param {object} [data] - current rules by default
+ * @returns {module:plugins.SqlSupport.SqlQuery}
+ * @fires module:plugins.SqlSupport.changer:getSQLField
+ * @fires module:plugins.SqlSupport.changer:ruleToSQL
+ * @fires module:plugins.SqlSupport.changer:groupToSQL
+ * @throws UndefinedSQLConditionError, UndefinedSQLOperatorError
+ */
+ getSQL: function(stmt, nl, data) {
+ data = (data === undefined) ? this.getRules() : data;
+
+ if (!data) {
+ return null;
+ }
+
+ nl = !!nl ? '\n' : ' ';
+ var boolean_as_integer = this.getPluginOptions('sql-support', 'boolean_as_integer');
+
+ if (stmt === true) {
+ stmt = 'question_mark';
+ }
+ if (typeof stmt == 'string') {
+ var config = getStmtConfig(stmt);
+ stmt = this.settings.sqlStatements[config[1]](config[2]);
+ }
+
+ var self = this;
+
+ var sql = (function parse(group) {
+ if (!group.condition) {
+ group.condition = self.settings.default_condition;
+ }
+ if (['AND', 'OR'].indexOf(group.condition.toUpperCase()) === -1) {
+ Utils.error('UndefinedSQLCondition', 'Unable to build SQL query with condition "{0}"', group.condition);
+ }
+
+ if (!group.rules) {
+ return '';
+ }
+
+ var parts = [];
+
+ group.rules.forEach(function(rule) {
+ if (rule.rules && rule.rules.length > 0) {
+ parts.push('(' + nl + parse(rule) + nl + ')' + nl);
+ }
+ else {
+ var sql = self.settings.sqlOperators[rule.operator];
+ var ope = self.getOperatorByType(rule.operator);
+ var value = '';
+
+ if (sql === undefined) {
+ Utils.error('UndefinedSQLOperator', 'Unknown SQL operation for operator "{0}"', rule.operator);
+ }
+
+ if (ope.nb_inputs !== 0) {
+ if (!(rule.value instanceof Array)) {
+ rule.value = [rule.value];
+ }
+
+ rule.value.forEach(function(v, i) {
+ if (i > 0) {
+ value += sql.sep;
+ }
+
+ if (rule.type == 'boolean' && boolean_as_integer) {
+ v = v ? 1 : 0;
+ }
+ else if (!stmt && rule.type !== 'integer' && rule.type !== 'double' && rule.type !== 'boolean') {
+ v = Utils.escapeString(v);
+ }
+
+ if (sql.mod) {
+ v = Utils.fmt(sql.mod, v);
+ }
+
+ if (stmt) {
+ value += stmt.add(rule, v);
+ }
+ else {
+ if (typeof v == 'string') {
+ v = '\'' + v + '\'';
+ }
+
+ value += v;
+ }
+ });
+ }
+
+ var sqlFn = function(v) {
+ return sql.op.replace('?', function() {
+ return v;
+ });
+ };
+
+ /**
+ * Modifies the SQL field used by a rule
+ * @event changer:getSQLField
+ * @memberof module:plugins.SqlSupport
+ * @param {string} field
+ * @param {Rule} rule
+ * @returns {string}
+ */
+ var field = self.change('getSQLField', rule.field, rule);
+
+ var ruleExpression = field + ' ' + sqlFn(value);
+
+ /**
+ * Modifies the SQL generated for a rule
+ * @event changer:ruleToSQL
+ * @memberof module:plugins.SqlSupport
+ * @param {string} expression
+ * @param {Rule} rule
+ * @param {*} value
+ * @param {function} valueWrapper - function that takes the value and adds the operator
+ * @returns {string}
+ */
+ parts.push(self.change('ruleToSQL', ruleExpression, rule, value, sqlFn));
+ }
+ });
+
+ var groupExpression = parts.join(' ' + group.condition + nl);
+
+ /**
+ * Modifies the SQL generated for a group
+ * @event changer:groupToSQL
+ * @memberof module:plugins.SqlSupport
+ * @param {string} expression
+ * @param {Group} group
+ * @returns {string}
+ */
+ return self.change('groupToSQL', groupExpression, group);
+ }(data));
+
+ if (stmt) {
+ return {
+ sql: sql,
+ params: stmt.run()
+ };
+ }
+ else {
+ return {
+ sql: sql
+ };
+ }
+ },
+
+ /**
+ * Convert a SQL query to rules
+ * @param {string|module:plugins.SqlSupport.SqlQuery} query
+ * @param {boolean|string} stmt
+ * @returns {object}
+ * @fires module:plugins.SqlSupport.changer:parseSQLNode
+ * @fires module:plugins.SqlSupport.changer:getSQLFieldID
+ * @fires module:plugins.SqlSupport.changer:sqlToRule
+ * @fires module:plugins.SqlSupport.changer:sqlToGroup
+ * @throws MissingLibraryError, SQLParseError, UndefinedSQLOperatorError
+ */
+ getRulesFromSQL: function(query, stmt) {
+ if (!('SQLParser' in window)) {
+ Utils.error('MissingLibrary', 'SQLParser is required to parse SQL queries. Get it here https://github.com/mistic100/sql-parser');
+ }
+
+ var self = this;
+
+ if (typeof query == 'string') {
+ query = { sql: query };
+ }
+
+ if (stmt === true) stmt = 'question_mark';
+ if (typeof stmt == 'string') {
+ var config = getStmtConfig(stmt);
+ stmt = this.settings.sqlRuleStatement[config[1]](query.params, config[2]);
+ }
+
+ if (stmt) {
+ query.sql = stmt.esc(query.sql);
+ }
+
+ if (query.sql.toUpperCase().indexOf('SELECT') !== 0) {
+ query.sql = 'SELECT * FROM table WHERE ' + query.sql;
+ }
+
+ var parsed = SQLParser.parse(query.sql);
+
+ if (!parsed.where) {
+ Utils.error('SQLParse', 'No WHERE clause found');
+ }
+
+ /**
+ * Custom parsing of an AST node generated by SQLParser, you can return a sub-part of the tree, or a well formed group or rule JSON
+ * @event changer:parseSQLNode
+ * @memberof module:plugins.SqlSupport
+ * @param {object} AST node
+ * @returns {object} tree, rule or group
+ */
+ var data = self.change('parseSQLNode', parsed.where.conditions);
+
+ // a plugin returned a group
+ if ('rules' in data && 'condition' in data) {
+ return data;
+ }
+
+ // a plugin returned a rule
+ if ('id' in data && 'operator' in data && 'value' in data) {
+ return {
+ condition: this.settings.default_condition,
+ rules: [data]
+ };
+ }
+
+ // create root group
+ var out = self.change('sqlToGroup', {
+ condition: this.settings.default_condition,
+ rules: []
+ }, data);
+
+ // keep track of current group
+ var curr = out;
+
+ (function flatten(data, i) {
+ if (data === null) {
+ return;
+ }
+
+ // allow plugins to manually parse or handle special cases
+ data = self.change('parseSQLNode', data);
+
+ // a plugin returned a group
+ if ('rules' in data && 'condition' in data) {
+ curr.rules.push(data);
+ return;
+ }
+
+ // a plugin returned a rule
+ if ('id' in data && 'operator' in data && 'value' in data) {
+ curr.rules.push(data);
+ return;
+ }
+
+ // data must be a SQL parser node
+ if (!('left' in data) || !('right' in data) || !('operation' in data)) {
+ Utils.error('SQLParse', 'Unable to parse WHERE clause');
+ }
+
+ // it's a node
+ if (['AND', 'OR'].indexOf(data.operation.toUpperCase()) !== -1) {
+ // create a sub-group if the condition is not the same and it's not the first level
+
+ /**
+ * Given an existing group and an AST node, determines if a sub-group must be created
+ * @event changer:sqlGroupsDistinct
+ * @memberof module:plugins.SqlSupport
+ * @param {boolean} create - true by default if the group condition is different
+ * @param {object} group
+ * @param {object} AST
+ * @param {int} current group level
+ * @returns {boolean}
+ */
+ var createGroup = self.change('sqlGroupsDistinct', i > 0 && curr.condition != data.operation.toUpperCase(), curr, data, i);
+
+ if (createGroup) {
+ /**
+ * Modifies the group generated from the SQL expression (this is called before the group is filled with rules)
+ * @event changer:sqlToGroup
+ * @memberof module:plugins.SqlSupport
+ * @param {object} group
+ * @param {object} AST
+ * @returns {object}
+ */
+ var group = self.change('sqlToGroup', {
+ condition: self.settings.default_condition,
+ rules: []
+ }, data);
+
+ curr.rules.push(group);
+ curr = group;
+ }
+
+ curr.condition = data.operation.toUpperCase();
+ i++;
+
+ // some magic !
+ var next = curr;
+ flatten(data.left, i);
+
+ curr = next;
+ flatten(data.right, i);
+ }
+ // it's a leaf
+ else {
+ if ($.isPlainObject(data.right.value)) {
+ Utils.error('SQLParse', 'Value format not supported for {0}.', data.left.value);
+ }
+
+ // convert array
+ var value;
+ if ($.isArray(data.right.value)) {
+ value = data.right.value.map(function(v) {
+ return v.value;
+ });
+ }
+ else {
+ value = data.right.value;
+ }
+
+ // get actual values
+ if (stmt) {
+ if ($.isArray(value)) {
+ value = value.map(stmt.parse);
+ }
+ else {
+ value = stmt.parse(value);
+ }
+ }
+
+ // convert operator
+ var operator = data.operation.toUpperCase();
+ if (operator == '<>') {
+ operator = '!=';
+ }
+
+ var sqlrl = self.settings.sqlRuleOperator[operator];
+ if (sqlrl === undefined) {
+ Utils.error('UndefinedSQLOperator', 'Invalid SQL operation "{0}".', data.operation);
+ }
+
+ var opVal = sqlrl.call(this, value, data.operation);
+
+ // find field name
+ var field;
+ if ('values' in data.left) {
+ field = data.left.values.join('.');
+ }
+ else if ('value' in data.left) {
+ field = data.left.value;
+ }
+ else {
+ Utils.error('SQLParse', 'Cannot find field name in {0}', JSON.stringify(data.left));
+ }
+
+ var id = self.getSQLFieldID(field, value);
+
+ /**
+ * Modifies the rule generated from the SQL expression
+ * @event changer:sqlToRule
+ * @memberof module:plugins.SqlSupport
+ * @param {object} rule
+ * @param {object} AST
+ * @returns {object}
+ */
+ var rule = self.change('sqlToRule', {
+ id: id,
+ field: field,
+ operator: opVal.op,
+ value: opVal.val
+ }, data);
+
+ curr.rules.push(rule);
+ }
+ }(data, 0));
+
+ return out;
+ },
+
+ /**
+ * Sets the builder's rules from a SQL query
+ * @see module:plugins.SqlSupport.getRulesFromSQL
+ */
+ setRulesFromSQL: function(query, stmt) {
+ this.setRules(this.getRulesFromSQL(query, stmt));
+ },
+
+ /**
+ * Returns a filter identifier from the SQL field.
+ * Automatically use the only one filter with a matching field, fires a changer otherwise.
+ * @param {string} field
+ * @param {*} value
+ * @fires module:plugins.SqlSupport:changer:getSQLFieldID
+ * @returns {string}
+ * @private
+ */
+ getSQLFieldID: function(field, value) {
+ var matchingFilters = this.filters.filter(function(filter) {
+ return filter.field.toLowerCase() === field.toLowerCase();
+ });
+
+ var id;
+ if (matchingFilters.length === 1) {
+ id = matchingFilters[0].id;
+ }
+ else {
+ /**
+ * Returns a filter identifier from the SQL field
+ * @event changer:getSQLFieldID
+ * @memberof module:plugins.SqlSupport
+ * @param {string} field
+ * @param {*} value
+ * @returns {string}
+ */
+ id = this.change('getSQLFieldID', field, value);
+ }
+
+ return id;
+ }
+});
+
+/**
+ * Parses the statement configuration
+ * @memberof module:plugins.SqlSupport
+ * @param {string} stmt
+ * @returns {Array} null, mode, option
+ * @private
+ */
+function getStmtConfig(stmt) {
+ var config = stmt.match(/(question_mark|numbered|named)(?:\((.)\))?/);
+ if (!config) config = [null, 'question_mark', undefined];
+ return config;
+}
+
+
+/**
+ * @class UniqueFilter
+ * @memberof module:plugins
+ * @description Allows to define some filters as "unique": ie which can be used for only one rule, globally or in the same group.
+ */
+QueryBuilder.define('unique-filter', function() {
+ this.status.used_filters = {};
+
+ this.on('afterUpdateRuleFilter', this.updateDisabledFilters);
+ this.on('afterDeleteRule', this.updateDisabledFilters);
+ this.on('afterCreateRuleFilters', this.applyDisabledFilters);
+ this.on('afterReset', this.clearDisabledFilters);
+ this.on('afterClear', this.clearDisabledFilters);
+
+ // Ensure that the default filter is not already used if unique
+ this.on('getDefaultFilter.filter', function(e, model) {
+ var self = e.builder;
+
+ self.updateDisabledFilters();
+
+ if (e.value.id in self.status.used_filters) {
+ var found = self.filters.some(function(filter) {
+ if (!(filter.id in self.status.used_filters) || self.status.used_filters[filter.id].length > 0 && self.status.used_filters[filter.id].indexOf(model.parent) === -1) {
+ e.value = filter;
+ return true;
+ }
+ });
+
+ if (!found) {
+ Utils.error(false, 'UniqueFilter', 'No more non-unique filters available');
+ e.value = undefined;
+ }
+ }
+ });
+});
+
+QueryBuilder.extend(/** @lends module:plugins.UniqueFilter.prototype */ {
+ /**
+ * Updates the list of used filters
+ * @param {$.Event} [e]
+ * @private
+ */
+ updateDisabledFilters: function(e) {
+ var self = e ? e.builder : this;
+
+ self.status.used_filters = {};
+
+ if (!self.model) {
+ return;
+ }
+
+ // get used filters
+ (function walk(group) {
+ group.each(function(rule) {
+ if (rule.filter && rule.filter.unique) {
+ if (!self.status.used_filters[rule.filter.id]) {
+ self.status.used_filters[rule.filter.id] = [];
+ }
+ if (rule.filter.unique == 'group') {
+ self.status.used_filters[rule.filter.id].push(rule.parent);
+ }
+ }
+ }, function(group) {
+ walk(group);
+ });
+ }(self.model.root));
+
+ self.applyDisabledFilters(e);
+ },
+
+ /**
+ * Clear the list of used filters
+ * @param {$.Event} [e]
+ * @private
+ */
+ clearDisabledFilters: function(e) {
+ var self = e ? e.builder : this;
+
+ self.status.used_filters = {};
+
+ self.applyDisabledFilters(e);
+ },
+
+ /**
+ * Disabled filters depending on the list of used ones
+ * @param {$.Event} [e]
+ * @private
+ */
+ applyDisabledFilters: function(e) {
+ var self = e ? e.builder : this;
+
+ // re-enable everything
+ self.$el.find(QueryBuilder.selectors.filter_container + ' option').prop('disabled', false);
+
+ // disable some
+ $.each(self.status.used_filters, function(filterId, groups) {
+ if (groups.length === 0) {
+ self.$el.find(QueryBuilder.selectors.filter_container + ' option[value="' + filterId + '"]:not(:selected)').prop('disabled', true);
+ }
+ else {
+ groups.forEach(function(group) {
+ group.each(function(rule) {
+ rule.$el.find(QueryBuilder.selectors.filter_container + ' option[value="' + filterId + '"]:not(:selected)').prop('disabled', true);
+ });
+ });
+ }
+ });
+
+ // update Selectpicker
+ if (self.settings.plugins && self.settings.plugins['bt-selectpicker']) {
+ self.$el.find(QueryBuilder.selectors.rule_filter).selectpicker('render');
+ }
+ }
+});
+
+
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: English (en)
+ * Author: Damien "Mistic" Sorel, http://www.strangeplanet.fr
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+QueryBuilder.regional['en'] = {
+ "__locale": "English (en)",
+ "__author": "Damien \"Mistic\" Sorel, http://www.strangeplanet.fr",
+ "add_rule": "Add rule",
+ "add_group": "Add group",
+ "delete_rule": "Delete",
+ "delete_group": "Delete",
+ "conditions": {
+ "AND": "AND",
+ "OR": "OR"
+ },
+ "operators": {
+ "equal": "equal",
+ "not_equal": "not equal",
+ "in": "in",
+ "not_in": "not in",
+ "less": "less",
+ "less_or_equal": "less or equal",
+ "greater": "greater",
+ "greater_or_equal": "greater or equal",
+ "between": "between",
+ "not_between": "not between",
+ "begins_with": "begins with",
+ "not_begins_with": "doesn't begin with",
+ "contains": "contains",
+ "not_contains": "doesn't contain",
+ "ends_with": "ends with",
+ "not_ends_with": "doesn't end with",
+ "is_empty": "is empty",
+ "is_not_empty": "is not empty",
+ "is_null": "is null",
+ "is_not_null": "is not null"
+ },
+ "errors": {
+ "no_filter": "No filter selected",
+ "empty_group": "The group is empty",
+ "radio_empty": "No value selected",
+ "checkbox_empty": "No value selected",
+ "select_empty": "No value selected",
+ "string_empty": "Empty value",
+ "string_exceed_min_length": "Must contain at least {0} characters",
+ "string_exceed_max_length": "Must not contain more than {0} characters",
+ "string_invalid_format": "Invalid format ({0})",
+ "number_nan": "Not a number",
+ "number_not_integer": "Not an integer",
+ "number_not_double": "Not a real number",
+ "number_exceed_min": "Must be greater than {0}",
+ "number_exceed_max": "Must be lower than {0}",
+ "number_wrong_step": "Must be a multiple of {0}",
+ "number_between_invalid": "Invalid values, {0} is greater than {1}",
+ "datetime_empty": "Empty value",
+ "datetime_invalid": "Invalid date format ({0})",
+ "datetime_exceed_min": "Must be after {0}",
+ "datetime_exceed_max": "Must be before {0}",
+ "datetime_between_invalid": "Invalid values, {0} is greater than {1}",
+ "boolean_not_valid": "Not a boolean",
+ "operator_not_multiple": "Operator \"{1}\" cannot accept multiple values"
+ },
+ "invert": "Invert",
+ "NOT": "NOT"
+};
+
+QueryBuilder.defaults({ lang_code: 'en' });
+return QueryBuilder;
+
+}));
diff --git a/dist/js/query-builder.min.js b/dist/js/query-builder.min.js
new file mode 100644
index 00000000..1669fcec
--- /dev/null
+++ b/dist/js/query-builder.min.js
@@ -0,0 +1,8 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Copyright 2014-2020 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+!function(e,t){"function"==typeof define&&define.amd?define(["jquery","dot/doT","jquery-extendext"],t):"object"==typeof module&&module.exports?module.exports=t(require("jquery"),require("dot/doT"),require("jquery-extendext")):t(e.jQuery,e.doT)}(this,function($,r){"use strict";var c=function(e,t){(e[0].queryBuilder=this).$el=e,this.settings=$.extendext(!0,"replace",{},c.DEFAULTS,t),this.model=new i,this.status={id:null,generated_id:!1,group_id:0,rule_id:0,has_optgroup:!1,has_operator_optgroup:!1},this.filters=this.settings.filters,this.icons=this.settings.icons,this.operators=this.settings.operators,this.templates=this.settings.templates,this.plugins=this.settings.plugins,this.lang=null,void 0===c.regional.en&&h.error("Config",'"i18n/en.js" not loaded.'),this.lang=$.extendext(!0,"replace",{},c.regional.en,c.regional[this.settings.lang_code],this.settings.lang),!1===this.settings.allow_groups?this.settings.allow_groups=0:!0===this.settings.allow_groups&&(this.settings.allow_groups=-1),Object.keys(this.templates).forEach(function(e){this.templates[e]||(this.templates[e]=c.templates[e]),"string"==typeof this.templates[e]&&(this.templates[e]=r.template(this.templates[e]))},this),this.$el.attr("id")||(this.$el.attr("id","qb_"+Math.floor(99999*Math.random())),this.status.generated_id=!0),this.status.id=this.$el.attr("id"),this.$el.addClass("query-builder form-inline"),this.filters=this.checkFilters(this.filters),this.operators=this.checkOperators(this.operators),this.bindEvents(),this.initPlugins()};$.extend(c.prototype,{trigger:function(e){var t=new $.Event(this._tojQueryEvent(e),{builder:this});return this.$el.triggerHandler(t,Array.prototype.slice.call(arguments,1)),t},change:function(e,t){var r=new $.Event(this._tojQueryEvent(e,!0),{builder:this,value:t});return this.$el.triggerHandler(r,Array.prototype.slice.call(arguments,2)),r.value},on:function(e,t){return this.$el.on(this._tojQueryEvent(e),t),this},off:function(e,t){return this.$el.off(this._tojQueryEvent(e),t),this},once:function(e,t){return this.$el.one(this._tojQueryEvent(e),t),this},_tojQueryEvent:function(e,t){return e.split(" ").map(function(e){return e+".queryBuilder"+(t?".filter":"")}).join(" ")}}),c.types={string:"string",integer:"number",double:"number",date:"datetime",time:"datetime",datetime:"datetime",boolean:"boolean"},c.inputs=["text","number","textarea","radio","checkbox","select"],c.modifiable_options=["display_errors","allow_groups","allow_empty","default_condition","default_filter"],c.selectors={group_container:".rules-group-container",rule_container:".rule-container",filter_container:".rule-filter-container",operator_container:".rule-operator-container",value_container:".rule-value-container",error_container:".error-container",condition_container:".rules-group-header .group-conditions",rule_header:".rule-header",group_header:".rules-group-header",group_actions:".group-actions",rule_actions:".rule-actions",rules_list:".rules-group-body>.rules-list",group_condition:".rules-group-header [name$=_cond]",rule_filter:".rule-filter-container [name$=_filter]",rule_operator:".rule-operator-container [name$=_operator]",rule_value:".rule-value-container [name*=_value_]",add_rule:"[data-add=rule]",delete_rule:"[data-delete=rule]",add_group:"[data-add=group]",delete_group:"[data-delete=group]"},c.templates={},c.regional={},c.OPERATORS={equal:{type:"equal",nb_inputs:1,multiple:!1,apply_to:["string","number","datetime","boolean"]},not_equal:{type:"not_equal",nb_inputs:1,multiple:!1,apply_to:["string","number","datetime","boolean"]},in:{type:"in",nb_inputs:1,multiple:!0,apply_to:["string","number","datetime"]},not_in:{type:"not_in",nb_inputs:1,multiple:!0,apply_to:["string","number","datetime"]},less:{type:"less",nb_inputs:1,multiple:!1,apply_to:["number","datetime"]},less_or_equal:{type:"less_or_equal",nb_inputs:1,multiple:!1,apply_to:["number","datetime"]},greater:{type:"greater",nb_inputs:1,multiple:!1,apply_to:["number","datetime"]},greater_or_equal:{type:"greater_or_equal",nb_inputs:1,multiple:!1,apply_to:["number","datetime"]},between:{type:"between",nb_inputs:2,multiple:!1,apply_to:["number","datetime"]},not_between:{type:"not_between",nb_inputs:2,multiple:!1,apply_to:["number","datetime"]},begins_with:{type:"begins_with",nb_inputs:1,multiple:!1,apply_to:["string"]},not_begins_with:{type:"not_begins_with",nb_inputs:1,multiple:!1,apply_to:["string"]},contains:{type:"contains",nb_inputs:1,multiple:!1,apply_to:["string"]},not_contains:{type:"not_contains",nb_inputs:1,multiple:!1,apply_to:["string"]},ends_with:{type:"ends_with",nb_inputs:1,multiple:!1,apply_to:["string"]},not_ends_with:{type:"not_ends_with",nb_inputs:1,multiple:!1,apply_to:["string"]},is_empty:{type:"is_empty",nb_inputs:0,multiple:!1,apply_to:["string"]},is_not_empty:{type:"is_not_empty",nb_inputs:0,multiple:!1,apply_to:["string"]},is_null:{type:"is_null",nb_inputs:0,multiple:!1,apply_to:["string","number","datetime","boolean"]},is_not_null:{type:"is_not_null",nb_inputs:0,multiple:!1,apply_to:["string","number","datetime","boolean"]}},c.DEFAULTS={filters:[],plugins:[],sort_filters:!1,display_errors:!0,allow_groups:-1,allow_empty:!1,conditions:["AND","OR"],default_condition:"AND",inputs_separator:" , ",select_placeholder:"------",display_empty_filter:!0,default_filter:null,optgroups:{},default_rule_flags:{filter_readonly:!1,operator_readonly:!1,value_readonly:!1,no_delete:!1},default_group_flags:{condition_readonly:!1,no_add_rule:!1,no_add_group:!1,no_delete:!1},templates:{group:null,rule:null,filterSelect:null,operatorSelect:null,ruleValueSelect:null},lang_code:"en",lang:{},operators:["equal","not_equal","in","not_in","less","less_or_equal","greater","greater_or_equal","between","not_between","begins_with","not_begins_with","contains","not_contains","ends_with","not_ends_with","is_empty","is_not_empty","is_null","is_not_null"],icons:{add_group:"fas fa-plus-circle",add_rule:"fas fa-plus",remove_group:"fas fa-times",remove_rule:"fas fa-times",error:"fas fa-exclamation-triangle"}},c.plugins={},c.defaults=function(e){if("object"!=typeof e)return"string"==typeof e?"object"==typeof c.DEFAULTS[e]?$.extend(!0,{},c.DEFAULTS[e]):c.DEFAULTS[e]:$.extend(!0,{},c.DEFAULTS);$.extendext(!0,"replace",c.DEFAULTS,e)},c.define=function(e,t,r){c.plugins[e]={fct:t,def:r||{}}},c.extend=function(e){$.extend(c.prototype,e)},c.prototype.initPlugins=function(){if(this.plugins){if($.isArray(this.plugins)){var t={};this.plugins.forEach(function(e){t[e]=null}),this.plugins=t}Object.keys(this.plugins).forEach(function(e){e in c.plugins?(this.plugins[e]=$.extend(!0,{},c.plugins[e].def,this.plugins[e]||{}),c.plugins[e].fct.call(this,this.plugins[e])):h.error("Config",'Unable to find plugin "{0}"',e)},this)}},c.prototype.getPluginOptions=function(e,t){var r;if(this.plugins&&this.plugins[e]?r=this.plugins[e]:c.plugins[e]&&(r=c.plugins[e].def),r)return t?r[t]:r;h.error("Config",'Unable to find plugin "{0}"',e)},c.prototype.init=function(e){this.trigger("afterInit"),e?(this.setRules(e),delete this.settings.rules):this.setRoot(!0)},c.prototype.checkFilters=function(e){var t=[];if(e&&0!==e.length||h.error("Config","Missing filters list"),e.forEach(function(i,e){switch(i.id||h.error("Config","Missing filter {0} id",e),-1!=t.indexOf(i.id)&&h.error("Config",'Filter "{0}" already defined',i.id),t.push(i.id),i.type?c.types[i.type]||h.error("Config",'Invalid type "{0}"',i.type):i.type="string",i.input?"function"!=typeof i.input&&-1==c.inputs.indexOf(i.input)&&h.error("Config",'Invalid input "{0}"',i.input):i.input="number"===c.types[i.type]?"number":"text",i.operators&&i.operators.forEach(function(e){"string"!=typeof e&&h.error("Config","Filter operators must be global operators types (string)")}),i.field||(i.field=i.id),i.label||(i.label=i.field),i.optgroup?(this.status.has_optgroup=!0,this.settings.optgroups[i.optgroup]||(this.settings.optgroups[i.optgroup]=i.optgroup)):i.optgroup=null,i.input){case"radio":case"checkbox":(!i.values||i.values.length<1)&&h.error("Config",'Missing filter "{0}" values',i.id);break;case"select":var o=[];i.has_optgroup=!1,h.iterateOptions(i.values,function(e,t,r){o.push({value:e,label:t,optgroup:r||null}),r&&(i.has_optgroup=!0,this.settings.optgroups[r]||(this.settings.optgroups[r]=r))}.bind(this)),i.has_optgroup?i.values=h.groupSort(o,"optgroup"):i.values=o,i.placeholder&&(void 0===i.placeholder_value&&(i.placeholder_value=-1),i.values.forEach(function(e){e.value==i.placeholder_value&&h.error("Config",'Placeholder of filter "{0}" overlaps with one of its values',i.id)}))}},this),this.settings.sort_filters)if("function"==typeof this.settings.sort_filters)e.sort(this.settings.sort_filters);else{var r=this;e.sort(function(e,t){return r.translate(e.label).localeCompare(r.translate(t.label))})}return this.status.has_optgroup&&(e=h.groupSort(e,"optgroup")),e},c.prototype.checkOperators=function(r){var i=[];return r.forEach(function(e,t){"string"==typeof e?(c.OPERATORS[e]||h.error("Config",'Unknown operator "{0}"',e),r[t]=e=$.extendext(!0,"replace",{},c.OPERATORS[e])):(e.type||h.error("Config",'Missing "type" for operator {0}',t),c.OPERATORS[e.type]&&(r[t]=e=$.extendext(!0,"replace",{},c.OPERATORS[e.type],e)),void 0!==e.nb_inputs&&void 0!==e.apply_to||h.error("Config",'Missing "nb_inputs" and/or "apply_to" for operator "{0}"',e.type)),-1!=i.indexOf(e.type)&&h.error("Config",'Operator "{0}" already defined',e.type),i.push(e.type),e.optgroup?(this.status.has_operator_optgroup=!0,this.settings.optgroups[e.optgroup]||(this.settings.optgroups[e.optgroup]=e.optgroup)):e.optgroup=null},this),this.status.has_operator_optgroup&&(r=h.groupSort(r,"optgroup")),r},c.prototype.bindEvents=function(){var n=this,t=c.selectors;this.$el.on("change.queryBuilder",t.group_condition,function(){if($(this).is(":checked")){var e=$(this).closest(t.group_container);n.getModel(e).condition=$(this).val()}}),this.$el.on("change.queryBuilder",t.rule_filter,function(){var e=$(this).closest(t.rule_container);n.getModel(e).filter=n.getFilterById($(this).val())}),this.$el.on("change.queryBuilder",t.rule_operator,function(){var e=$(this).closest(t.rule_container);n.getModel(e).operator=n.getOperatorByType($(this).val())}),this.$el.on("click.queryBuilder",t.add_rule,function(){var e=$(this).closest(t.group_container);n.addRule(n.getModel(e))}),this.$el.on("click.queryBuilder",t.delete_rule,function(){var e=$(this).closest(t.rule_container);n.deleteRule(n.getModel(e))}),0!==this.settings.allow_groups&&(this.$el.on("click.queryBuilder",t.add_group,function(){var e=$(this).closest(t.group_container);n.addGroup(n.getModel(e))}),this.$el.on("click.queryBuilder",t.delete_group,function(){var e=$(this).closest(t.group_container);n.deleteGroup(n.getModel(e))})),this.model.on({drop:function(e,t){t.$el.remove(),n.refreshGroupsConditions()},add:function(e,t,r,i){0===i?r.$el.prependTo(t.$el.find(">"+c.selectors.rules_list)):r.$el.insertAfter(t.rules[i-1].$el),n.refreshGroupsConditions()},move:function(e,t,r,i){t.$el.detach(),0===i?t.$el.prependTo(r.$el.find(">"+c.selectors.rules_list)):t.$el.insertAfter(r.rules[i-1].$el),n.refreshGroupsConditions()},update:function(e,t,r,i,o){if(t instanceof l)switch(r){case"error":n.updateError(t);break;case"flags":n.applyRuleFlags(t);break;case"filter":n.updateRuleFilter(t,o);break;case"operator":n.updateRuleOperator(t,o);break;case"value":n.updateRuleValue(t,o)}else switch(r){case"error":n.updateError(t);break;case"flags":n.applyGroupFlags(t);break;case"condition":n.updateGroupCondition(t,o)}}})},c.prototype.setRoot=function(e,t,r){e=void 0===e||!0===e;var i=this.nextGroupId(),o=$(this.getGroupTemplate(i,1));return this.$el.append(o),this.model.root=new a(null,o),this.model.root.model=this.model,this.model.root.data=t,this.model.root.flags=$.extend({},this.settings.default_group_flags,r),this.model.root.condition=this.settings.default_condition,this.trigger("afterAddGroup",this.model.root),e&&this.addRule(this.model.root),this.model.root},c.prototype.addGroup=function(e,t,r,i){t=void 0===t||!0===t;var o=e.level+1;if(this.trigger("beforeAddGroup",e,t,o).isDefaultPrevented())return null;var n=this.nextGroupId(),l=$(this.getGroupTemplate(n,o)),s=e.addGroup(l);return s.data=r,s.flags=$.extend({},this.settings.default_group_flags,i),s.condition=this.settings.default_condition,this.trigger("afterAddGroup",s),this.trigger("rulesChanged"),t&&this.addRule(s),s},c.prototype.deleteGroup=function(e){if(e.isRoot())return!1;if(this.trigger("beforeDeleteGroup",e).isDefaultPrevented())return!1;var t=!0;return e.each("reverse",function(e){t&=this.deleteRule(e)},function(e){t&=this.deleteGroup(e)},this),t&&(e.drop(),this.trigger("afterDeleteGroup"),this.trigger("rulesChanged")),t},c.prototype.updateGroupCondition=function(t,e){t.$el.find(">"+c.selectors.group_condition).each(function(){var e=$(this);e.prop("checked",e.val()===t.condition),e.parent().toggleClass("active",e.val()===t.condition)}),this.trigger("afterUpdateGroupCondition",t,e),this.trigger("rulesChanged")},c.prototype.refreshGroupsConditions=function(){!function t(e){(!e.flags||e.flags&&!e.flags.condition_readonly)&&e.$el.find(">"+c.selectors.group_condition).prop("disabled",e.rules.length<=1).parent().toggleClass("disabled",e.rules.length<=1),e.each(null,function(e){t(e)},this)}(this.model.root)},c.prototype.addRule=function(e,t,r){if(this.trigger("beforeAddRule",e).isDefaultPrevented())return null;var i=this.nextRuleId(),o=$(this.getRuleTemplate(i)),n=e.addRule(o);return n.data=t,n.flags=$.extend({},this.settings.default_rule_flags,r),this.trigger("afterAddRule",n),this.trigger("rulesChanged"),this.createRuleFilters(n),!this.settings.default_filter&&this.settings.display_empty_filter||(n.filter=this.change("getDefaultFilter",this.getFilterById(this.settings.default_filter||this.filters[0].id),n)),n},c.prototype.deleteRule=function(e){return!e.flags.no_delete&&(!this.trigger("beforeDeleteRule",e).isDefaultPrevented()&&(e.drop(),this.trigger("afterDeleteRule"),this.trigger("rulesChanged"),!0))},c.prototype.createRuleFilters=function(e){var t=this.change("getRuleFilters",this.filters,e),r=$(this.getRuleFilterSelect(e,t));e.$el.find(c.selectors.filter_container).html(r),this.trigger("afterCreateRuleFilters",e),this.applyRuleFlags(e)},c.prototype.createRuleOperators=function(e){var t=e.$el.find(c.selectors.operator_container).empty();if(e.filter){var r=this.getOperators(e.filter),i=$(this.getRuleOperatorSelect(e,r));t.html(i),e.filter.default_operator?e.__.operator=this.getOperatorByType(e.filter.default_operator):e.__.operator=r[0],e.$el.find(c.selectors.rule_operator).val(e.operator.type),this.trigger("afterCreateRuleOperators",e,r),this.applyRuleFlags(e)}},c.prototype.createRuleInput=function(e){var t=e.$el.find(c.selectors.value_container).empty();if(e.__.value=void 0,e.filter&&e.operator&&0!==e.operator.nb_inputs){for(var r=this,i=$(),o=e.filter,n=0;n"+r.group_condition).prop("disabled",t.condition_readonly).parent().toggleClass("readonly",t.condition_readonly),t.no_add_rule&&e.$el.find(r.add_rule).remove(),t.no_add_group&&e.$el.find(r.add_group).remove(),t.no_delete&&e.$el.find(r.delete_group).remove(),this.trigger("afterApplyGroupFlags",e)},c.prototype.clearErrors=function(e){(e=e||this.model.root)&&(e.error=null,e instanceof a&&e.each(function(e){e.error=null},function(e){this.clearErrors(e)},this))},c.prototype.updateError=function(e){if(this.settings.display_errors)if(null===e.error)e.$el.removeClass("has-error");else{var t=this.translate("errors",e.error[0]);t=h.fmt(t,e.error.slice(1)),t=this.change("displayError",t,e.error,e),e.$el.addClass("has-error").find(c.selectors.error_container).eq(0).attr("title",t)}},c.prototype.triggerValidationError=function(e,t,r){$.isArray(t)||(t=[t]),this.trigger("validationError",e,t,r).isDefaultPrevented()||(e.error=t)},c.prototype.destroy=function(){this.trigger("beforeDestroy"),this.status.generated_id&&this.$el.removeAttr("id"),this.clear(),this.model=null,this.$el.off(".queryBuilder").removeClass("query-builder").removeData("queryBuilder"),delete this.$el[0].queryBuilder},c.prototype.reset=function(){this.trigger("beforeReset").isDefaultPrevented()||(this.status.group_id=1,this.status.rule_id=0,this.model.root.empty(),this.model.root.data=void 0,this.model.root.flags=$.extend({},this.settings.default_group_flags),this.model.root.condition=this.settings.default_condition,this.addRule(this.model.root),this.trigger("afterReset"),this.trigger("rulesChanged"))},c.prototype.clear=function(){this.trigger("beforeClear").isDefaultPrevented()||(this.status.group_id=0,this.status.rule_id=0,this.model.root&&(this.model.root.drop(),this.model.root=null),this.trigger("afterClear"),this.trigger("rulesChanged"))},c.prototype.setOptions=function(e){$.each(e,function(e,t){-1!==c.modifiable_options.indexOf(e)&&(this.settings[e]=t)}.bind(this))},c.prototype.getModel=function(e){return e?e instanceof o?e:$(e).data("queryBuilderModel"):this.model.root},c.prototype.validate=function(n){n=$.extend({skip_empty:!1},n),this.clearErrors();var l=this,e=function r(e){var i=0,o=0;return e.each(function(e){if(e.filter||!n.skip_empty){if(!e.filter)return l.triggerValidationError(e,"no_filter",null),void o++;if(!e.operator)return l.triggerValidationError(e,"no_operator",null),void o++;if(0!==e.operator.nb_inputs){var t=l.validateValue(e,e.value);if(!0!==t)return l.triggerValidationError(e,t,e.value),void o++}i++}},function(e){var t=r(e);!0===t?i++:!1===t&&o++}),!(0parseInt(l.max)){s=[this.getValidationMessage(l,"max","string_exceed_max_length"),l.max];break}if(!l.format||("string"==typeof l.format&&(l.format=new RegExp(l.format)),l.format.test(i[u])))break;s=[this.getValidationMessage(l,"format","string_invalid_format"),l.format];break;case"number":if(void 0===i[u]||0===i[u].length){l.allow_empty_value||(s=["number_nan"]);break}if(isNaN(i[u])){s=["number_nan"];break}if("integer"==o.type){if(parseInt(i[u])!=i[u]){s=["number_not_integer"];break}}else if(parseFloat(i[u])!=i[u]){s=["number_not_double"];break}if(void 0!==l.min&&i[u]parseFloat(l.max)){s=[this.getValidationMessage(l,"max","number_exceed_max"),l.max];break}if(void 0!==l.step&&"any"!==l.step){var p=(i[u]/l.step).toPrecision(14);if(parseInt(p)!=p){s=[this.getValidationMessage(l,"step","number_wrong_step"),l.step];break}}break;case"datetime":if(void 0===i[u]||0===i[u].length){l.allow_empty_value||(s=["datetime_empty"]);break}if(l.format){"moment"in window||h.error("MissingLibrary","MomentJS is required for Date/Time validation. Get it here http://momentjs.com");var d=moment(i[u],l.format);if(!d.isValid()){s=[this.getValidationMessage(l,"format","datetime_invalid"),l.format];break}if(l.min&&dmoment(l.max,l.format)){s=[this.getValidationMessage(l,"max","datetime_exceed_max"),l.max];break}}break;case"boolean":if(void 0===i[u]||0===i[u].length){l.allow_empty_value||(s=["boolean_not_valid"]);break}if("true"!==(r=(""+i[u]).trim().toLowerCase())&&"false"!==r&&"1"!==r&&"0"!==r&&1!==i[u]&&0!==i[u]){s=["boolean_not_valid"];break}}if(!0!==s)break}}if(!0!==s)break}if(("between"===e.operator.type||"not_between"===e.operator.type)&&2===t.length)switch(c.types[o.type]){case"number":t[0]>t[1]&&(s=["number_between_invalid",t[0],t[1]]);break;case"datetime":l.format&&("moment"in window||h.error("MissingLibrary","MomentJS is required for Date/Time validation. Get it here http://momentjs.com"),moment(t[0],l.format).isAfter(moment(t[1],l.format))&&(s=["datetime_between_invalid",t[0],t[1]]))}return s},c.prototype.nextGroupId=function(){return this.status.id+"_group_"+this.status.group_id++},c.prototype.nextRuleId=function(){return this.status.id+"_rule_"+this.status.rule_id++},c.prototype.getOperators=function(r){"string"==typeof r&&(r=this.getFilterById(r));for(var e=[],t=0,i=this.operators.length;t ',c.templates.rule=' {{? it.settings.display_errors }}
{{?}}
',c.templates.filterSelect='{{ var optgroup = null; }} {{? it.settings.display_empty_filter }} {{= it.settings.select_placeholder }} {{?}} {{~ it.filters: filter }} {{? optgroup !== filter.optgroup }} {{? optgroup !== null }}{{?}} {{? (optgroup = filter.optgroup) !== null }} {{?}} {{?}} {{= it.translate(filter.label) }} {{~}} {{? optgroup !== null }} {{?}} ',c.templates.operatorSelect='{{? it.operators.length === 1 }} {{= it.translate("operators", it.operators[0].type) }} {{?}} {{ var optgroup = null; }} {{~ it.operators: operator }} {{? optgroup !== operator.optgroup }} {{? optgroup !== null }}{{?}} {{? (optgroup = operator.optgroup) !== null }} {{?}} {{?}} {{= it.translate("operators", operator.type) }} {{~}} {{? optgroup !== null }} {{?}} ',c.templates.ruleValueSelect='{{ var optgroup = null; }} {{? it.rule.filter.placeholder }} {{= it.rule.filter.placeholder }} {{?}} {{~ it.rule.filter.values: entry }} {{? optgroup !== entry.optgroup }} {{? optgroup !== null }}{{?}} {{? (optgroup = entry.optgroup) !== null }} {{?}} {{?}} {{= entry.label }} {{~}} {{? optgroup !== null }} {{?}} ',c.prototype.getGroupTemplate=function(e,t){var r=this.templates.group({builder:this,group_id:e,level:t,conditions:this.settings.conditions,icons:this.icons,settings:this.settings,translate:this.translate.bind(this)});return this.change("getGroupTemplate",r,t)},c.prototype.getRuleTemplate=function(e){var t=this.templates.rule({builder:this,rule_id:e,icons:this.icons,settings:this.settings,translate:this.translate.bind(this)});return this.change("getRuleTemplate",t)},c.prototype.getRuleFilterSelect=function(e,t){var r=this.templates.filterSelect({builder:this,rule:e,filters:t,icons:this.icons,settings:this.settings,translate:this.translate.bind(this)});return this.change("getRuleFilterSelect",r,e,t)},c.prototype.getRuleOperatorSelect=function(e,t){var r=this.templates.operatorSelect({builder:this,rule:e,operators:t,icons:this.icons,settings:this.settings,translate:this.translate.bind(this)});return this.change("getRuleOperatorSelect",r,e,t)},c.prototype.getRuleValueSelect=function(e,t){var r=this.templates.ruleValueSelect({builder:this,name:e,rule:t,icons:this.icons,settings:this.settings,translate:this.translate.bind(this)});return this.change("getRuleValueSelect",r,e,t)},c.prototype.getRuleInput=function(e,t){var r=e.filter,i=e.filter.validation||{},o=e.id+"_value_"+t,n=r.vertical?" class=block":"",l="",s=Array.isArray(r.placeholder)?r.placeholder[t]:r.placeholder;if("function"==typeof r.input)l=r.input.call(this,e,o);else switch(r.input){case"radio":case"checkbox":h.iterateOptions(r.values,function(e,t){l+=" '+t+" "});break;case"select":l=this.getRuleValueSelect(o,e);break;case"textarea":l+='";break;case"number":l+=' " ;break;default:l=' " }return this.change getRuleInput ,l,e,o)};var h="{};function" i(){this.root='null,this.$=$(this)}(c.utils=h).iterateOptions=function(e,r){e&&($.isArray(e)?e.forEach(function(e){$.isPlainObject(e)?"value"in' e?r(e.value,e.label||e.value,e.optgroup):$.each(e,function(e,t){return r(e,t),!1}):r(e,e)}):$.each(e,function(e,t){r(e,t)}))},h.fmt="function(e,r){return" Array.isArray(r)||(r="Array.prototype.slice.call(arguments,1)),e.replace(/{([0-9]+)}/g,function(e,t){return" r[parseInt(t)]})},h.error="function(){var" e='0,t="boolean"!=typeof' arguments[e]||arguments[e++],r="arguments[e++],i=arguments[e++],o=Array.isArray(arguments[e])?arguments[e]:Array.prototype.slice.call(arguments,e);if(t){var" n="new" Error(h.fmt(i,o));throw n.name='r+"Error",n.args=o,n}console.error(r+"Error:' +h.fmt(i,o))},h.changeType='function(e,t){if(""!==e&&void' 0='=e)switch(t){case"integer":return"string"!=typeof' e||/^-?\d+$/.test(e)?parseInt(e):e;case double :return string !="typeof" e||/^-?\d+\.?\d*$/.test(e)?parseFloat(e):e;case boolean :return string !="typeof" e||/^(0|1|true|false){1}$/i.test(e)?!0='==e||1===e||"true"===e.toLowerCase()||"1"===e:e;default:return' e}},h.escapeString='function(e){return"string"!=typeof' e?e:e.replace(/[\0\n\r\b \ ]/g,function(e){switch(e){case \0 :return \\0 ;case \n :return \\n ;case \r :return \\r ;case \b :return \\b ;default:return \ +e}}).replace(/\t/g \\t ).replace(/\x1a/g \\Z )},h.escapeRegExp="function(e){return" e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g \ )},h.escapeElementId="function(e){return" e?e.replace(/(\\)?([:.\[\],])/g,function(e,t,r){return t?e \ +r}):e},h.groupSort="function(e,r){var" i="[],o=[];return" e.forEach(function(e){var t;e[r]?-1="=(t=i.lastIndexOf(e[r]))?t=i.length:t++:t=i.length,i.splice(t,0,e[r]),o.splice(t,0,e)}),o},h.defineModelProperties=function(e,t){t.forEach(function(r){Object.defineProperty(e.prototype,r,{enumerable:!0,get:function(){return" this.__[r]},set:function(e){var t='null!==this.__[r]&&"object"==typeof' this.__[r]?$.extend({},this.__[r]):this.__[r];this.__[r='e,null!==this.model&&this.model.trigger("update",this,r,e,t)}})})},$.extend(i.prototype,{trigger:function(e){var' t="new" $.Event(e);return this.$.triggerHandler(t,Array.prototype.slice.call(arguments,1)),t},on:function(){return this.$.on.apply(this.$,Array.prototype.slice.call(arguments)),this},off:function(){return this.$.off.apply(this.$,Array.prototype.slice.call(arguments)),this},once:function(){return this.$.one.apply(this.$,Array.prototype.slice.call(arguments)),this}});var o="function(e,t){if(!(this" instanceof o))return new o(e,t);Object.defineProperty(this _ ,{value:{}}),t.data queryBuilderModel ,this),this.__.level="1,this.__.error=null,this.__.flags={},this.__.data=void" 0,this.$el='t,this.id=t[0].id,this.model=null,this.parent=e};h.defineModelProperties(o,["level","error","data","flags"]),Object.defineProperty(o.prototype,"parent",{enumerable:!0,get:function(){return' this.__.parent},set:function(e){this.__.parent="e,this.level=null===e?1:e.level+1,this.model=null===e?null:e.model}}),o.prototype.isRoot=function(){return" 1="==this.level},o.prototype.getPos=function(){return" this.isRoot()?-1:this.parent.getNodePos(this)},o.prototype.drop="function(){var" e='this.model;this.parent&&this.parent.removeNode(this),this.$el.removeData("queryBuilderModel"),null!==e&&e.trigger("drop",this)},o.prototype.moveAfter=function(e){this.isRoot()||this.move(e.parent,e.getPos()+1)},o.prototype.moveAtBegin=function(e){this.isRoot()||(void' 0="==e&&(e=this.parent),this.move(e,0))},o.prototype.moveAtEnd=function(e){this.isRoot()||(void" 0='==e&&(e=this.parent),this.move(e,0===e.length()?0:e.length()-1))},o.prototype.move=function(e,t){this.isRoot()||("number"==typeof' e&&(t='e,e=this.parent),this.parent.removeNode(this),e.insertNode(this,t,!1),null!==this.model&&this.model.trigger("move",this,e,t))};var' a="function(e,t){if(!(this" instanceof a))return new a(e,t);o.call(this,e,t),this.rules='[],this.__.condition=null};a.prototype=Object.create(o.prototype),a.prototype.constructor=a,h.defineModelProperties(a,["condition"]),a.prototype.empty=function(){this.each("reverse",function(e){e.drop()},function(e){e.drop()})},a.prototype.drop=function(){this.empty(),o.prototype.drop.call(this)},a.prototype.length=function(){return' this.rules.length},a.prototype.insertNode="function(e,t,r){return" void 0='==t&&(t=this.length()),this.rules.splice(t,0,e),e.parent=this,r&&null!==this.model&&this.model.trigger("add",this,e,t),e},a.prototype.addGroup=function(e,t){return' this.insertNode(new a(this,e),t,!0)},a.prototype.addRule="function(e,t){return" this.insertNode(new l(this,e),t,!0)},a.prototype.removeNode="function(e){var" t="this.getNodePos(e);-1!==t&&(e.parent=null,this.rules.splice(t,1))},a.prototype.getNodePos=function(e){return" this.rules.indexOf(e)},a.prototype.each='function(e,t,r,i){"boolean"!=typeof' e string !="typeof" e&&(i="r,r=t,t=e,e=!1),i=void" 0="==i?null:i;for(var" o="e?this.rules.length-1:0,n=e?0:this.rules.length-1,l=e?-1:1,s=!1;(e?n<=o:o<=n)&&(this.rules[o]instanceof" a?r&&(s="!1===r.call(i,this.rules[o])):t&&(s=!1===t.call(i,this.rules[o])),!s);o+=l);return!s},a.prototype.contains=function(t,e){return-1!==this.getNodePos(t)||!!e&&!this.each(function(){return!0},function(e){return!e.contains(t,!0)})};var" l="function(e,t){if(!(this" instanceof l))return new l(e,t);o.call(this,e,t),this._updating_value="!1,this._updating_input=!1,this.__.filter=null,this.__.operator=null,this.__.value=void" 0};function u(e,t,r){var i,o,n='c.selectors;(i=t.closest(n.rule_container)).length&&(o="moveAfter"),o||(i=t.closest(n.group_header)).length&&(i=t.closest(n.group_container),o="moveAtBegin"),o||(i=t.closest(n.group_container)).length&&(o="moveAtEnd"),o&&(e[o](r.getModel(i)),r&&e' instanceof l&&r.setRuleInputValue(e,e.value))}function n(e){var t="e.match(/(question_mark|numbered|named)(?:\((.)\))?/);return" t||(t='[null,"question_mark",void' 0]),t}return l.prototype='Object.create(o.prototype),l.prototype.constructor=l,h.defineModelProperties(l,["filter","operator","value"]),l.prototype.isRoot=function(){return!1},c.Group=a,c.Rule=l,$.fn.queryBuilder=function(e){0===this.length&&h.error("Config","No' target defined ),1> '+t+" "})}})},{font:"glyphicons",color:"default"}),c.define("bt-selectpicker",function(r){$.fn.selectpicker&&$.fn.selectpicker.Constructor||h.error("MissingLibrary",'Bootstrap Select is required to use "bt-selectpicker" plugin. Get it here: http://silviomoreto.github.io/bootstrap-select');var i=c.selectors;this.on("afterCreateRuleFilters",function(e,t){t.$el.find(i.rule_filter).removeClass("form-control").selectpicker(r)}),this.on("afterCreateRuleOperators",function(e,t){t.$el.find(i.rule_operator).removeClass("form-control").selectpicker(r)}),this.on("afterUpdateRuleFilter",function(e,t){t.$el.find(i.rule_filter).selectpicker("render")}),this.on("afterUpdateRuleOperator",function(e,t){t.$el.find(i.rule_operator).selectpicker("render")}),this.on("beforeDeleteRule",function(e,t){t.$el.find(i.rule_filter).selectpicker("destroy"),t.$el.find(i.rule_operator).selectpicker("destroy")})},{container:"body",style:"btn-inverse btn-sm",width:"auto",showIcon:!1}),c.define("bt-tooltip-errors",function(i){$.fn.tooltip&&$.fn.tooltip.Constructor&&$.fn.tooltip.Constructor.prototype.fixTitle||h.error("MissingLibrary",'Bootstrap Tooltip is required to use "bt-tooltip-errors" plugin. Get it here: http://getbootstrap.com');var o=this;this.on("getRuleTemplate.filter getGroupTemplate.filter",function(e){var t=$(e.value);t.find(c.selectors.error_container).attr("data-toggle","tooltip"),e.value=t.prop("outerHTML")}),this.model.on("update",function(e,t,r){"error"==r&&o.settings.display_errors&&t.$el.find(c.selectors.error_container).eq(0).tooltip(i).tooltip("hide").tooltip("fixTitle")})},{placement:"right"}),c.extend({setFilters:function(e,t){var r=this;void 0===t&&(t=e,e=!1),t=this.checkFilters(t);var i=(t=this.change("setFilters",t)).map(function(e){return e.id});if(e||function e(t){t.each(function(e){e.filter&&-1===i.indexOf(e.filter.id)&&h.error("ChangeFilter",'A rule is using filter "{0}"',e.filter.id)},e)}(this.model.root),this.filters=t,function e(t){t.each(!0,function(e){e.filter&&-1===i.indexOf(e.filter.id)?(e.drop(),r.trigger("rulesChanged")):(r.createRuleFilters(e),e.$el.find(c.selectors.rule_filter).val(e.filter?e.filter.id:"-1"),r.trigger("afterUpdateRuleFilter",e))},e)}(this.model.root),this.settings.plugins&&(this.settings.plugins["unique-filter"]&&this.updateDisabledFilters(),this.settings.plugins["bt-selectpicker"]&&this.$el.find(c.selectors.rule_filter).selectpicker("render")),this.settings.default_filter)try{this.getFilterById(this.settings.default_filter)}catch(e){this.settings.default_filter=null}this.trigger("afterSetFilters",t)},addFilter:function(e,r){void 0===r||"#end"==r?r=this.filters.length:"#start"==r&&(r=0),$.isArray(e)||(e=[e]);var t=$.extend(!0,[],this.filters);parseInt(r)==r?Array.prototype.splice.apply(t,[r,0].concat(e)):this.filters.some(function(e,t){if(e.id==r)return r=t+1,!0})?Array.prototype.splice.apply(t,[r,0].concat(e)):Array.prototype.push.apply(t,e),this.setFilters(t)},removeFilter:function(t,e){var r=$.extend(!0,[],this.filters);"string"==typeof t&&(t=[t]),r=r.filter(function(e){return-1===t.indexOf(e.id)}),this.setFilters(e,r)}}),c.define("chosen-selectpicker",function(r){$.fn.chosen||h.error("MissingLibrary",'chosen is required to use "chosen-selectpicker" plugin. Get it here: https://github.com/harvesthq/chosen'),this.settings.plugins["bt-selectpicker"]&&h.error("Conflict","bt-selectpicker is already selected as the dropdown plugin. Please remove chosen-selectpicker from the plugin list");var i=c.selectors;this.on("afterCreateRuleFilters",function(e,t){t.$el.find(i.rule_filter).removeClass("form-control").chosen(r)}),this.on("afterCreateRuleOperators",function(e,t){1
')).appendTo(t.$el):r.css("display",""),r.html(' '+i)):r.hide()}):"popover"===o.mode?($.fn.popover&&$.fn.popover.Constructor&&$.fn.popover.Constructor.prototype.fixTitle||h.error("MissingLibrary",'Bootstrap Popover is required to use "filter-description" plugin. Get it here: http://getbootstrap.com'),this.on("afterUpdateRuleFilter afterUpdateRuleOperator",function(e,t){var r=t.$el.find("button.filter-description"),i=e.builder.getFilterDescription(t.filter,t);i?(0===r.length?((r=$(' ')).prependTo(t.$el.find(c.selectors.rule_actions)),r.popover({placement:"left",container:"body",html:!0}),r.on("mouseout",function(){r.popover("hide")})):r.css("display",""),r.data("bs.popover").options.content=i,r.attr("aria-describedby")&&r.popover("show")):(r.hide(),r.data("bs.popover")&&r.popover("hide"))})):"bootbox"===o.mode&&("bootbox"in window||h.error("MissingLibrary",'Bootbox is required to use "filter-description" plugin. Get it here: http://bootboxjs.com'),this.on("afterUpdateRuleFilter afterUpdateRuleOperator",function(e,t){var r=t.$el.find("button.filter-description"),i=e.builder.getFilterDescription(t.filter,t);i?(0===r.length?((r=$(' ')).prependTo(t.$el.find(c.selectors.rule_actions)),r.on("click",function(){bootbox.alert(r.data("description"))})):r.css("display",""),r.data("description",i)):r.hide()}))},{icon:"glyphicon glyphicon-info-sign",mode:"popover"}),c.extend({getFilterDescription:function(e,t){return e?"function"==typeof e.description?e.description.call(this,t):e.description:void 0}}),c.define("invert",function(r){var i=this,o=c.selectors;this.on("afterInit",function(){i.$el.on("click.queryBuilder","[data-invert=group]",function(){var e=$(this).closest(o.group_container);i.invert(i.getModel(e),r)}),r.display_rules_button&&r.invert_rules&&i.$el.on("click.queryBuilder","[data-invert=rule]",function(){var e=$(this).closest(o.rule_container);i.invert(i.getModel(e),r)})}),r.disable_template||(this.on("getGroupTemplate.filter",function(e){var t=$(e.value);t.find(o.condition_container).after(' '+i.translate("invert")+" "),e.value=t.prop("outerHTML")}),r.display_rules_button&&r.invert_rules&&this.on("getRuleTemplate.filter",function(e){var t=$(e.value);t.find(o.rule_actions).prepend(' '+i.translate("invert")+" "),e.value=t.prop("outerHTML")}))},{icon:"glyphicon glyphicon-random",recursive:!0,invert_rules:!0,display_rules_button:!1,silent_fail:!1,disable_template:!1}),c.defaults({operatorOpposites:{equal:"not_equal",not_equal:"equal",in:"not_in",not_in:"in",less:"greater_or_equal",less_or_equal:"greater",greater:"less_or_equal",greater_or_equal:"less",between:"not_between",not_between:"between",begins_with:"not_begins_with",not_begins_with:"begins_with",contains:"not_contains",not_contains:"contains",ends_with:"not_ends_with",not_ends_with:"ends_with",is_empty:"is_not_empty",is_not_empty:"is_empty",is_null:"is_not_null",is_not_null:"is_null"},conditionOpposites:{AND:"OR",OR:"AND"}}),c.extend({invert:function(e,t){if(!(e instanceof o)){if(!this.model.root)return;t=e,e=this.model.root}if("object"!=typeof t&&(t={}),void 0===t.recursive&&(t.recursive=!0),void 0===t.invert_rules&&(t.invert_rules=!0),void 0===t.silent_fail&&(t.silent_fail=!1),void 0===t.trigger&&(t.trigger=!0),e instanceof a){if(this.settings.conditionOpposites[e.condition]?e.condition=this.settings.conditionOpposites[e.condition]:t.silent_fail||h.error("InvertCondition",'Unknown inverse of condition "{0}"',e.condition),t.recursive){var r=$.extend({},t,{trigger:!1});e.each(function(e){t.invert_rules&&this.invert(e,r)},function(e){this.invert(e,r)},this)}}else if(e instanceof l&&e.operator&&!e.filter.no_invert)if(this.settings.operatorOpposites[e.operator.type]){var i=this.settings.operatorOpposites[e.operator.type];e.filter.operators&&-1==e.filter.operators.indexOf(i)||(e.operator=this.getOperatorByType(i))}else t.silent_fail||h.error("InvertOperator",'Unknown inverse of operator "{0}"',e.operator.type);t.trigger&&(this.trigger("afterInvert",e,t),this.trigger("rulesChanged"))}}),c.defaults({mongoOperators:{equal:function(e){return e[0]},not_equal:function(e){return{$ne:e[0]}},in:function(e){return{$in:e}},not_in:function(e){return{$nin:e}},less:function(e){return{$lt:e[0]}},less_or_equal:function(e){return{$lte:e[0]}},greater:function(e){return{$gt:e[0]}},greater_or_equal:function(e){return{$gte:e[0]}},between:function(e){return{$gte:e[0],$lte:e[1]}},not_between:function(e){return{$lt:e[0],$gt:e[1]}},begins_with:function(e){return{$regex:"^"+h.escapeRegExp(e[0])}},not_begins_with:function(e){return{$regex:"^(?!"+h.escapeRegExp(e[0])+")"}},contains:function(e){return{$regex:h.escapeRegExp(e[0])}},not_contains:function(e){return{$regex:"^((?!"+h.escapeRegExp(e[0])+").)*$",$options:"s"}},ends_with:function(e){return{$regex:h.escapeRegExp(e[0])+"$"}},not_ends_with:function(e){return{$regex:"(? '+i.translate("NOT")+""),e.value=t.prop("outerHTML")}),this.on("groupToJson.filter",function(e,t){e.value.not=t.not}),this.on("jsonToGroup.filter",function(e,t){e.value.not=!!t.not}),this.on("groupToSQL.filter",function(e,t){t.not&&(e.value="NOT ( "+e.value+" )")}),this.on("parseSQLNode.filter",function(e){e.value.name&&"NOT"==e.value.name.toUpperCase()&&(e.value=e.value.arguments.value[0],-1===["AND","OR"].indexOf(e.value.operation.toUpperCase())&&(e.value=new SQLParser.nodes.Op(i.settings.default_condition,e.value,null)),e.value.not=!0)}),this.on("sqlGroupsDistinct.filter",function(e,t,r,i){r.not&&0"+c.selectors.group_not).toggleClass("active",e.not).find("i").attr("class",e.not?t.icon_checked:t.icon_unchecked),this.trigger("afterUpdateGroupNot",e),this.trigger("rulesChanged")}}),c.define("sortable",function(i){var o,n,l,s;"interact"in window||h.error("MissingLibrary",'interact.js is required to use "sortable" plugin. Get it here: http://interactjs.io'),void 0!==i.default_no_sortable&&(h.error(!1,"Config",'Sortable plugin : "default_no_sortable" options is deprecated, use standard "default_rule_flags" and "default_group_flags" instead'),this.settings.default_rule_flags.no_sortable=this.settings.default_group_flags.no_sortable=i.default_no_sortable),interact.dynamicDrop(!0),interact.pointerMoveTolerance(10),this.on("afterAddRule afterAddGroup",function(e,t){if(t!=o){var r=e.builder;i.inherit_no_sortable&&t.parent&&t.parent.flags.no_sortable&&(t.flags.no_sortable=!0),i.inherit_no_drop&&t.parent&&t.parent.flags.no_drop&&(t.flags.no_drop=!0),t.flags.no_sortable||interact(t.$el[0]).draggable({allowFrom:c.selectors.drag_handle,onstart:function(e){s=!1,l=r.getModel(e.target),n=l.$el.clone().appendTo(l.$el.parent()).width(l.$el.outerWidth()).addClass("dragging");var t=$('
').height(l.$el.outerHeight());o=l.parent.addRule(t,l.getPos()),l.$el.hide()},onmove:function(e){n[0].style.top=e.clientY-15+"px",n[0].style.left=e.clientX-15+"px"},onend:function(e){e.dropzone&&(u(l,$(e.relatedTarget),r),s=!0),n.remove(),n=void 0,o.drop(),o=void 0,l.$el.css("display",""),r.trigger("afterMove",l),r.trigger("rulesChanged")}}),t.flags.no_drop||(interact(t.$el[0]).dropzone({accept:c.selectors.rule_and_group_containers,ondragenter:function(e){u(o,$(e.target),r)},ondrop:function(e){s||u(l,$(e.target),r)}}),t instanceof a&&interact(t.$el.find(c.selectors.group_header)[0]).dropzone({accept:c.selectors.rule_and_group_containers,ondragenter:function(e){u(o,$(e.target),r)},ondrop:function(e){s||u(l,$(e.target),r)}}))}}),this.on("beforeDeleteRule beforeDeleteGroup",function(e,t){e.isDefaultPrevented()||(interact(t.$el[0]).unset(),t instanceof a&&interact(t.$el.find(c.selectors.group_header)[0]).unset())}),this.on("afterApplyRuleFlags afterApplyGroupFlags",function(e,t){t.flags.no_sortable&&t.$el.find(".drag-handle").remove()}),i.disable_template||(this.on("getGroupTemplate.filter",function(e,t){if(1 '),e.value=r.prop("outerHTML")}}),this.on("getRuleTemplate.filter",function(e){var t=$(e.value);t.find(c.selectors.rule_header).after('
'),e.value=t.prop("outerHTML")}))},{inherit_no_sortable:!0,inherit_no_drop:!0,icon:"glyphicon glyphicon-sort",disable_template:!1}),c.selectors.rule_and_group_containers=c.selectors.rule_container+", "+c.selectors.group_container,c.selectors.drag_handle=".drag-handle",c.defaults({default_rule_flags:{no_sortable:!1,no_drop:!1},default_group_flags:{no_sortable:!1,no_drop:!1}}),c.define("sql-support",function(e){},{boolean_as_integer:!0}),c.defaults({sqlOperators:{equal:{op:"= ?"},not_equal:{op:"!= ?"},in:{op:"IN(?)",sep:", "},not_in:{op:"NOT IN(?)",sep:", "},less:{op:"< ?"},less_or_equal:{op:"<= ?"},greater:{op:"> ?"},greater_or_equal:{op:">= ?"},between:{op:"BETWEEN ?",sep:" AND "},not_between:{op:"NOT BETWEEN ?",sep:" AND "},begins_with:{op:"LIKE(?)",mod:"{0}%"},not_begins_with:{op:"NOT LIKE(?)",mod:"{0}%"},contains:{op:"LIKE(?)",mod:"%{0}%"},not_contains:{op:"NOT LIKE(?)",mod:"%{0}%"},ends_with:{op:"LIKE(?)",mod:"%{0}"},not_ends_with:{op:"NOT LIKE(?)",mod:"%{0}"},is_empty:{op:"= ''"},is_not_empty:{op:"!= ''"},is_null:{op:"IS NULL"},is_not_null:{op:"IS NOT NULL"}},sqlRuleOperator:{"=":function(e){return{val:e,op:""===e?"is_empty":"equal"}},"!=":function(e){return{val:e,op:""===e?"is_not_empty":"not_equal"}},LIKE:function(e){return"%"==e.slice(0,1)&&"%"==e.slice(-1)?{val:e.slice(1,-1),op:"contains"}:"%"==e.slice(0,1)?{val:e.slice(1),op:"ends_with"}:"%"==e.slice(-1)?{val:e.slice(0,-1),op:"begins_with"}:void h.error("SQLParse",'Invalid value for LIKE operator "{0}"',e)},"NOT LIKE":function(e){return"%"==e.slice(0,1)&&"%"==e.slice(-1)?{val:e.slice(1,-1),op:"not_contains"}:"%"==e.slice(0,1)?{val:e.slice(1),op:"not_ends_with"}:"%"==e.slice(-1)?{val:e.slice(0,-1),op:"not_begins_with"}:void h.error("SQLParse",'Invalid value for NOT LIKE operator "{0}"',e)},IN:function(e){return{val:e,op:"in"}},"NOT IN":function(e){return{val:e,op:"not_in"}},"<":function(e){return{val:e,op:"less"}},"<=":function(e){return{val:e,op:"less_or_equal"}},">":function(e){return{val:e,op:"greater"}},">=":function(e){return{val:e,op:"greater_or_equal"}},BETWEEN:function(e){return{val:e,op:"between"}},"NOT BETWEEN":function(e){return{val:e,op:"not_between"}},IS:function(e){return null!==e&&h.error("SQLParse","Invalid value for IS operator"),{val:null,op:"is_null"}},"IS NOT":function(e){return null!==e&&h.error("SQLParse","Invalid value for IS operator"),{val:null,op:"is_not_null"}}},sqlStatements:{question_mark:function(){var r=[];return{add:function(e,t){return r.push(t),"?"},run:function(){return r}}},numbered:function(r){(!r||1"==l&&(l="!=");var s=f.settings.sqlRuleOperator[l];void 0===s&&h.error("UndefinedSQLOperator",'Invalid SQL operation "{0}".',t.operation);var a,u=s.call(this,n,t.operation);"values"in t.left?a=t.left.values.join("."):"value"in t.left?a=t.left.value:h.error("SQLParse","Cannot find field name in {0}",JSON.stringify(t.left));var p=f.getSQLFieldID(a,n),d=f.change("sqlToRule",{id:p,field:a,operator:u.op,value:u.val},t);g.rules.push(d)}}(i,0),o},setRulesFromSQL:function(e,t){this.setRules(this.getRulesFromSQL(e,t))},getSQLFieldID:function(t,e){var r=this.filters.filter(function(e){return e.field.toLowerCase()===t.toLowerCase()});return 1===r.length?r[0].id:this.change("getSQLFieldID",t,e)}}),c.define("unique-filter",function(){this.status.used_filters={},this.on("afterUpdateRuleFilter",this.updateDisabledFilters),this.on("afterDeleteRule",this.updateDisabledFilters),this.on("afterCreateRuleFilters",this.applyDisabledFilters),this.on("afterReset",this.clearDisabledFilters),this.on("afterClear",this.clearDisabledFilters),this.on("getDefaultFilter.filter",function(t,r){var i=t.builder;(i.updateDisabledFilters(),t.value.id in i.status.used_filters)&&(i.filters.some(function(e){if(!(e.id in i.status.used_filters)||0 <","<=",">",">=","BETWEEN","NOT BETWEEN","IS","IS NOT","sqlStatements","question_mark","params","run","numbered","char","named","indexes","sqlRuleStatement","esc","sql","regex1","regex2","getSQL","nl","sqlFn","getRulesFromSQL","parsed","where","curr","flatten","next","right","sqlrl","JSON","stringify","getSQLFieldID","setRulesFromSQL","used_filters","applyDisabledFilters","clearDisabledFilters","unique","filterId","groups","__locale","__author","no_filter","empty_group","radio_empty","checkbox_empty","select_empty","string_empty","string_exceed_min_length","string_exceed_max_length","string_invalid_format","number_nan","number_not_integer","number_not_double","number_exceed_min","number_exceed_max","number_wrong_step","number_between_invalid","datetime_empty","datetime_invalid","datetime_exceed_min","datetime_exceed_max","datetime_between_invalid","boolean_not_valid","operator_not_multiple","NOT"],"mappings":"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","file":"query-builder.min.js"}
\ No newline at end of file
diff --git a/dist/js/query-builder.standalone.js b/dist/js/query-builder.standalone.js
new file mode 100644
index 00000000..fe937432
--- /dev/null
+++ b/dist/js/query-builder.standalone.js
@@ -0,0 +1,6346 @@
+// doT.js
+// 2011-2014, Laura Doktorova, https://github.com/olado/doT
+// Licensed under the MIT license.
+
+(function () {
+ "use strict";
+
+ var doT = {
+ name: "doT",
+ version: "1.1.1",
+ templateSettings: {
+ evaluate: /\{\{([\s\S]+?(\}?)+)\}\}/g,
+ interpolate: /\{\{=([\s\S]+?)\}\}/g,
+ encode: /\{\{!([\s\S]+?)\}\}/g,
+ use: /\{\{#([\s\S]+?)\}\}/g,
+ useParams: /(^|[^\w$])def(?:\.|\[[\'\"])([\w$\.]+)(?:[\'\"]\])?\s*\:\s*([\w$\.]+|\"[^\"]+\"|\'[^\']+\'|\{[^\}]+\})/g,
+ define: /\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,
+ defineParams:/^\s*([\w$]+):([\s\S]+)/,
+ conditional: /\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g,
+ iterate: /\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g,
+ varname: "it",
+ strip: true,
+ append: true,
+ selfcontained: false,
+ doNotSkipEncoded: false
+ },
+ template: undefined, //fn, compile template
+ compile: undefined, //fn, for express
+ log: true
+ }, _globals;
+
+ doT.encodeHTMLSource = function(doNotSkipEncoded) {
+ var encodeHTMLRules = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'", "/": "/" },
+ matchHTML = doNotSkipEncoded ? /[&<>"'\/]/g : /&(?!#?\w+;)|<|>|"|'|\//g;
+ return function(code) {
+ return code ? code.toString().replace(matchHTML, function(m) {return encodeHTMLRules[m] || m;}) : "";
+ };
+ };
+
+ _globals = (function(){ return this || (0,eval)("this"); }());
+
+ /* istanbul ignore else */
+ if (typeof module !== "undefined" && module.exports) {
+ module.exports = doT;
+ } else if (typeof define === "function" && define.amd) {
+ define('doT', function(){return doT;});
+ } else {
+ _globals.doT = doT;
+ }
+
+ var startend = {
+ append: { start: "'+(", end: ")+'", startencode: "'+encodeHTML(" },
+ split: { start: "';out+=(", end: ");out+='", startencode: "';out+=encodeHTML(" }
+ }, skip = /$^/;
+
+ function resolveDefs(c, block, def) {
+ return ((typeof block === "string") ? block : block.toString())
+ .replace(c.define || skip, function(m, code, assign, value) {
+ if (code.indexOf("def.") === 0) {
+ code = code.substring(4);
+ }
+ if (!(code in def)) {
+ if (assign === ":") {
+ if (c.defineParams) value.replace(c.defineParams, function(m, param, v) {
+ def[code] = {arg: param, text: v};
+ });
+ if (!(code in def)) def[code]= value;
+ } else {
+ new Function("def", "def['"+code+"']=" + value)(def);
+ }
+ }
+ return "";
+ })
+ .replace(c.use || skip, function(m, code) {
+ if (c.useParams) code = code.replace(c.useParams, function(m, s, d, param) {
+ if (def[d] && def[d].arg && param) {
+ var rw = (d+":"+param).replace(/'|\\/g, "_");
+ def.__exp = def.__exp || {};
+ def.__exp[rw] = def[d].text.replace(new RegExp("(^|[^\\w$])" + def[d].arg + "([^\\w$])", "g"), "$1" + param + "$2");
+ return s + "def.__exp['"+rw+"']";
+ }
+ });
+ var v = new Function("def", "return " + code)(def);
+ return v ? resolveDefs(c, v, def) : v;
+ });
+ }
+
+ function unescape(code) {
+ return code.replace(/\\('|\\)/g, "$1").replace(/[\r\t\n]/g, " ");
+ }
+
+ doT.template = function(tmpl, c, def) {
+ c = c || doT.templateSettings;
+ var cse = c.append ? startend.append : startend.split, needhtmlencode, sid = 0, indv,
+ str = (c.use || c.define) ? resolveDefs(c, tmpl, def || {}) : tmpl;
+
+ str = ("var out='" + (c.strip ? str.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g," ")
+ .replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,""): str)
+ .replace(/'|\\/g, "\\$&")
+ .replace(c.interpolate || skip, function(m, code) {
+ return cse.start + unescape(code) + cse.end;
+ })
+ .replace(c.encode || skip, function(m, code) {
+ needhtmlencode = true;
+ return cse.startencode + unescape(code) + cse.end;
+ })
+ .replace(c.conditional || skip, function(m, elsecase, code) {
+ return elsecase ?
+ (code ? "';}else if(" + unescape(code) + "){out+='" : "';}else{out+='") :
+ (code ? "';if(" + unescape(code) + "){out+='" : "';}out+='");
+ })
+ .replace(c.iterate || skip, function(m, iterate, vname, iname) {
+ if (!iterate) return "';} } out+='";
+ sid+=1; indv=iname || "i"+sid; iterate=unescape(iterate);
+ return "';var arr"+sid+"="+iterate+";if(arr"+sid+"){var "+vname+","+indv+"=-1,l"+sid+"=arr"+sid+".length-1;while("+indv+"}
+ * @readonly
+ */
+ this.icons = this.settings.icons;
+
+ /**
+ * List of operators
+ * @member {QueryBuilder.Operator[]}
+ * @readonly
+ */
+ this.operators = this.settings.operators;
+
+ /**
+ * List of templates
+ * @member {object.}
+ * @readonly
+ */
+ this.templates = this.settings.templates;
+
+ /**
+ * Plugins configuration
+ * @member {object.}
+ * @readonly
+ */
+ this.plugins = this.settings.plugins;
+
+ /**
+ * Translations object
+ * @member {object}
+ * @readonly
+ */
+ this.lang = null;
+
+ // translations : english << 'lang_code' << custom
+ if (QueryBuilder.regional['en'] === undefined) {
+ Utils.error('Config', '"i18n/en.js" not loaded.');
+ }
+ this.lang = $.extendext(true, 'replace', {}, QueryBuilder.regional['en'], QueryBuilder.regional[this.settings.lang_code], this.settings.lang);
+
+ // "allow_groups" can be boolean or int
+ if (this.settings.allow_groups === false) {
+ this.settings.allow_groups = 0;
+ }
+ else if (this.settings.allow_groups === true) {
+ this.settings.allow_groups = -1;
+ }
+
+ // init templates
+ Object.keys(this.templates).forEach(function(tpl) {
+ if (!this.templates[tpl]) {
+ this.templates[tpl] = QueryBuilder.templates[tpl];
+ }
+ if (typeof this.templates[tpl] == 'string') {
+ this.templates[tpl] = doT.template(this.templates[tpl]);
+ }
+ }, this);
+
+ // ensure we have a container id
+ if (!this.$el.attr('id')) {
+ this.$el.attr('id', 'qb_' + Math.floor(Math.random() * 99999));
+ this.status.generated_id = true;
+ }
+ this.status.id = this.$el.attr('id');
+
+ // INIT
+ this.$el.addClass('query-builder form-inline');
+
+ this.filters = this.checkFilters(this.filters);
+ this.operators = this.checkOperators(this.operators);
+ this.bindEvents();
+ this.initPlugins();
+};
+
+$.extend(QueryBuilder.prototype, /** @lends QueryBuilder.prototype */ {
+ /**
+ * Triggers an event on the builder container
+ * @param {string} type
+ * @returns {$.Event}
+ */
+ trigger: function(type) {
+ var event = new $.Event(this._tojQueryEvent(type), {
+ builder: this
+ });
+
+ this.$el.triggerHandler(event, Array.prototype.slice.call(arguments, 1));
+
+ return event;
+ },
+
+ /**
+ * Triggers an event on the builder container and returns the modified value
+ * @param {string} type
+ * @param {*} value
+ * @returns {*}
+ */
+ change: function(type, value) {
+ var event = new $.Event(this._tojQueryEvent(type, true), {
+ builder: this,
+ value: value
+ });
+
+ this.$el.triggerHandler(event, Array.prototype.slice.call(arguments, 2));
+
+ return event.value;
+ },
+
+ /**
+ * Attaches an event listener on the builder container
+ * @param {string} type
+ * @param {function} cb
+ * @returns {QueryBuilder}
+ */
+ on: function(type, cb) {
+ this.$el.on(this._tojQueryEvent(type), cb);
+ return this;
+ },
+
+ /**
+ * Removes an event listener from the builder container
+ * @param {string} type
+ * @param {function} [cb]
+ * @returns {QueryBuilder}
+ */
+ off: function(type, cb) {
+ this.$el.off(this._tojQueryEvent(type), cb);
+ return this;
+ },
+
+ /**
+ * Attaches an event listener called once on the builder container
+ * @param {string} type
+ * @param {function} cb
+ * @returns {QueryBuilder}
+ */
+ once: function(type, cb) {
+ this.$el.one(this._tojQueryEvent(type), cb);
+ return this;
+ },
+
+ /**
+ * Appends `.queryBuilder` and optionally `.filter` to the events names
+ * @param {string} name
+ * @param {boolean} [filter=false]
+ * @returns {string}
+ * @private
+ */
+ _tojQueryEvent: function(name, filter) {
+ return name.split(' ').map(function(type) {
+ return type + '.queryBuilder' + (filter ? '.filter' : '');
+ }).join(' ');
+ }
+});
+
+
+/**
+ * Allowed types and their internal representation
+ * @type {object.}
+ * @readonly
+ * @private
+ */
+QueryBuilder.types = {
+ 'string': 'string',
+ 'integer': 'number',
+ 'double': 'number',
+ 'date': 'datetime',
+ 'time': 'datetime',
+ 'datetime': 'datetime',
+ 'boolean': 'boolean'
+};
+
+/**
+ * Allowed inputs
+ * @type {string[]}
+ * @readonly
+ * @private
+ */
+QueryBuilder.inputs = [
+ 'text',
+ 'number',
+ 'textarea',
+ 'radio',
+ 'checkbox',
+ 'select'
+];
+
+/**
+ * Runtime modifiable options with `setOptions` method
+ * @type {string[]}
+ * @readonly
+ * @private
+ */
+QueryBuilder.modifiable_options = [
+ 'display_errors',
+ 'allow_groups',
+ 'allow_empty',
+ 'default_condition',
+ 'default_filter'
+];
+
+/**
+ * CSS selectors for common components
+ * @type {object.}
+ * @readonly
+ */
+QueryBuilder.selectors = {
+ group_container: '.rules-group-container',
+ rule_container: '.rule-container',
+ filter_container: '.rule-filter-container',
+ operator_container: '.rule-operator-container',
+ value_container: '.rule-value-container',
+ error_container: '.error-container',
+ condition_container: '.rules-group-header .group-conditions',
+
+ rule_header: '.rule-header',
+ group_header: '.rules-group-header',
+ group_actions: '.group-actions',
+ rule_actions: '.rule-actions',
+
+ rules_list: '.rules-group-body>.rules-list',
+
+ group_condition: '.rules-group-header [name$=_cond]',
+ rule_filter: '.rule-filter-container [name$=_filter]',
+ rule_operator: '.rule-operator-container [name$=_operator]',
+ rule_value: '.rule-value-container [name*=_value_]',
+
+ add_rule: '[data-add=rule]',
+ delete_rule: '[data-delete=rule]',
+ add_group: '[data-add=group]',
+ delete_group: '[data-delete=group]'
+};
+
+/**
+ * Template strings (see template.js)
+ * @type {object.}
+ * @readonly
+ */
+QueryBuilder.templates = {};
+
+/**
+ * Localized strings (see i18n/)
+ * @type {object.}
+ * @readonly
+ */
+QueryBuilder.regional = {};
+
+/**
+ * Default operators
+ * @type {object.}
+ * @readonly
+ */
+QueryBuilder.OPERATORS = {
+ equal: { type: 'equal', nb_inputs: 1, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean'] },
+ not_equal: { type: 'not_equal', nb_inputs: 1, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean'] },
+ in: { type: 'in', nb_inputs: 1, multiple: true, apply_to: ['string', 'number', 'datetime'] },
+ not_in: { type: 'not_in', nb_inputs: 1, multiple: true, apply_to: ['string', 'number', 'datetime'] },
+ less: { type: 'less', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime'] },
+ less_or_equal: { type: 'less_or_equal', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime'] },
+ greater: { type: 'greater', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime'] },
+ greater_or_equal: { type: 'greater_or_equal', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime'] },
+ between: { type: 'between', nb_inputs: 2, multiple: false, apply_to: ['number', 'datetime'] },
+ not_between: { type: 'not_between', nb_inputs: 2, multiple: false, apply_to: ['number', 'datetime'] },
+ begins_with: { type: 'begins_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ not_begins_with: { type: 'not_begins_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ contains: { type: 'contains', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ not_contains: { type: 'not_contains', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ ends_with: { type: 'ends_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ not_ends_with: { type: 'not_ends_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ is_empty: { type: 'is_empty', nb_inputs: 0, multiple: false, apply_to: ['string'] },
+ is_not_empty: { type: 'is_not_empty', nb_inputs: 0, multiple: false, apply_to: ['string'] },
+ is_null: { type: 'is_null', nb_inputs: 0, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean'] },
+ is_not_null: { type: 'is_not_null', nb_inputs: 0, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean'] }
+};
+
+/**
+ * Default configuration
+ * @type {object}
+ * @readonly
+ */
+QueryBuilder.DEFAULTS = {
+ filters: [],
+ plugins: [],
+
+ sort_filters: false,
+ display_errors: true,
+ allow_groups: -1,
+ allow_empty: false,
+ conditions: ['AND', 'OR'],
+ default_condition: 'AND',
+ inputs_separator: ' , ',
+ select_placeholder: '------',
+ display_empty_filter: true,
+ default_filter: null,
+ optgroups: {},
+
+ default_rule_flags: {
+ filter_readonly: false,
+ operator_readonly: false,
+ value_readonly: false,
+ no_delete: false
+ },
+
+ default_group_flags: {
+ condition_readonly: false,
+ no_add_rule: false,
+ no_add_group: false,
+ no_delete: false
+ },
+
+ templates: {
+ group: null,
+ rule: null,
+ filterSelect: null,
+ operatorSelect: null,
+ ruleValueSelect: null
+ },
+
+ lang_code: 'en',
+ lang: {},
+
+ operators: [
+ 'equal',
+ 'not_equal',
+ 'in',
+ 'not_in',
+ 'less',
+ 'less_or_equal',
+ 'greater',
+ 'greater_or_equal',
+ 'between',
+ 'not_between',
+ 'begins_with',
+ 'not_begins_with',
+ 'contains',
+ 'not_contains',
+ 'ends_with',
+ 'not_ends_with',
+ 'is_empty',
+ 'is_not_empty',
+ 'is_null',
+ 'is_not_null'
+ ],
+
+ icons: {
+ add_group: 'fas fa-plus-circle',
+ add_rule: 'fas fa-plus',
+ remove_group: 'fas fa-times',
+ remove_rule: 'fas fa-times',
+ error: 'fas fa-exclamation-triangle'
+ }
+};
+
+
+/**
+ * @module plugins
+ */
+
+/**
+ * Definition of available plugins
+ * @type {object.}
+ */
+QueryBuilder.plugins = {};
+
+/**
+ * Gets or extends the default configuration
+ * @param {object} [options] - new configuration
+ * @returns {undefined|object} nothing or configuration object (copy)
+ */
+QueryBuilder.defaults = function(options) {
+ if (typeof options == 'object') {
+ $.extendext(true, 'replace', QueryBuilder.DEFAULTS, options);
+ }
+ else if (typeof options == 'string') {
+ if (typeof QueryBuilder.DEFAULTS[options] == 'object') {
+ return $.extend(true, {}, QueryBuilder.DEFAULTS[options]);
+ }
+ else {
+ return QueryBuilder.DEFAULTS[options];
+ }
+ }
+ else {
+ return $.extend(true, {}, QueryBuilder.DEFAULTS);
+ }
+};
+
+/**
+ * Registers a new plugin
+ * @param {string} name
+ * @param {function} fct - init function
+ * @param {object} [def] - default options
+ */
+QueryBuilder.define = function(name, fct, def) {
+ QueryBuilder.plugins[name] = {
+ fct: fct,
+ def: def || {}
+ };
+};
+
+/**
+ * Adds new methods to QueryBuilder prototype
+ * @param {object.} methods
+ */
+QueryBuilder.extend = function(methods) {
+ $.extend(QueryBuilder.prototype, methods);
+};
+
+/**
+ * Initializes plugins for an instance
+ * @throws ConfigError
+ * @private
+ */
+QueryBuilder.prototype.initPlugins = function() {
+ if (!this.plugins) {
+ return;
+ }
+
+ if ($.isArray(this.plugins)) {
+ var tmp = {};
+ this.plugins.forEach(function(plugin) {
+ tmp[plugin] = null;
+ });
+ this.plugins = tmp;
+ }
+
+ Object.keys(this.plugins).forEach(function(plugin) {
+ if (plugin in QueryBuilder.plugins) {
+ this.plugins[plugin] = $.extend(true, {},
+ QueryBuilder.plugins[plugin].def,
+ this.plugins[plugin] || {}
+ );
+
+ QueryBuilder.plugins[plugin].fct.call(this, this.plugins[plugin]);
+ }
+ else {
+ Utils.error('Config', 'Unable to find plugin "{0}"', plugin);
+ }
+ }, this);
+};
+
+/**
+ * Returns the config of a plugin, if the plugin is not loaded, returns the default config.
+ * @param {string} name
+ * @param {string} [property]
+ * @throws ConfigError
+ * @returns {*}
+ */
+QueryBuilder.prototype.getPluginOptions = function(name, property) {
+ var plugin;
+ if (this.plugins && this.plugins[name]) {
+ plugin = this.plugins[name];
+ }
+ else if (QueryBuilder.plugins[name]) {
+ plugin = QueryBuilder.plugins[name].def;
+ }
+
+ if (plugin) {
+ if (property) {
+ return plugin[property];
+ }
+ else {
+ return plugin;
+ }
+ }
+ else {
+ Utils.error('Config', 'Unable to find plugin "{0}"', name);
+ }
+};
+
+
+/**
+ * Final initialisation of the builder
+ * @param {object} [rules]
+ * @fires QueryBuilder.afterInit
+ * @private
+ */
+QueryBuilder.prototype.init = function(rules) {
+ /**
+ * When the initilization is done, just before creating the root group
+ * @event afterInit
+ * @memberof QueryBuilder
+ */
+ this.trigger('afterInit');
+
+ if (rules) {
+ this.setRules(rules);
+ delete this.settings.rules;
+ }
+ else {
+ this.setRoot(true);
+ }
+};
+
+/**
+ * Checks the configuration of each filter
+ * @param {QueryBuilder.Filter[]} filters
+ * @returns {QueryBuilder.Filter[]}
+ * @throws ConfigError
+ */
+QueryBuilder.prototype.checkFilters = function(filters) {
+ var definedFilters = [];
+
+ if (!filters || filters.length === 0) {
+ Utils.error('Config', 'Missing filters list');
+ }
+
+ filters.forEach(function(filter, i) {
+ if (!filter.id) {
+ Utils.error('Config', 'Missing filter {0} id', i);
+ }
+ if (definedFilters.indexOf(filter.id) != -1) {
+ Utils.error('Config', 'Filter "{0}" already defined', filter.id);
+ }
+ definedFilters.push(filter.id);
+
+ if (!filter.type) {
+ filter.type = 'string';
+ }
+ else if (!QueryBuilder.types[filter.type]) {
+ Utils.error('Config', 'Invalid type "{0}"', filter.type);
+ }
+
+ if (!filter.input) {
+ filter.input = QueryBuilder.types[filter.type] === 'number' ? 'number' : 'text';
+ }
+ else if (typeof filter.input != 'function' && QueryBuilder.inputs.indexOf(filter.input) == -1) {
+ Utils.error('Config', 'Invalid input "{0}"', filter.input);
+ }
+
+ if (filter.operators) {
+ filter.operators.forEach(function(operator) {
+ if (typeof operator != 'string') {
+ Utils.error('Config', 'Filter operators must be global operators types (string)');
+ }
+ });
+ }
+
+ if (!filter.field) {
+ filter.field = filter.id;
+ }
+ if (!filter.label) {
+ filter.label = filter.field;
+ }
+
+ if (!filter.optgroup) {
+ filter.optgroup = null;
+ }
+ else {
+ this.status.has_optgroup = true;
+
+ // register optgroup if needed
+ if (!this.settings.optgroups[filter.optgroup]) {
+ this.settings.optgroups[filter.optgroup] = filter.optgroup;
+ }
+ }
+
+ switch (filter.input) {
+ case 'radio':
+ case 'checkbox':
+ if (!filter.values || filter.values.length < 1) {
+ Utils.error('Config', 'Missing filter "{0}" values', filter.id);
+ }
+ break;
+
+ case 'select':
+ var cleanValues = [];
+ filter.has_optgroup = false;
+
+ Utils.iterateOptions(filter.values, function(value, label, optgroup) {
+ cleanValues.push({
+ value: value,
+ label: label,
+ optgroup: optgroup || null
+ });
+
+ if (optgroup) {
+ filter.has_optgroup = true;
+
+ // register optgroup if needed
+ if (!this.settings.optgroups[optgroup]) {
+ this.settings.optgroups[optgroup] = optgroup;
+ }
+ }
+ }.bind(this));
+
+ if (filter.has_optgroup) {
+ filter.values = Utils.groupSort(cleanValues, 'optgroup');
+ }
+ else {
+ filter.values = cleanValues;
+ }
+
+ if (filter.placeholder) {
+ if (filter.placeholder_value === undefined) {
+ filter.placeholder_value = -1;
+ }
+
+ filter.values.forEach(function(entry) {
+ if (entry.value == filter.placeholder_value) {
+ Utils.error('Config', 'Placeholder of filter "{0}" overlaps with one of its values', filter.id);
+ }
+ });
+ }
+ break;
+ }
+ }, this);
+
+ if (this.settings.sort_filters) {
+ if (typeof this.settings.sort_filters == 'function') {
+ filters.sort(this.settings.sort_filters);
+ }
+ else {
+ var self = this;
+ filters.sort(function(a, b) {
+ return self.translate(a.label).localeCompare(self.translate(b.label));
+ });
+ }
+ }
+
+ if (this.status.has_optgroup) {
+ filters = Utils.groupSort(filters, 'optgroup');
+ }
+
+ return filters;
+};
+
+/**
+ * Checks the configuration of each operator
+ * @param {QueryBuilder.Operator[]} operators
+ * @returns {QueryBuilder.Operator[]}
+ * @throws ConfigError
+ */
+QueryBuilder.prototype.checkOperators = function(operators) {
+ var definedOperators = [];
+
+ operators.forEach(function(operator, i) {
+ if (typeof operator == 'string') {
+ if (!QueryBuilder.OPERATORS[operator]) {
+ Utils.error('Config', 'Unknown operator "{0}"', operator);
+ }
+
+ operators[i] = operator = $.extendext(true, 'replace', {}, QueryBuilder.OPERATORS[operator]);
+ }
+ else {
+ if (!operator.type) {
+ Utils.error('Config', 'Missing "type" for operator {0}', i);
+ }
+
+ if (QueryBuilder.OPERATORS[operator.type]) {
+ operators[i] = operator = $.extendext(true, 'replace', {}, QueryBuilder.OPERATORS[operator.type], operator);
+ }
+
+ if (operator.nb_inputs === undefined || operator.apply_to === undefined) {
+ Utils.error('Config', 'Missing "nb_inputs" and/or "apply_to" for operator "{0}"', operator.type);
+ }
+ }
+
+ if (definedOperators.indexOf(operator.type) != -1) {
+ Utils.error('Config', 'Operator "{0}" already defined', operator.type);
+ }
+ definedOperators.push(operator.type);
+
+ if (!operator.optgroup) {
+ operator.optgroup = null;
+ }
+ else {
+ this.status.has_operator_optgroup = true;
+
+ // register optgroup if needed
+ if (!this.settings.optgroups[operator.optgroup]) {
+ this.settings.optgroups[operator.optgroup] = operator.optgroup;
+ }
+ }
+ }, this);
+
+ if (this.status.has_operator_optgroup) {
+ operators = Utils.groupSort(operators, 'optgroup');
+ }
+
+ return operators;
+};
+
+/**
+ * Adds all events listeners to the builder
+ * @private
+ */
+QueryBuilder.prototype.bindEvents = function() {
+ var self = this;
+ var Selectors = QueryBuilder.selectors;
+
+ // group condition change
+ this.$el.on('change.queryBuilder', Selectors.group_condition, function() {
+ if ($(this).is(':checked')) {
+ var $group = $(this).closest(Selectors.group_container);
+ self.getModel($group).condition = $(this).val();
+ }
+ });
+
+ // rule filter change
+ this.$el.on('change.queryBuilder', Selectors.rule_filter, function() {
+ var $rule = $(this).closest(Selectors.rule_container);
+ self.getModel($rule).filter = self.getFilterById($(this).val());
+ });
+
+ // rule operator change
+ this.$el.on('change.queryBuilder', Selectors.rule_operator, function() {
+ var $rule = $(this).closest(Selectors.rule_container);
+ self.getModel($rule).operator = self.getOperatorByType($(this).val());
+ });
+
+ // add rule button
+ this.$el.on('click.queryBuilder', Selectors.add_rule, function() {
+ var $group = $(this).closest(Selectors.group_container);
+ self.addRule(self.getModel($group));
+ });
+
+ // delete rule button
+ this.$el.on('click.queryBuilder', Selectors.delete_rule, function() {
+ var $rule = $(this).closest(Selectors.rule_container);
+ self.deleteRule(self.getModel($rule));
+ });
+
+ if (this.settings.allow_groups !== 0) {
+ // add group button
+ this.$el.on('click.queryBuilder', Selectors.add_group, function() {
+ var $group = $(this).closest(Selectors.group_container);
+ self.addGroup(self.getModel($group));
+ });
+
+ // delete group button
+ this.$el.on('click.queryBuilder', Selectors.delete_group, function() {
+ var $group = $(this).closest(Selectors.group_container);
+ self.deleteGroup(self.getModel($group));
+ });
+ }
+
+ // model events
+ this.model.on({
+ 'drop': function(e, node) {
+ node.$el.remove();
+ self.refreshGroupsConditions();
+ },
+ 'add': function(e, parent, node, index) {
+ if (index === 0) {
+ node.$el.prependTo(parent.$el.find('>' + QueryBuilder.selectors.rules_list));
+ }
+ else {
+ node.$el.insertAfter(parent.rules[index - 1].$el);
+ }
+ self.refreshGroupsConditions();
+ },
+ 'move': function(e, node, group, index) {
+ node.$el.detach();
+
+ if (index === 0) {
+ node.$el.prependTo(group.$el.find('>' + QueryBuilder.selectors.rules_list));
+ }
+ else {
+ node.$el.insertAfter(group.rules[index - 1].$el);
+ }
+ self.refreshGroupsConditions();
+ },
+ 'update': function(e, node, field, value, oldValue) {
+ if (node instanceof Rule) {
+ switch (field) {
+ case 'error':
+ self.updateError(node);
+ break;
+
+ case 'flags':
+ self.applyRuleFlags(node);
+ break;
+
+ case 'filter':
+ self.updateRuleFilter(node, oldValue);
+ break;
+
+ case 'operator':
+ self.updateRuleOperator(node, oldValue);
+ break;
+
+ case 'value':
+ self.updateRuleValue(node, oldValue);
+ break;
+ }
+ }
+ else {
+ switch (field) {
+ case 'error':
+ self.updateError(node);
+ break;
+
+ case 'flags':
+ self.applyGroupFlags(node);
+ break;
+
+ case 'condition':
+ self.updateGroupCondition(node, oldValue);
+ break;
+ }
+ }
+ }
+ });
+};
+
+/**
+ * Creates the root group
+ * @param {boolean} [addRule=true] - adds a default empty rule
+ * @param {object} [data] - group custom data
+ * @param {object} [flags] - flags to apply to the group
+ * @returns {Group} root group
+ * @fires QueryBuilder.afterAddGroup
+ */
+QueryBuilder.prototype.setRoot = function(addRule, data, flags) {
+ addRule = (addRule === undefined || addRule === true);
+
+ var group_id = this.nextGroupId();
+ var $group = $(this.getGroupTemplate(group_id, 1));
+
+ this.$el.append($group);
+ this.model.root = new Group(null, $group);
+ this.model.root.model = this.model;
+
+ this.model.root.data = data;
+ this.model.root.flags = $.extend({}, this.settings.default_group_flags, flags);
+ this.model.root.condition = this.settings.default_condition;
+
+ this.trigger('afterAddGroup', this.model.root);
+
+ if (addRule) {
+ this.addRule(this.model.root);
+ }
+
+ return this.model.root;
+};
+
+/**
+ * Adds a new group
+ * @param {Group} parent
+ * @param {boolean} [addRule=true] - adds a default empty rule
+ * @param {object} [data] - group custom data
+ * @param {object} [flags] - flags to apply to the group
+ * @returns {Group}
+ * @fires QueryBuilder.beforeAddGroup
+ * @fires QueryBuilder.afterAddGroup
+ */
+QueryBuilder.prototype.addGroup = function(parent, addRule, data, flags) {
+ addRule = (addRule === undefined || addRule === true);
+
+ var level = parent.level + 1;
+
+ /**
+ * Just before adding a group, can be prevented.
+ * @event beforeAddGroup
+ * @memberof QueryBuilder
+ * @param {Group} parent
+ * @param {boolean} addRule - if an empty rule will be added in the group
+ * @param {int} level - nesting level of the group, 1 is the root group
+ */
+ var e = this.trigger('beforeAddGroup', parent, addRule, level);
+ if (e.isDefaultPrevented()) {
+ return null;
+ }
+
+ var group_id = this.nextGroupId();
+ var $group = $(this.getGroupTemplate(group_id, level));
+ var model = parent.addGroup($group);
+
+ model.data = data;
+ model.flags = $.extend({}, this.settings.default_group_flags, flags);
+ model.condition = this.settings.default_condition;
+
+ /**
+ * Just after adding a group
+ * @event afterAddGroup
+ * @memberof QueryBuilder
+ * @param {Group} group
+ */
+ this.trigger('afterAddGroup', model);
+
+ /**
+ * After any change in the rules
+ * @event rulesChanged
+ * @memberof QueryBuilder
+ */
+ this.trigger('rulesChanged');
+
+ if (addRule) {
+ this.addRule(model);
+ }
+
+ return model;
+};
+
+/**
+ * Tries to delete a group. The group is not deleted if at least one rule is flagged `no_delete`.
+ * @param {Group} group
+ * @returns {boolean} if the group has been deleted
+ * @fires QueryBuilder.beforeDeleteGroup
+ * @fires QueryBuilder.afterDeleteGroup
+ */
+QueryBuilder.prototype.deleteGroup = function(group) {
+ if (group.isRoot()) {
+ return false;
+ }
+
+ /**
+ * Just before deleting a group, can be prevented
+ * @event beforeDeleteGroup
+ * @memberof QueryBuilder
+ * @param {Group} parent
+ */
+ var e = this.trigger('beforeDeleteGroup', group);
+ if (e.isDefaultPrevented()) {
+ return false;
+ }
+
+ var del = true;
+
+ group.each('reverse', function(rule) {
+ del &= this.deleteRule(rule);
+ }, function(group) {
+ del &= this.deleteGroup(group);
+ }, this);
+
+ if (del) {
+ group.drop();
+
+ /**
+ * Just after deleting a group
+ * @event afterDeleteGroup
+ * @memberof QueryBuilder
+ */
+ this.trigger('afterDeleteGroup');
+
+ this.trigger('rulesChanged');
+ }
+
+ return del;
+};
+
+/**
+ * Performs actions when a group's condition changes
+ * @param {Group} group
+ * @param {object} previousCondition
+ * @fires QueryBuilder.afterUpdateGroupCondition
+ * @private
+ */
+QueryBuilder.prototype.updateGroupCondition = function(group, previousCondition) {
+ group.$el.find('>' + QueryBuilder.selectors.group_condition).each(function() {
+ var $this = $(this);
+ $this.prop('checked', $this.val() === group.condition);
+ $this.parent().toggleClass('active', $this.val() === group.condition);
+ });
+
+ /**
+ * After the group condition has been modified
+ * @event afterUpdateGroupCondition
+ * @memberof QueryBuilder
+ * @param {Group} group
+ * @param {object} previousCondition
+ */
+ this.trigger('afterUpdateGroupCondition', group, previousCondition);
+
+ this.trigger('rulesChanged');
+};
+
+/**
+ * Updates the visibility of conditions based on number of rules inside each group
+ * @private
+ */
+QueryBuilder.prototype.refreshGroupsConditions = function() {
+ (function walk(group) {
+ if (!group.flags || (group.flags && !group.flags.condition_readonly)) {
+ group.$el.find('>' + QueryBuilder.selectors.group_condition).prop('disabled', group.rules.length <= 1)
+ .parent().toggleClass('disabled', group.rules.length <= 1);
+ }
+
+ group.each(null, function(group) {
+ walk(group);
+ }, this);
+ }(this.model.root));
+};
+
+/**
+ * Adds a new rule
+ * @param {Group} parent
+ * @param {object} [data] - rule custom data
+ * @param {object} [flags] - flags to apply to the rule
+ * @returns {Rule}
+ * @fires QueryBuilder.beforeAddRule
+ * @fires QueryBuilder.afterAddRule
+ * @fires QueryBuilder.changer:getDefaultFilter
+ */
+QueryBuilder.prototype.addRule = function(parent, data, flags) {
+ /**
+ * Just before adding a rule, can be prevented
+ * @event beforeAddRule
+ * @memberof QueryBuilder
+ * @param {Group} parent
+ */
+ var e = this.trigger('beforeAddRule', parent);
+ if (e.isDefaultPrevented()) {
+ return null;
+ }
+
+ var rule_id = this.nextRuleId();
+ var $rule = $(this.getRuleTemplate(rule_id));
+ var model = parent.addRule($rule);
+
+ model.data = data;
+ model.flags = $.extend({}, this.settings.default_rule_flags, flags);
+
+ /**
+ * Just after adding a rule
+ * @event afterAddRule
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ */
+ this.trigger('afterAddRule', model);
+
+ this.trigger('rulesChanged');
+
+ this.createRuleFilters(model);
+
+ if (this.settings.default_filter || !this.settings.display_empty_filter) {
+ /**
+ * Modifies the default filter for a rule
+ * @event changer:getDefaultFilter
+ * @memberof QueryBuilder
+ * @param {QueryBuilder.Filter} filter
+ * @param {Rule} rule
+ * @returns {QueryBuilder.Filter}
+ */
+ model.filter = this.change('getDefaultFilter',
+ this.getFilterById(this.settings.default_filter || this.filters[0].id),
+ model
+ );
+ }
+
+ return model;
+};
+
+/**
+ * Tries to delete a rule
+ * @param {Rule} rule
+ * @returns {boolean} if the rule has been deleted
+ * @fires QueryBuilder.beforeDeleteRule
+ * @fires QueryBuilder.afterDeleteRule
+ */
+QueryBuilder.prototype.deleteRule = function(rule) {
+ if (rule.flags.no_delete) {
+ return false;
+ }
+
+ /**
+ * Just before deleting a rule, can be prevented
+ * @event beforeDeleteRule
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ */
+ var e = this.trigger('beforeDeleteRule', rule);
+ if (e.isDefaultPrevented()) {
+ return false;
+ }
+
+ rule.drop();
+
+ /**
+ * Just after deleting a rule
+ * @event afterDeleteRule
+ * @memberof QueryBuilder
+ */
+ this.trigger('afterDeleteRule');
+
+ this.trigger('rulesChanged');
+
+ return true;
+};
+
+/**
+ * Creates the filters for a rule
+ * @param {Rule} rule
+ * @fires QueryBuilder.changer:getRuleFilters
+ * @fires QueryBuilder.afterCreateRuleFilters
+ * @private
+ */
+QueryBuilder.prototype.createRuleFilters = function(rule) {
+ /**
+ * Modifies the list a filters available for a rule
+ * @event changer:getRuleFilters
+ * @memberof QueryBuilder
+ * @param {QueryBuilder.Filter[]} filters
+ * @param {Rule} rule
+ * @returns {QueryBuilder.Filter[]}
+ */
+ var filters = this.change('getRuleFilters', this.filters, rule);
+ var $filterSelect = $(this.getRuleFilterSelect(rule, filters));
+
+ rule.$el.find(QueryBuilder.selectors.filter_container).html($filterSelect);
+
+ /**
+ * After creating the dropdown for filters
+ * @event afterCreateRuleFilters
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ */
+ this.trigger('afterCreateRuleFilters', rule);
+
+ this.applyRuleFlags(rule);
+};
+
+/**
+ * Creates the operators for a rule and init the rule operator
+ * @param {Rule} rule
+ * @fires QueryBuilder.afterCreateRuleOperators
+ * @private
+ */
+QueryBuilder.prototype.createRuleOperators = function(rule) {
+ var $operatorContainer = rule.$el.find(QueryBuilder.selectors.operator_container).empty();
+
+ if (!rule.filter) {
+ return;
+ }
+
+ var operators = this.getOperators(rule.filter);
+ var $operatorSelect = $(this.getRuleOperatorSelect(rule, operators));
+
+ $operatorContainer.html($operatorSelect);
+
+ // set the operator without triggering update event
+ if (rule.filter.default_operator) {
+ rule.__.operator = this.getOperatorByType(rule.filter.default_operator);
+ }
+ else {
+ rule.__.operator = operators[0];
+ }
+
+ rule.$el.find(QueryBuilder.selectors.rule_operator).val(rule.operator.type);
+
+ /**
+ * After creating the dropdown for operators
+ * @event afterCreateRuleOperators
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ * @param {QueryBuilder.Operator[]} operators - allowed operators for this rule
+ */
+ this.trigger('afterCreateRuleOperators', rule, operators);
+
+ this.applyRuleFlags(rule);
+};
+
+/**
+ * Creates the main input for a rule
+ * @param {Rule} rule
+ * @fires QueryBuilder.afterCreateRuleInput
+ * @private
+ */
+QueryBuilder.prototype.createRuleInput = function(rule) {
+ var $valueContainer = rule.$el.find(QueryBuilder.selectors.value_container).empty();
+
+ rule.__.value = undefined;
+
+ if (!rule.filter || !rule.operator || rule.operator.nb_inputs === 0) {
+ return;
+ }
+
+ var self = this;
+ var $inputs = $();
+ var filter = rule.filter;
+
+ for (var i = 0; i < rule.operator.nb_inputs; i++) {
+ var $ruleInput = $(this.getRuleInput(rule, i));
+ if (i > 0) $valueContainer.append(this.settings.inputs_separator);
+ $valueContainer.append($ruleInput);
+ $inputs = $inputs.add($ruleInput);
+ }
+
+ $valueContainer.css('display', '');
+
+ $inputs.on('change ' + (filter.input_event || ''), function() {
+ if (!rule._updating_input) {
+ rule._updating_value = true;
+ rule.value = self.getRuleInputValue(rule);
+ rule._updating_value = false;
+ }
+ });
+
+ if (filter.plugin) {
+ $inputs[filter.plugin](filter.plugin_config || {});
+ }
+
+ /**
+ * After creating the input for a rule and initializing optional plugin
+ * @event afterCreateRuleInput
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ */
+ this.trigger('afterCreateRuleInput', rule);
+
+ if (filter.default_value !== undefined) {
+ rule.value = filter.default_value;
+ }
+ else {
+ rule._updating_value = true;
+ rule.value = self.getRuleInputValue(rule);
+ rule._updating_value = false;
+ }
+
+ this.applyRuleFlags(rule);
+};
+
+/**
+ * Performs action when a rule's filter changes
+ * @param {Rule} rule
+ * @param {object} previousFilter
+ * @fires QueryBuilder.afterUpdateRuleFilter
+ * @private
+ */
+QueryBuilder.prototype.updateRuleFilter = function(rule, previousFilter) {
+ this.createRuleOperators(rule);
+ this.createRuleInput(rule);
+
+ rule.$el.find(QueryBuilder.selectors.rule_filter).val(rule.filter ? rule.filter.id : '-1');
+
+ // clear rule data if the filter changed
+ if (previousFilter && rule.filter && previousFilter.id !== rule.filter.id) {
+ rule.data = undefined;
+ }
+
+ /**
+ * After the filter has been updated and the operators and input re-created
+ * @event afterUpdateRuleFilter
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ * @param {object} previousFilter
+ */
+ this.trigger('afterUpdateRuleFilter', rule, previousFilter);
+
+ this.trigger('rulesChanged');
+};
+
+/**
+ * Performs actions when a rule's operator changes
+ * @param {Rule} rule
+ * @param {object} previousOperator
+ * @fires QueryBuilder.afterUpdateRuleOperator
+ * @private
+ */
+QueryBuilder.prototype.updateRuleOperator = function(rule, previousOperator) {
+ var $valueContainer = rule.$el.find(QueryBuilder.selectors.value_container);
+
+ if (!rule.operator || rule.operator.nb_inputs === 0) {
+ $valueContainer.hide();
+
+ rule.__.value = undefined;
+ }
+ else {
+ $valueContainer.css('display', '');
+
+ if ($valueContainer.is(':empty') || !previousOperator ||
+ rule.operator.nb_inputs !== previousOperator.nb_inputs ||
+ rule.operator.optgroup !== previousOperator.optgroup
+ ) {
+ this.createRuleInput(rule);
+ }
+ }
+
+ if (rule.operator) {
+ rule.$el.find(QueryBuilder.selectors.rule_operator).val(rule.operator.type);
+
+ // refresh value if the format changed for this operator
+ rule.__.value = this.getRuleInputValue(rule);
+ }
+
+ /**
+ * After the operator has been updated and the input optionally re-created
+ * @event afterUpdateRuleOperator
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ * @param {object} previousOperator
+ */
+ this.trigger('afterUpdateRuleOperator', rule, previousOperator);
+
+ this.trigger('rulesChanged');
+};
+
+/**
+ * Performs actions when rule's value changes
+ * @param {Rule} rule
+ * @param {object} previousValue
+ * @fires QueryBuilder.afterUpdateRuleValue
+ * @private
+ */
+QueryBuilder.prototype.updateRuleValue = function(rule, previousValue) {
+ if (!rule._updating_value) {
+ this.setRuleInputValue(rule, rule.value);
+ }
+
+ /**
+ * After the rule value has been modified
+ * @event afterUpdateRuleValue
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ * @param {*} previousValue
+ */
+ this.trigger('afterUpdateRuleValue', rule, previousValue);
+
+ this.trigger('rulesChanged');
+};
+
+/**
+ * Changes a rule's properties depending on its flags
+ * @param {Rule} rule
+ * @fires QueryBuilder.afterApplyRuleFlags
+ * @private
+ */
+QueryBuilder.prototype.applyRuleFlags = function(rule) {
+ var flags = rule.flags;
+ var Selectors = QueryBuilder.selectors;
+
+ rule.$el.find(Selectors.rule_filter).prop('disabled', flags.filter_readonly);
+ rule.$el.find(Selectors.rule_operator).prop('disabled', flags.operator_readonly);
+ rule.$el.find(Selectors.rule_value).prop('disabled', flags.value_readonly);
+
+ if (flags.no_delete) {
+ rule.$el.find(Selectors.delete_rule).remove();
+ }
+
+ /**
+ * After rule's flags has been applied
+ * @event afterApplyRuleFlags
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ */
+ this.trigger('afterApplyRuleFlags', rule);
+};
+
+/**
+ * Changes group's properties depending on its flags
+ * @param {Group} group
+ * @fires QueryBuilder.afterApplyGroupFlags
+ * @private
+ */
+QueryBuilder.prototype.applyGroupFlags = function(group) {
+ var flags = group.flags;
+ var Selectors = QueryBuilder.selectors;
+
+ group.$el.find('>' + Selectors.group_condition).prop('disabled', flags.condition_readonly)
+ .parent().toggleClass('readonly', flags.condition_readonly);
+
+ if (flags.no_add_rule) {
+ group.$el.find(Selectors.add_rule).remove();
+ }
+ if (flags.no_add_group) {
+ group.$el.find(Selectors.add_group).remove();
+ }
+ if (flags.no_delete) {
+ group.$el.find(Selectors.delete_group).remove();
+ }
+
+ /**
+ * After group's flags has been applied
+ * @event afterApplyGroupFlags
+ * @memberof QueryBuilder
+ * @param {Group} group
+ */
+ this.trigger('afterApplyGroupFlags', group);
+};
+
+/**
+ * Clears all errors markers
+ * @param {Node} [node] default is root Group
+ */
+QueryBuilder.prototype.clearErrors = function(node) {
+ node = node || this.model.root;
+
+ if (!node) {
+ return;
+ }
+
+ node.error = null;
+
+ if (node instanceof Group) {
+ node.each(function(rule) {
+ rule.error = null;
+ }, function(group) {
+ this.clearErrors(group);
+ }, this);
+ }
+};
+
+/**
+ * Adds/Removes error on a Rule or Group
+ * @param {Node} node
+ * @fires QueryBuilder.changer:displayError
+ * @private
+ */
+QueryBuilder.prototype.updateError = function(node) {
+ if (this.settings.display_errors) {
+ if (node.error === null) {
+ node.$el.removeClass('has-error');
+ }
+ else {
+ var errorMessage = this.translate('errors', node.error[0]);
+ errorMessage = Utils.fmt(errorMessage, node.error.slice(1));
+
+ /**
+ * Modifies an error message before display
+ * @event changer:displayError
+ * @memberof QueryBuilder
+ * @param {string} errorMessage - the error message (translated and formatted)
+ * @param {array} error - the raw error array (error code and optional arguments)
+ * @param {Node} node
+ * @returns {string}
+ */
+ errorMessage = this.change('displayError', errorMessage, node.error, node);
+
+ node.$el.addClass('has-error')
+ .find(QueryBuilder.selectors.error_container).eq(0)
+ .attr('title', errorMessage);
+ }
+ }
+};
+
+/**
+ * Triggers a validation error event
+ * @param {Node} node
+ * @param {string|array} error
+ * @param {*} value
+ * @fires QueryBuilder.validationError
+ * @private
+ */
+QueryBuilder.prototype.triggerValidationError = function(node, error, value) {
+ if (!$.isArray(error)) {
+ error = [error];
+ }
+
+ /**
+ * Fired when a validation error occurred, can be prevented
+ * @event validationError
+ * @memberof QueryBuilder
+ * @param {Node} node
+ * @param {string} error
+ * @param {*} value
+ */
+ var e = this.trigger('validationError', node, error, value);
+ if (!e.isDefaultPrevented()) {
+ node.error = error;
+ }
+};
+
+
+/**
+ * Destroys the builder
+ * @fires QueryBuilder.beforeDestroy
+ */
+QueryBuilder.prototype.destroy = function() {
+ /**
+ * Before the {@link QueryBuilder#destroy} method
+ * @event beforeDestroy
+ * @memberof QueryBuilder
+ */
+ this.trigger('beforeDestroy');
+
+ if (this.status.generated_id) {
+ this.$el.removeAttr('id');
+ }
+
+ this.clear();
+ this.model = null;
+
+ this.$el
+ .off('.queryBuilder')
+ .removeClass('query-builder')
+ .removeData('queryBuilder');
+
+ delete this.$el[0].queryBuilder;
+};
+
+/**
+ * Clear all rules and resets the root group
+ * @fires QueryBuilder.beforeReset
+ * @fires QueryBuilder.afterReset
+ */
+QueryBuilder.prototype.reset = function() {
+ /**
+ * Before the {@link QueryBuilder#reset} method, can be prevented
+ * @event beforeReset
+ * @memberof QueryBuilder
+ */
+ var e = this.trigger('beforeReset');
+ if (e.isDefaultPrevented()) {
+ return;
+ }
+
+ this.status.group_id = 1;
+ this.status.rule_id = 0;
+
+ this.model.root.empty();
+
+ this.model.root.data = undefined;
+ this.model.root.flags = $.extend({}, this.settings.default_group_flags);
+ this.model.root.condition = this.settings.default_condition;
+
+ this.addRule(this.model.root);
+
+ /**
+ * After the {@link QueryBuilder#reset} method
+ * @event afterReset
+ * @memberof QueryBuilder
+ */
+ this.trigger('afterReset');
+
+ this.trigger('rulesChanged');
+};
+
+/**
+ * Clears all rules and removes the root group
+ * @fires QueryBuilder.beforeClear
+ * @fires QueryBuilder.afterClear
+ */
+QueryBuilder.prototype.clear = function() {
+ /**
+ * Before the {@link QueryBuilder#clear} method, can be prevented
+ * @event beforeClear
+ * @memberof QueryBuilder
+ */
+ var e = this.trigger('beforeClear');
+ if (e.isDefaultPrevented()) {
+ return;
+ }
+
+ this.status.group_id = 0;
+ this.status.rule_id = 0;
+
+ if (this.model.root) {
+ this.model.root.drop();
+ this.model.root = null;
+ }
+
+ /**
+ * After the {@link QueryBuilder#clear} method
+ * @event afterClear
+ * @memberof QueryBuilder
+ */
+ this.trigger('afterClear');
+
+ this.trigger('rulesChanged');
+};
+
+/**
+ * Modifies the builder configuration.
+ * Only options defined in QueryBuilder.modifiable_options are modifiable
+ * @param {object} options
+ */
+QueryBuilder.prototype.setOptions = function(options) {
+ $.each(options, function(opt, value) {
+ if (QueryBuilder.modifiable_options.indexOf(opt) !== -1) {
+ this.settings[opt] = value;
+ }
+ }.bind(this));
+};
+
+/**
+ * Returns the model associated to a DOM object, or the root model
+ * @param {jQuery} [target]
+ * @returns {Node}
+ */
+QueryBuilder.prototype.getModel = function(target) {
+ if (!target) {
+ return this.model.root;
+ }
+ else if (target instanceof Node) {
+ return target;
+ }
+ else {
+ return $(target).data('queryBuilderModel');
+ }
+};
+
+/**
+ * Validates the whole builder
+ * @param {object} [options]
+ * @param {boolean} [options.skip_empty=false] - skips validating rules that have no filter selected
+ * @returns {boolean}
+ * @fires QueryBuilder.changer:validate
+ */
+QueryBuilder.prototype.validate = function(options) {
+ options = $.extend({
+ skip_empty: false
+ }, options);
+
+ this.clearErrors();
+
+ var self = this;
+
+ var valid = (function parse(group) {
+ var done = 0;
+ var errors = 0;
+
+ group.each(function(rule) {
+ if (!rule.filter && options.skip_empty) {
+ return;
+ }
+
+ if (!rule.filter) {
+ self.triggerValidationError(rule, 'no_filter', null);
+ errors++;
+ return;
+ }
+
+ if (!rule.operator) {
+ self.triggerValidationError(rule, 'no_operator', null);
+ errors++;
+ return;
+ }
+
+ if (rule.operator.nb_inputs !== 0) {
+ var valid = self.validateValue(rule, rule.value);
+
+ if (valid !== true) {
+ self.triggerValidationError(rule, valid, rule.value);
+ errors++;
+ return;
+ }
+ }
+
+ done++;
+
+ }, function(group) {
+ var res = parse(group);
+ if (res === true) {
+ done++;
+ }
+ else if (res === false) {
+ errors++;
+ }
+ });
+
+ if (errors > 0) {
+ return false;
+ }
+ else if (done === 0 && !group.isRoot() && options.skip_empty) {
+ return null;
+ }
+ else if (done === 0 && (!self.settings.allow_empty || !group.isRoot())) {
+ self.triggerValidationError(group, 'empty_group', null);
+ return false;
+ }
+
+ return true;
+
+ }(this.model.root));
+
+ /**
+ * Modifies the result of the {@link QueryBuilder#validate} method
+ * @event changer:validate
+ * @memberof QueryBuilder
+ * @param {boolean} valid
+ * @returns {boolean}
+ */
+ return this.change('validate', valid);
+};
+
+/**
+ * Gets an object representing current rules
+ * @param {object} [options]
+ * @param {boolean|string} [options.get_flags=false] - export flags, true: only changes from default flags or 'all'
+ * @param {boolean} [options.allow_invalid=false] - returns rules even if they are invalid
+ * @param {boolean} [options.skip_empty=false] - remove rules that have no filter selected
+ * @returns {object}
+ * @fires QueryBuilder.changer:ruleToJson
+ * @fires QueryBuilder.changer:groupToJson
+ * @fires QueryBuilder.changer:getRules
+ */
+QueryBuilder.prototype.getRules = function(options) {
+ options = $.extend({
+ get_flags: false,
+ allow_invalid: false,
+ skip_empty: false
+ }, options);
+
+ var valid = this.validate(options);
+ if (!valid && !options.allow_invalid) {
+ return null;
+ }
+
+ var self = this;
+
+ var out = (function parse(group) {
+ var groupData = {
+ condition: group.condition,
+ rules: []
+ };
+
+ if (group.data) {
+ groupData.data = $.extendext(true, 'replace', {}, group.data);
+ }
+
+ if (options.get_flags) {
+ var flags = self.getGroupFlags(group.flags, options.get_flags === 'all');
+ if (!$.isEmptyObject(flags)) {
+ groupData.flags = flags;
+ }
+ }
+
+ group.each(function(rule) {
+ if (!rule.filter && options.skip_empty) {
+ return;
+ }
+
+ var value = null;
+ if (!rule.operator || rule.operator.nb_inputs !== 0) {
+ value = rule.value;
+ }
+
+ var ruleData = {
+ id: rule.filter ? rule.filter.id : null,
+ field: rule.filter ? rule.filter.field : null,
+ type: rule.filter ? rule.filter.type : null,
+ input: rule.filter ? rule.filter.input : null,
+ operator: rule.operator ? rule.operator.type : null,
+ value: value
+ };
+
+ if (rule.filter && rule.filter.data || rule.data) {
+ ruleData.data = $.extendext(true, 'replace', {}, rule.filter.data, rule.data);
+ }
+
+ if (options.get_flags) {
+ var flags = self.getRuleFlags(rule.flags, options.get_flags === 'all');
+ if (!$.isEmptyObject(flags)) {
+ ruleData.flags = flags;
+ }
+ }
+
+ /**
+ * Modifies the JSON generated from a Rule object
+ * @event changer:ruleToJson
+ * @memberof QueryBuilder
+ * @param {object} json
+ * @param {Rule} rule
+ * @returns {object}
+ */
+ groupData.rules.push(self.change('ruleToJson', ruleData, rule));
+
+ }, function(model) {
+ var data = parse(model);
+ if (data.rules.length !== 0 || !options.skip_empty) {
+ groupData.rules.push(data);
+ }
+ }, this);
+
+ /**
+ * Modifies the JSON generated from a Group object
+ * @event changer:groupToJson
+ * @memberof QueryBuilder
+ * @param {object} json
+ * @param {Group} group
+ * @returns {object}
+ */
+ return self.change('groupToJson', groupData, group);
+
+ }(this.model.root));
+
+ out.valid = valid;
+
+ /**
+ * Modifies the result of the {@link QueryBuilder#getRules} method
+ * @event changer:getRules
+ * @memberof QueryBuilder
+ * @param {object} json
+ * @returns {object}
+ */
+ return this.change('getRules', out);
+};
+
+/**
+ * Sets rules from object
+ * @param {object} data
+ * @param {object} [options]
+ * @param {boolean} [options.allow_invalid=false] - silent-fail if the data are invalid
+ * @throws RulesError, UndefinedConditionError
+ * @fires QueryBuilder.changer:setRules
+ * @fires QueryBuilder.changer:jsonToRule
+ * @fires QueryBuilder.changer:jsonToGroup
+ * @fires QueryBuilder.afterSetRules
+ */
+QueryBuilder.prototype.setRules = function(data, options) {
+ options = $.extend({
+ allow_invalid: false
+ }, options);
+
+ if ($.isArray(data)) {
+ data = {
+ condition: this.settings.default_condition,
+ rules: data
+ };
+ }
+
+ if (!data || !data.rules || (data.rules.length === 0 && !this.settings.allow_empty)) {
+ Utils.error('RulesParse', 'Incorrect data object passed');
+ }
+
+ this.clear();
+ this.setRoot(false, data.data, this.parseGroupFlags(data));
+
+ /**
+ * Modifies data before the {@link QueryBuilder#setRules} method
+ * @event changer:setRules
+ * @memberof QueryBuilder
+ * @param {object} json
+ * @param {object} options
+ * @returns {object}
+ */
+ data = this.change('setRules', data, options);
+
+ var self = this;
+
+ (function add(data, group) {
+ if (group === null) {
+ return;
+ }
+
+ if (data.condition === undefined) {
+ data.condition = self.settings.default_condition;
+ }
+ else if (self.settings.conditions.indexOf(data.condition) == -1) {
+ Utils.error(!options.allow_invalid, 'UndefinedCondition', 'Invalid condition "{0}"', data.condition);
+ data.condition = self.settings.default_condition;
+ }
+
+ group.condition = data.condition;
+
+ data.rules.forEach(function(item) {
+ var model;
+
+ if (item.rules !== undefined) {
+ if (self.settings.allow_groups !== -1 && self.settings.allow_groups < group.level) {
+ Utils.error(!options.allow_invalid, 'RulesParse', 'No more than {0} groups are allowed', self.settings.allow_groups);
+ self.reset();
+ }
+ else {
+ model = self.addGroup(group, false, item.data, self.parseGroupFlags(item));
+ if (model === null) {
+ return;
+ }
+
+ add(item, model);
+ }
+ }
+ else {
+ if (!item.empty) {
+ if (item.id === undefined) {
+ Utils.error(!options.allow_invalid, 'RulesParse', 'Missing rule field id');
+ item.empty = true;
+ }
+ if (item.operator === undefined) {
+ item.operator = 'equal';
+ }
+ }
+
+ model = self.addRule(group, item.data, self.parseRuleFlags(item));
+ if (model === null) {
+ return;
+ }
+
+ if (!item.empty) {
+ model.filter = self.getFilterById(item.id, !options.allow_invalid);
+ }
+
+ if (model.filter) {
+ model.operator = self.getOperatorByType(item.operator, !options.allow_invalid);
+
+ if (!model.operator) {
+ model.operator = self.getOperators(model.filter)[0];
+ }
+ }
+
+ if (model.operator && model.operator.nb_inputs !== 0) {
+ if (item.value !== undefined) {
+ model.value = item.value;
+ }
+ else if (model.filter.default_value !== undefined) {
+ model.value = model.filter.default_value;
+ }
+ }
+
+ /**
+ * Modifies the Rule object generated from the JSON
+ * @event changer:jsonToRule
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ * @param {object} json
+ * @returns {Rule} the same rule
+ */
+ if (self.change('jsonToRule', model, item) != model) {
+ Utils.error('RulesParse', 'Plugin tried to change rule reference');
+ }
+ }
+ });
+
+ /**
+ * Modifies the Group object generated from the JSON
+ * @event changer:jsonToGroup
+ * @memberof QueryBuilder
+ * @param {Group} group
+ * @param {object} json
+ * @returns {Group} the same group
+ */
+ if (self.change('jsonToGroup', group, data) != group) {
+ Utils.error('RulesParse', 'Plugin tried to change group reference');
+ }
+
+ }(data, this.model.root));
+
+ /**
+ * After the {@link QueryBuilder#setRules} method
+ * @event afterSetRules
+ * @memberof QueryBuilder
+ */
+ this.trigger('afterSetRules');
+};
+
+
+/**
+ * Performs value validation
+ * @param {Rule} rule
+ * @param {string|string[]} value
+ * @returns {array|boolean} true or error array
+ * @fires QueryBuilder.changer:validateValue
+ */
+QueryBuilder.prototype.validateValue = function(rule, value) {
+ var validation = rule.filter.validation || {};
+ var result = true;
+
+ if (validation.callback) {
+ result = validation.callback.call(this, value, rule);
+ }
+ else {
+ result = this._validateValue(rule, value);
+ }
+
+ /**
+ * Modifies the result of the rule validation method
+ * @event changer:validateValue
+ * @memberof QueryBuilder
+ * @param {array|boolean} result - true or an error array
+ * @param {*} value
+ * @param {Rule} rule
+ * @returns {array|boolean}
+ */
+ return this.change('validateValue', result, value, rule);
+};
+
+/**
+ * Default validation function
+ * @param {Rule} rule
+ * @param {string|string[]} value
+ * @returns {array|boolean} true or error array
+ * @throws ConfigError
+ * @private
+ */
+QueryBuilder.prototype._validateValue = function(rule, value) {
+ var filter = rule.filter;
+ var operator = rule.operator;
+ var validation = filter.validation || {};
+ var result = true;
+ var tmp, tempValue;
+
+ if (rule.operator.nb_inputs === 1) {
+ value = [value];
+ }
+
+ for (var i = 0; i < operator.nb_inputs; i++) {
+ if (!operator.multiple && $.isArray(value[i]) && value[i].length > 1) {
+ result = ['operator_not_multiple', operator.type, this.translate('operators', operator.type)];
+ break;
+ }
+
+ switch (filter.input) {
+ case 'radio':
+ if (value[i] === undefined || value[i].length === 0) {
+ if (!validation.allow_empty_value) {
+ result = ['radio_empty'];
+ }
+ break;
+ }
+ break;
+
+ case 'checkbox':
+ if (value[i] === undefined || value[i].length === 0) {
+ if (!validation.allow_empty_value) {
+ result = ['checkbox_empty'];
+ }
+ break;
+ }
+ break;
+
+ case 'select':
+ if (value[i] === undefined || value[i].length === 0 || (filter.placeholder && value[i] == filter.placeholder_value)) {
+ if (!validation.allow_empty_value) {
+ result = ['select_empty'];
+ }
+ break;
+ }
+ break;
+
+ default:
+ tempValue = $.isArray(value[i]) ? value[i] : [value[i]];
+
+ for (var j = 0; j < tempValue.length; j++) {
+ switch (QueryBuilder.types[filter.type]) {
+ case 'string':
+ if (tempValue[j] === undefined || tempValue[j].length === 0) {
+ if (!validation.allow_empty_value) {
+ result = ['string_empty'];
+ }
+ break;
+ }
+ if (validation.min !== undefined) {
+ if (tempValue[j].length < parseInt(validation.min)) {
+ result = [this.getValidationMessage(validation, 'min', 'string_exceed_min_length'), validation.min];
+ break;
+ }
+ }
+ if (validation.max !== undefined) {
+ if (tempValue[j].length > parseInt(validation.max)) {
+ result = [this.getValidationMessage(validation, 'max', 'string_exceed_max_length'), validation.max];
+ break;
+ }
+ }
+ if (validation.format) {
+ if (typeof validation.format == 'string') {
+ validation.format = new RegExp(validation.format);
+ }
+ if (!validation.format.test(tempValue[j])) {
+ result = [this.getValidationMessage(validation, 'format', 'string_invalid_format'), validation.format];
+ break;
+ }
+ }
+ break;
+
+ case 'number':
+ if (tempValue[j] === undefined || tempValue[j].length === 0) {
+ if (!validation.allow_empty_value) {
+ result = ['number_nan'];
+ }
+ break;
+ }
+ if (isNaN(tempValue[j])) {
+ result = ['number_nan'];
+ break;
+ }
+ if (filter.type == 'integer') {
+ if (parseInt(tempValue[j]) != tempValue[j]) {
+ result = ['number_not_integer'];
+ break;
+ }
+ }
+ else {
+ if (parseFloat(tempValue[j]) != tempValue[j]) {
+ result = ['number_not_double'];
+ break;
+ }
+ }
+ if (validation.min !== undefined) {
+ if (tempValue[j] < parseFloat(validation.min)) {
+ result = [this.getValidationMessage(validation, 'min', 'number_exceed_min'), validation.min];
+ break;
+ }
+ }
+ if (validation.max !== undefined) {
+ if (tempValue[j] > parseFloat(validation.max)) {
+ result = [this.getValidationMessage(validation, 'max', 'number_exceed_max'), validation.max];
+ break;
+ }
+ }
+ if (validation.step !== undefined && validation.step !== 'any') {
+ var v = (tempValue[j] / validation.step).toPrecision(14);
+ if (parseInt(v) != v) {
+ result = [this.getValidationMessage(validation, 'step', 'number_wrong_step'), validation.step];
+ break;
+ }
+ }
+ break;
+
+ case 'datetime':
+ if (tempValue[j] === undefined || tempValue[j].length === 0) {
+ if (!validation.allow_empty_value) {
+ result = ['datetime_empty'];
+ }
+ break;
+ }
+
+ // we need MomentJS
+ if (validation.format) {
+ if (!('moment' in window)) {
+ Utils.error('MissingLibrary', 'MomentJS is required for Date/Time validation. Get it here http://momentjs.com');
+ }
+
+ var datetime = moment(tempValue[j], validation.format);
+ if (!datetime.isValid()) {
+ result = [this.getValidationMessage(validation, 'format', 'datetime_invalid'), validation.format];
+ break;
+ }
+ else {
+ if (validation.min) {
+ if (datetime < moment(validation.min, validation.format)) {
+ result = [this.getValidationMessage(validation, 'min', 'datetime_exceed_min'), validation.min];
+ break;
+ }
+ }
+ if (validation.max) {
+ if (datetime > moment(validation.max, validation.format)) {
+ result = [this.getValidationMessage(validation, 'max', 'datetime_exceed_max'), validation.max];
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case 'boolean':
+ if (tempValue[j] === undefined || tempValue[j].length === 0) {
+ if (!validation.allow_empty_value) {
+ result = ['boolean_not_valid'];
+ }
+ break;
+ }
+ tmp = ('' + tempValue[j]).trim().toLowerCase();
+ if (tmp !== 'true' && tmp !== 'false' && tmp !== '1' && tmp !== '0' && tempValue[j] !== 1 && tempValue[j] !== 0) {
+ result = ['boolean_not_valid'];
+ break;
+ }
+ }
+
+ if (result !== true) {
+ break;
+ }
+ }
+ }
+
+ if (result !== true) {
+ break;
+ }
+ }
+
+ if ((rule.operator.type === 'between' || rule.operator.type === 'not_between') && value.length === 2) {
+ switch (QueryBuilder.types[filter.type]) {
+ case 'number':
+ if (value[0] > value[1]) {
+ result = ['number_between_invalid', value[0], value[1]];
+ }
+ break;
+
+ case 'datetime':
+ // we need MomentJS
+ if (validation.format) {
+ if (!('moment' in window)) {
+ Utils.error('MissingLibrary', 'MomentJS is required for Date/Time validation. Get it here http://momentjs.com');
+ }
+
+ if (moment(value[0], validation.format).isAfter(moment(value[1], validation.format))) {
+ result = ['datetime_between_invalid', value[0], value[1]];
+ }
+ }
+ break;
+ }
+ }
+
+ return result;
+};
+
+/**
+ * Returns an incremented group ID
+ * @returns {string}
+ * @private
+ */
+QueryBuilder.prototype.nextGroupId = function() {
+ return this.status.id + '_group_' + (this.status.group_id++);
+};
+
+/**
+ * Returns an incremented rule ID
+ * @returns {string}
+ * @private
+ */
+QueryBuilder.prototype.nextRuleId = function() {
+ return this.status.id + '_rule_' + (this.status.rule_id++);
+};
+
+/**
+ * Returns the operators for a filter
+ * @param {string|object} filter - filter id or filter object
+ * @returns {object[]}
+ * @fires QueryBuilder.changer:getOperators
+ */
+QueryBuilder.prototype.getOperators = function(filter) {
+ if (typeof filter == 'string') {
+ filter = this.getFilterById(filter);
+ }
+
+ var result = [];
+
+ for (var i = 0, l = this.operators.length; i < l; i++) {
+ // filter operators check
+ if (filter.operators) {
+ if (filter.operators.indexOf(this.operators[i].type) == -1) {
+ continue;
+ }
+ }
+ // type check
+ else if (this.operators[i].apply_to.indexOf(QueryBuilder.types[filter.type]) == -1) {
+ continue;
+ }
+
+ result.push(this.operators[i]);
+ }
+
+ // keep sort order defined for the filter
+ if (filter.operators) {
+ result.sort(function(a, b) {
+ return filter.operators.indexOf(a.type) - filter.operators.indexOf(b.type);
+ });
+ }
+
+ /**
+ * Modifies the operators available for a filter
+ * @event changer:getOperators
+ * @memberof QueryBuilder
+ * @param {QueryBuilder.Operator[]} operators
+ * @param {QueryBuilder.Filter} filter
+ * @returns {QueryBuilder.Operator[]}
+ */
+ return this.change('getOperators', result, filter);
+};
+
+/**
+ * Returns a particular filter by its id
+ * @param {string} id
+ * @param {boolean} [doThrow=true]
+ * @returns {object|null}
+ * @throws UndefinedFilterError
+ */
+QueryBuilder.prototype.getFilterById = function(id, doThrow) {
+ if (id == '-1') {
+ return null;
+ }
+
+ for (var i = 0, l = this.filters.length; i < l; i++) {
+ if (this.filters[i].id == id) {
+ return this.filters[i];
+ }
+ }
+
+ Utils.error(doThrow !== false, 'UndefinedFilter', 'Undefined filter "{0}"', id);
+
+ return null;
+};
+
+/**
+ * Returns a particular operator by its type
+ * @param {string} type
+ * @param {boolean} [doThrow=true]
+ * @returns {object|null}
+ * @throws UndefinedOperatorError
+ */
+QueryBuilder.prototype.getOperatorByType = function(type, doThrow) {
+ if (type == '-1') {
+ return null;
+ }
+
+ for (var i = 0, l = this.operators.length; i < l; i++) {
+ if (this.operators[i].type == type) {
+ return this.operators[i];
+ }
+ }
+
+ Utils.error(doThrow !== false, 'UndefinedOperator', 'Undefined operator "{0}"', type);
+
+ return null;
+};
+
+/**
+ * Returns rule's current input value
+ * @param {Rule} rule
+ * @returns {*}
+ * @fires QueryBuilder.changer:getRuleValue
+ * @private
+ */
+QueryBuilder.prototype.getRuleInputValue = function(rule) {
+ var filter = rule.filter;
+ var operator = rule.operator;
+ var value = [];
+
+ if (filter.valueGetter) {
+ value = filter.valueGetter.call(this, rule);
+ }
+ else {
+ var $value = rule.$el.find(QueryBuilder.selectors.value_container);
+
+ for (var i = 0; i < operator.nb_inputs; i++) {
+ var name = Utils.escapeElementId(rule.id + '_value_' + i);
+ var tmp;
+
+ switch (filter.input) {
+ case 'radio':
+ value.push($value.find('[name=' + name + ']:checked').val());
+ break;
+
+ case 'checkbox':
+ tmp = [];
+ // jshint loopfunc:true
+ $value.find('[name=' + name + ']:checked').each(function() {
+ tmp.push($(this).val());
+ });
+ // jshint loopfunc:false
+ value.push(tmp);
+ break;
+
+ case 'select':
+ if (filter.multiple) {
+ tmp = [];
+ // jshint loopfunc:true
+ $value.find('[name=' + name + '] option:selected').each(function() {
+ tmp.push($(this).val());
+ });
+ // jshint loopfunc:false
+ value.push(tmp);
+ }
+ else {
+ value.push($value.find('[name=' + name + '] option:selected').val());
+ }
+ break;
+
+ default:
+ value.push($value.find('[name=' + name + ']').val());
+ }
+ }
+
+ value = value.map(function(val) {
+ if (operator.multiple && filter.value_separator && typeof val == 'string') {
+ val = val.split(filter.value_separator);
+ }
+
+ if ($.isArray(val)) {
+ return val.map(function(subval) {
+ return Utils.changeType(subval, filter.type);
+ });
+ }
+ else {
+ return Utils.changeType(val, filter.type);
+ }
+ });
+
+ if (operator.nb_inputs === 1) {
+ value = value[0];
+ }
+
+ // @deprecated
+ if (filter.valueParser) {
+ value = filter.valueParser.call(this, rule, value);
+ }
+ }
+
+ /**
+ * Modifies the rule's value grabbed from the DOM
+ * @event changer:getRuleValue
+ * @memberof QueryBuilder
+ * @param {*} value
+ * @param {Rule} rule
+ * @returns {*}
+ */
+ return this.change('getRuleValue', value, rule);
+};
+
+/**
+ * Sets the value of a rule's input
+ * @param {Rule} rule
+ * @param {*} value
+ * @private
+ */
+QueryBuilder.prototype.setRuleInputValue = function(rule, value) {
+ var filter = rule.filter;
+ var operator = rule.operator;
+
+ if (!filter || !operator) {
+ return;
+ }
+
+ rule._updating_input = true;
+
+ if (filter.valueSetter) {
+ filter.valueSetter.call(this, rule, value);
+ }
+ else {
+ var $value = rule.$el.find(QueryBuilder.selectors.value_container);
+
+ if (operator.nb_inputs == 1) {
+ value = [value];
+ }
+
+ for (var i = 0; i < operator.nb_inputs; i++) {
+ var name = Utils.escapeElementId(rule.id + '_value_' + i);
+
+ switch (filter.input) {
+ case 'radio':
+ $value.find('[name=' + name + '][value="' + value[i] + '"]').prop('checked', true).trigger('change');
+ break;
+
+ case 'checkbox':
+ if (!$.isArray(value[i])) {
+ value[i] = [value[i]];
+ }
+ // jshint loopfunc:true
+ value[i].forEach(function(value) {
+ $value.find('[name=' + name + '][value="' + value + '"]').prop('checked', true).trigger('change');
+ });
+ // jshint loopfunc:false
+ break;
+
+ default:
+ if (operator.multiple && filter.value_separator && $.isArray(value[i])) {
+ value[i] = value[i].join(filter.value_separator);
+ }
+ $value.find('[name=' + name + ']').val(value[i]).trigger('change');
+ break;
+ }
+ }
+ }
+
+ rule._updating_input = false;
+};
+
+/**
+ * Parses rule flags
+ * @param {object} rule
+ * @returns {object}
+ * @fires QueryBuilder.changer:parseRuleFlags
+ * @private
+ */
+QueryBuilder.prototype.parseRuleFlags = function(rule) {
+ var flags = $.extend({}, this.settings.default_rule_flags);
+
+ if (rule.readonly) {
+ $.extend(flags, {
+ filter_readonly: true,
+ operator_readonly: true,
+ value_readonly: true,
+ no_delete: true
+ });
+ }
+
+ if (rule.flags) {
+ $.extend(flags, rule.flags);
+ }
+
+ /**
+ * Modifies the consolidated rule's flags
+ * @event changer:parseRuleFlags
+ * @memberof QueryBuilder
+ * @param {object} flags
+ * @param {object} rule - not a Rule object
+ * @returns {object}
+ */
+ return this.change('parseRuleFlags', flags, rule);
+};
+
+/**
+ * Gets a copy of flags of a rule
+ * @param {object} flags
+ * @param {boolean} [all=false] - return all flags or only changes from default flags
+ * @returns {object}
+ * @private
+ */
+QueryBuilder.prototype.getRuleFlags = function(flags, all) {
+ if (all) {
+ return $.extend({}, flags);
+ }
+ else {
+ var ret = {};
+ $.each(this.settings.default_rule_flags, function(key, value) {
+ if (flags[key] !== value) {
+ ret[key] = flags[key];
+ }
+ });
+ return ret;
+ }
+};
+
+/**
+ * Parses group flags
+ * @param {object} group
+ * @returns {object}
+ * @fires QueryBuilder.changer:parseGroupFlags
+ * @private
+ */
+QueryBuilder.prototype.parseGroupFlags = function(group) {
+ var flags = $.extend({}, this.settings.default_group_flags);
+
+ if (group.readonly) {
+ $.extend(flags, {
+ condition_readonly: true,
+ no_add_rule: true,
+ no_add_group: true,
+ no_delete: true
+ });
+ }
+
+ if (group.flags) {
+ $.extend(flags, group.flags);
+ }
+
+ /**
+ * Modifies the consolidated group's flags
+ * @event changer:parseGroupFlags
+ * @memberof QueryBuilder
+ * @param {object} flags
+ * @param {object} group - not a Group object
+ * @returns {object}
+ */
+ return this.change('parseGroupFlags', flags, group);
+};
+
+/**
+ * Gets a copy of flags of a group
+ * @param {object} flags
+ * @param {boolean} [all=false] - return all flags or only changes from default flags
+ * @returns {object}
+ * @private
+ */
+QueryBuilder.prototype.getGroupFlags = function(flags, all) {
+ if (all) {
+ return $.extend({}, flags);
+ }
+ else {
+ var ret = {};
+ $.each(this.settings.default_group_flags, function(key, value) {
+ if (flags[key] !== value) {
+ ret[key] = flags[key];
+ }
+ });
+ return ret;
+ }
+};
+
+/**
+ * Translate a label either by looking in the `lang` object or in itself if it's an object where keys are language codes
+ * @param {string} [category]
+ * @param {string|object} key
+ * @returns {string}
+ * @fires QueryBuilder.changer:translate
+ */
+QueryBuilder.prototype.translate = function(category, key) {
+ if (!key) {
+ key = category;
+ category = undefined;
+ }
+
+ var translation;
+ if (typeof key === 'object') {
+ translation = key[this.settings.lang_code] || key['en'];
+ }
+ else {
+ translation = (category ? this.lang[category] : this.lang)[key] || key;
+ }
+
+ /**
+ * Modifies the translated label
+ * @event changer:translate
+ * @memberof QueryBuilder
+ * @param {string} translation
+ * @param {string|object} key
+ * @param {string} [category]
+ * @returns {string}
+ */
+ return this.change('translate', translation, key, category);
+};
+
+/**
+ * Returns a validation message
+ * @param {object} validation
+ * @param {string} type
+ * @param {string} def
+ * @returns {string}
+ * @private
+ */
+QueryBuilder.prototype.getValidationMessage = function(validation, type, def) {
+ return validation.messages && validation.messages[type] || def;
+};
+
+
+QueryBuilder.templates.group = '\
+';
+
+QueryBuilder.templates.rule = '\
+ \
+ \
+ {{? it.settings.display_errors }} \
+
\
+ {{?}} \
+
\
+
\
+
\
+
';
+
+QueryBuilder.templates.filterSelect = '\
+{{ var optgroup = null; }} \
+ \
+ {{? it.settings.display_empty_filter }} \
+ {{= it.settings.select_placeholder }} \
+ {{?}} \
+ {{~ it.filters: filter }} \
+ {{? optgroup !== filter.optgroup }} \
+ {{? optgroup !== null }}{{?}} \
+ {{? (optgroup = filter.optgroup) !== null }} \
+ \
+ {{?}} \
+ {{?}} \
+ {{= it.translate(filter.label) }} \
+ {{~}} \
+ {{? optgroup !== null }} {{?}} \
+ ';
+
+QueryBuilder.templates.operatorSelect = '\
+{{? it.operators.length === 1 }} \
+ \
+{{= it.translate("operators", it.operators[0].type) }} \
+ \
+{{?}} \
+{{ var optgroup = null; }} \
+ \
+ {{~ it.operators: operator }} \
+ {{? optgroup !== operator.optgroup }} \
+ {{? optgroup !== null }}{{?}} \
+ {{? (optgroup = operator.optgroup) !== null }} \
+ \
+ {{?}} \
+ {{?}} \
+ {{= it.translate("operators", operator.type) }} \
+ {{~}} \
+ {{? optgroup !== null }} {{?}} \
+ ';
+
+QueryBuilder.templates.ruleValueSelect = '\
+{{ var optgroup = null; }} \
+ \
+ {{? it.rule.filter.placeholder }} \
+ {{= it.rule.filter.placeholder }} \
+ {{?}} \
+ {{~ it.rule.filter.values: entry }} \
+ {{? optgroup !== entry.optgroup }} \
+ {{? optgroup !== null }}{{?}} \
+ {{? (optgroup = entry.optgroup) !== null }} \
+ \
+ {{?}} \
+ {{?}} \
+ {{= entry.label }} \
+ {{~}} \
+ {{? optgroup !== null }} {{?}} \
+ ';
+
+/**
+ * Returns group's HTML
+ * @param {string} group_id
+ * @param {int} level
+ * @returns {string}
+ * @fires QueryBuilder.changer:getGroupTemplate
+ * @private
+ */
+QueryBuilder.prototype.getGroupTemplate = function(group_id, level) {
+ var h = this.templates.group({
+ builder: this,
+ group_id: group_id,
+ level: level,
+ conditions: this.settings.conditions,
+ icons: this.icons,
+ settings: this.settings,
+ translate: this.translate.bind(this)
+ });
+
+ /**
+ * Modifies the raw HTML of a group
+ * @event changer:getGroupTemplate
+ * @memberof QueryBuilder
+ * @param {string} html
+ * @param {int} level
+ * @returns {string}
+ */
+ return this.change('getGroupTemplate', h, level);
+};
+
+/**
+ * Returns rule's HTML
+ * @param {string} rule_id
+ * @returns {string}
+ * @fires QueryBuilder.changer:getRuleTemplate
+ * @private
+ */
+QueryBuilder.prototype.getRuleTemplate = function(rule_id) {
+ var h = this.templates.rule({
+ builder: this,
+ rule_id: rule_id,
+ icons: this.icons,
+ settings: this.settings,
+ translate: this.translate.bind(this)
+ });
+
+ /**
+ * Modifies the raw HTML of a rule
+ * @event changer:getRuleTemplate
+ * @memberof QueryBuilder
+ * @param {string} html
+ * @returns {string}
+ */
+ return this.change('getRuleTemplate', h);
+};
+
+/**
+ * Returns rule's filter HTML
+ * @param {Rule} rule
+ * @param {object[]} filters
+ * @returns {string}
+ * @fires QueryBuilder.changer:getRuleFilterTemplate
+ * @private
+ */
+QueryBuilder.prototype.getRuleFilterSelect = function(rule, filters) {
+ var h = this.templates.filterSelect({
+ builder: this,
+ rule: rule,
+ filters: filters,
+ icons: this.icons,
+ settings: this.settings,
+ translate: this.translate.bind(this)
+ });
+
+ /**
+ * Modifies the raw HTML of the rule's filter dropdown
+ * @event changer:getRuleFilterSelect
+ * @memberof QueryBuilder
+ * @param {string} html
+ * @param {Rule} rule
+ * @param {QueryBuilder.Filter[]} filters
+ * @returns {string}
+ */
+ return this.change('getRuleFilterSelect', h, rule, filters);
+};
+
+/**
+ * Returns rule's operator HTML
+ * @param {Rule} rule
+ * @param {object[]} operators
+ * @returns {string}
+ * @fires QueryBuilder.changer:getRuleOperatorTemplate
+ * @private
+ */
+QueryBuilder.prototype.getRuleOperatorSelect = function(rule, operators) {
+ var h = this.templates.operatorSelect({
+ builder: this,
+ rule: rule,
+ operators: operators,
+ icons: this.icons,
+ settings: this.settings,
+ translate: this.translate.bind(this)
+ });
+
+ /**
+ * Modifies the raw HTML of the rule's operator dropdown
+ * @event changer:getRuleOperatorSelect
+ * @memberof QueryBuilder
+ * @param {string} html
+ * @param {Rule} rule
+ * @param {QueryBuilder.Operator[]} operators
+ * @returns {string}
+ */
+ return this.change('getRuleOperatorSelect', h, rule, operators);
+};
+
+/**
+ * Returns the rule's value select HTML
+ * @param {string} name
+ * @param {Rule} rule
+ * @returns {string}
+ * @fires QueryBuilder.changer:getRuleValueSelect
+ * @private
+ */
+QueryBuilder.prototype.getRuleValueSelect = function(name, rule) {
+ var h = this.templates.ruleValueSelect({
+ builder: this,
+ name: name,
+ rule: rule,
+ icons: this.icons,
+ settings: this.settings,
+ translate: this.translate.bind(this)
+ });
+
+ /**
+ * Modifies the raw HTML of the rule's value dropdown (in case of a "select filter)
+ * @event changer:getRuleValueSelect
+ * @memberof QueryBuilder
+ * @param {string} html
+ * @param [string} name
+ * @param {Rule} rule
+ * @returns {string}
+ */
+ return this.change('getRuleValueSelect', h, name, rule);
+};
+
+/**
+ * Returns the rule's value HTML
+ * @param {Rule} rule
+ * @param {int} value_id
+ * @returns {string}
+ * @fires QueryBuilder.changer:getRuleInput
+ * @private
+ */
+QueryBuilder.prototype.getRuleInput = function(rule, value_id) {
+ var filter = rule.filter;
+ var validation = rule.filter.validation || {};
+ var name = rule.id + '_value_' + value_id;
+ var c = filter.vertical ? ' class=block' : '';
+ var h = '';
+ var placeholder = Array.isArray(filter.placeholder) ? filter.placeholder[value_id] : filter.placeholder;
+
+ if (typeof filter.input == 'function') {
+ h = filter.input.call(this, rule, name);
+ }
+ else {
+ switch (filter.input) {
+ case 'radio':
+ case 'checkbox':
+ Utils.iterateOptions(filter.values, function(key, val) {
+ h += ' ' + val + ' ';
+ });
+ break;
+
+ case 'select':
+ h = this.getRuleValueSelect(name, rule);
+ break;
+
+ case 'textarea':
+ h += '" ; + break + + case number : + h +=' " ; + break + + default + h +=' " ; + } + } + + + * Modifies the raw HTML of the rule s input + * @event changer:getRuleInput + * @memberof QueryBuilder + * @param {string html + * @param {Rule rule + * @param {string name - the name that the input must have + * @returns {string + * + return this.change getRuleInput , h rule name + + + + + * @namespace + * +var Utils="{};" + + + * @member {object + * @memberof QueryBuilder + * @see Utils + * +QueryBuilder.utils="Utils;" + + + * @callback Utils#OptionsIteratee + * @param {string key + * @param {string value + * @param {string [optgroup + * + + + * Iterates over radio/checkbox/selection options it accept four formats + * + * @example + * array of values + * options="['one'," two , three ] + * @example + * simple key-value map + * options="{1:" one , 2 two , 3 three } + * @example + * array of 1-element maps + * options="[{1:" one } {2 two } {3 three } + * @example + * array of elements + * options="[{value:" 1 label one , optgroup group } {value 2 label two } + * + * @param {object|array options + * @param {Utils#OptionsIteratee tpl + * +Utils.iterateOptions="function(options," tpl { + if (options { + if ($.isArray(options { + options.forEach(function(entry { + if ($.isPlainObject(entry { + array of elements + if ( value in entry { + tpl(entry.value entry.label | entry.value entry.optgroup + } + array of one-element maps + else { + $.each(entry function(key val { + tpl(key val + return false break after first entry + } + } + } + array of values + else { + tpl(entry entry + } + } + } + unordered map + else { + $.each(options function(key val { + tpl(key val + } + } + } + + + + * Replaces {0 {1 . in a string + * @param {string str + * @param { args + * @returns {string + * +Utils.fmt="function(str," args { + if (!Array.isArray(args { + args="Array.prototype.slice.call(arguments," 1 + } + + return str.replace(/{([0-9]+)}/g function(m i { + return args[parseInt(i + } + + + + * Throws an Error object with custom name or logs an error + * @param {boolean [doThrow="true]" + * @param {string type + * @param {string message + * @param { args + * +Utils.error="function()" { + var i="0;" + var doThrow="typeof" arguments[i="==" boolean ? arguments[i : true + var type="arguments[i++];" + var message="arguments[i++];" + var args="Array.isArray(arguments[i])" ? arguments[i : Array.prototype.slice.call(arguments i + + if (doThrow { + var err="new" Error(Utils.fmt(message args + err.name="type" + Error ; + err.args="args;" + throw err + } + else { + console.error(type + Error + Utils.fmt(message args + } + + + + * Changes the type of a value to int float or bool + * @param { value + * @param {string type - integer , double , boolean or anything else (passthrough + * @returns { + * +Utils.changeType="function(value," type { + if (value="==" | value="==" undefined { + return undefined + } + + switch (type { + @formatter:off + case integer : + if (typeof value="==" string & !/^-?\d+$/.test(value { + return value + } + return parseInt(value + case double : + if (typeof value="==" string & !/^-?\d+\.?\d*$/.test(value { + return value + } + return parseFloat(value + case boolean : + if (typeof value="==" string & !/^(0|1|true|false){1}$/i.test(value { + return value + } + return value="==" true | value="==" 1 | value.toLowerCase="==" true | value="==" 1 ; + default return value + @formatter:on + } + + + + * Escapes a string like PHP s mysql_real_escape_string does + * @param {string value + * @returns {string + * +Utils.escapeString="function(value)" { + if (typeof value !="string" ) { + return value + } + + return value + .replace(/[\0\n\r\b \ ]/g function(s { + switch (s { + @formatter:off + case \0 : return \\0 ; + case \n : return \\n ; + case \r : return \\r ; + case \b : return \\b ; + default return \ + s + @formatter:off + } + } + uglify compliant + .replace(/\t/g \\t ) + .replace(/\x1a/g \\Z ) + + + + * Escapes a string for use in regex + * @param {string str + * @returns {string + * +Utils.escapeRegExp="function(str)" { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g \ ) + + + + * Escapes a string for use in HTML element id + * @param {string str + * @returns {string + * +Utils.escapeElementId="function(str)" { + Regex based on that suggested by + https://learn.jquery.com/using-jquery-core/faq/how-do-i-select-an-element-by-an-id-that-has-characters-used-in-css-notation + - escapes : . [ ] , + - avoids escaping already escaped values + return (str ? str.replace(/(\\)?([:.\[\],])/g + function $0 $1 $2 ) { return $1 ? $0 : \ + $2 } : str + + + + * Sorts objects by grouping them by `key preserving initial order when possible + * @param {object items + * @param {string key + * @returns {object + * +Utils.groupSort="function(items," key { + var optgroups="[];" + var newItems="[];" + + items.forEach(function(item { + var idx + + if (item[key { + idx="optgroups.lastIndexOf(item[key]);" + + if (idx="=" -1 { + idx="optgroups.length;" + } + else { + idx + } + } + else { + idx="optgroups.length;" + } + + optgroups.splice(idx 0 item[key + newItems.splice(idx 0 item + } + + return newItems + + + + * Defines properties on an Node prototype with getter and setter />
+ * Update events are emitted in the setter through root Model (if any).
+ * The object must have a `__` object, non enumerable property to store values.
+ * @param {function} obj
+ * @param {string[]} fields
+ */
+Utils.defineModelProperties = function(obj, fields) {
+ fields.forEach(function(field) {
+ Object.defineProperty(obj.prototype, field, {
+ enumerable: true,
+ get: function() {
+ return this.__[field];
+ },
+ set: function(value) {
+ var previousValue = (this.__[field] !== null && typeof this.__[field] == 'object') ?
+ $.extend({}, this.__[field]) :
+ this.__[field];
+
+ this.__[field] = value;
+
+ if (this.model !== null) {
+ /**
+ * After a value of the model changed
+ * @event model:update
+ * @memberof Model
+ * @param {Node} node
+ * @param {string} field
+ * @param {*} value
+ * @param {*} previousValue
+ */
+ this.model.trigger('update', this, field, value, previousValue);
+ }
+ }
+ });
+ });
+};
+
+
+/**
+ * Main object storing data model and emitting model events
+ * @constructor
+ */
+function Model() {
+ /**
+ * @member {Group}
+ * @readonly
+ */
+ this.root = null;
+
+ /**
+ * Base for event emitting
+ * @member {jQuery}
+ * @readonly
+ * @private
+ */
+ this.$ = $(this);
+}
+
+$.extend(Model.prototype, /** @lends Model.prototype */ {
+ /**
+ * Triggers an event on the model
+ * @param {string} type
+ * @returns {$.Event}
+ */
+ trigger: function(type) {
+ var event = new $.Event(type);
+ this.$.triggerHandler(event, Array.prototype.slice.call(arguments, 1));
+ return event;
+ },
+
+ /**
+ * Attaches an event listener on the model
+ * @param {string} type
+ * @param {function} cb
+ * @returns {Model}
+ */
+ on: function() {
+ this.$.on.apply(this.$, Array.prototype.slice.call(arguments));
+ return this;
+ },
+
+ /**
+ * Removes an event listener from the model
+ * @param {string} type
+ * @param {function} [cb]
+ * @returns {Model}
+ */
+ off: function() {
+ this.$.off.apply(this.$, Array.prototype.slice.call(arguments));
+ return this;
+ },
+
+ /**
+ * Attaches an event listener called once on the model
+ * @param {string} type
+ * @param {function} cb
+ * @returns {Model}
+ */
+ once: function() {
+ this.$.one.apply(this.$, Array.prototype.slice.call(arguments));
+ return this;
+ }
+});
+
+
+/**
+ * Root abstract object
+ * @constructor
+ * @param {Node} [parent]
+ * @param {jQuery} $el
+ */
+var Node = function(parent, $el) {
+ if (!(this instanceof Node)) {
+ return new Node(parent, $el);
+ }
+
+ Object.defineProperty(this, '__', { value: {} });
+
+ $el.data('queryBuilderModel', this);
+
+ /**
+ * @name level
+ * @member {int}
+ * @memberof Node
+ * @instance
+ * @readonly
+ */
+ this.__.level = 1;
+
+ /**
+ * @name error
+ * @member {string}
+ * @memberof Node
+ * @instance
+ */
+ this.__.error = null;
+
+ /**
+ * @name flags
+ * @member {object}
+ * @memberof Node
+ * @instance
+ * @readonly
+ */
+ this.__.flags = {};
+
+ /**
+ * @name data
+ * @member {object}
+ * @memberof Node
+ * @instance
+ */
+ this.__.data = undefined;
+
+ /**
+ * @member {jQuery}
+ * @readonly
+ */
+ this.$el = $el;
+
+ /**
+ * @member {string}
+ * @readonly
+ */
+ this.id = $el[0].id;
+
+ /**
+ * @member {Model}
+ * @readonly
+ */
+ this.model = null;
+
+ /**
+ * @member {Group}
+ * @readonly
+ */
+ this.parent = parent;
+};
+
+Utils.defineModelProperties(Node, ['level', 'error', 'data', 'flags']);
+
+Object.defineProperty(Node.prototype, 'parent', {
+ enumerable: true,
+ get: function() {
+ return this.__.parent;
+ },
+ set: function(value) {
+ this.__.parent = value;
+ this.level = value === null ? 1 : value.level + 1;
+ this.model = value === null ? null : value.model;
+ }
+});
+
+/**
+ * Checks if this Node is the root
+ * @returns {boolean}
+ */
+Node.prototype.isRoot = function() {
+ return (this.level === 1);
+};
+
+/**
+ * Returns the node position inside its parent
+ * @returns {int}
+ */
+Node.prototype.getPos = function() {
+ if (this.isRoot()) {
+ return -1;
+ }
+ else {
+ return this.parent.getNodePos(this);
+ }
+};
+
+/**
+ * Deletes self
+ * @fires Model.model:drop
+ */
+Node.prototype.drop = function() {
+ var model = this.model;
+
+ if (!!this.parent) {
+ this.parent.removeNode(this);
+ }
+
+ this.$el.removeData('queryBuilderModel');
+
+ if (model !== null) {
+ /**
+ * After a node of the model has been removed
+ * @event model:drop
+ * @memberof Model
+ * @param {Node} node
+ */
+ model.trigger('drop', this);
+ }
+};
+
+/**
+ * Moves itself after another Node
+ * @param {Node} target
+ * @fires Model.model:move
+ */
+Node.prototype.moveAfter = function(target) {
+ if (!this.isRoot()) {
+ this.move(target.parent, target.getPos() + 1);
+ }
+};
+
+/**
+ * Moves itself at the beginning of parent or another Group
+ * @param {Group} [target]
+ * @fires Model.model:move
+ */
+Node.prototype.moveAtBegin = function(target) {
+ if (!this.isRoot()) {
+ if (target === undefined) {
+ target = this.parent;
+ }
+
+ this.move(target, 0);
+ }
+};
+
+/**
+ * Moves itself at the end of parent or another Group
+ * @param {Group} [target]
+ * @fires Model.model:move
+ */
+Node.prototype.moveAtEnd = function(target) {
+ if (!this.isRoot()) {
+ if (target === undefined) {
+ target = this.parent;
+ }
+
+ this.move(target, target.length() === 0 ? 0 : target.length() - 1);
+ }
+};
+
+/**
+ * Moves itself at specific position of Group
+ * @param {Group} target
+ * @param {int} index
+ * @fires Model.model:move
+ */
+Node.prototype.move = function(target, index) {
+ if (!this.isRoot()) {
+ if (typeof target === 'number') {
+ index = target;
+ target = this.parent;
+ }
+
+ this.parent.removeNode(this);
+ target.insertNode(this, index, false);
+
+ if (this.model !== null) {
+ /**
+ * After a node of the model has been moved
+ * @event model:move
+ * @memberof Model
+ * @param {Node} node
+ * @param {Node} target
+ * @param {int} index
+ */
+ this.model.trigger('move', this, target, index);
+ }
+ }
+};
+
+
+/**
+ * Group object
+ * @constructor
+ * @extends Node
+ * @param {Group} [parent]
+ * @param {jQuery} $el
+ */
+var Group = function(parent, $el) {
+ if (!(this instanceof Group)) {
+ return new Group(parent, $el);
+ }
+
+ Node.call(this, parent, $el);
+
+ /**
+ * @member {object[]}
+ * @readonly
+ */
+ this.rules = [];
+
+ /**
+ * @name condition
+ * @member {string}
+ * @memberof Group
+ * @instance
+ */
+ this.__.condition = null;
+};
+
+Group.prototype = Object.create(Node.prototype);
+Group.prototype.constructor = Group;
+
+Utils.defineModelProperties(Group, ['condition']);
+
+/**
+ * Removes group's content
+ */
+Group.prototype.empty = function() {
+ this.each('reverse', function(rule) {
+ rule.drop();
+ }, function(group) {
+ group.drop();
+ });
+};
+
+/**
+ * Deletes self
+ */
+Group.prototype.drop = function() {
+ this.empty();
+ Node.prototype.drop.call(this);
+};
+
+/**
+ * Returns the number of children
+ * @returns {int}
+ */
+Group.prototype.length = function() {
+ return this.rules.length;
+};
+
+/**
+ * Adds a Node at specified index
+ * @param {Node} node
+ * @param {int} [index=end]
+ * @param {boolean} [trigger=false] - fire 'add' event
+ * @returns {Node} the inserted node
+ * @fires Model.model:add
+ */
+Group.prototype.insertNode = function(node, index, trigger) {
+ if (index === undefined) {
+ index = this.length();
+ }
+
+ this.rules.splice(index, 0, node);
+ node.parent = this;
+
+ if (trigger && this.model !== null) {
+ /**
+ * After a node of the model has been added
+ * @event model:add
+ * @memberof Model
+ * @param {Node} parent
+ * @param {Node} node
+ * @param {int} index
+ */
+ this.model.trigger('add', this, node, index);
+ }
+
+ return node;
+};
+
+/**
+ * Adds a new Group at specified index
+ * @param {jQuery} $el
+ * @param {int} [index=end]
+ * @returns {Group}
+ * @fires Model.model:add
+ */
+Group.prototype.addGroup = function($el, index) {
+ return this.insertNode(new Group(this, $el), index, true);
+};
+
+/**
+ * Adds a new Rule at specified index
+ * @param {jQuery} $el
+ * @param {int} [index=end]
+ * @returns {Rule}
+ * @fires Model.model:add
+ */
+Group.prototype.addRule = function($el, index) {
+ return this.insertNode(new Rule(this, $el), index, true);
+};
+
+/**
+ * Deletes a specific Node
+ * @param {Node} node
+ */
+Group.prototype.removeNode = function(node) {
+ var index = this.getNodePos(node);
+ if (index !== -1) {
+ node.parent = null;
+ this.rules.splice(index, 1);
+ }
+};
+
+/**
+ * Returns the position of a child Node
+ * @param {Node} node
+ * @returns {int}
+ */
+Group.prototype.getNodePos = function(node) {
+ return this.rules.indexOf(node);
+};
+
+/**
+ * @callback Model#GroupIteratee
+ * @param {Node} node
+ * @returns {boolean} stop the iteration
+ */
+
+/**
+ * Iterate over all Nodes
+ * @param {boolean} [reverse=false] - iterate in reverse order, required if you delete nodes
+ * @param {Model#GroupIteratee} cbRule - callback for Rules (can be `null` but not omitted)
+ * @param {Model#GroupIteratee} [cbGroup] - callback for Groups
+ * @param {object} [context] - context for callbacks
+ * @returns {boolean} if the iteration has been stopped by a callback
+ */
+Group.prototype.each = function(reverse, cbRule, cbGroup, context) {
+ if (typeof reverse !== 'boolean' && typeof reverse !== 'string') {
+ context = cbGroup;
+ cbGroup = cbRule;
+ cbRule = reverse;
+ reverse = false;
+ }
+ context = context === undefined ? null : context;
+
+ var i = reverse ? this.rules.length - 1 : 0;
+ var l = reverse ? 0 : this.rules.length - 1;
+ var c = reverse ? -1 : 1;
+ var next = function() {
+ return reverse ? i >= l : i <= l;
+ };
+ var stop = false;
+
+ for (; next(); i += c) {
+ if (this.rules[i] instanceof Group) {
+ if (!!cbGroup) {
+ stop = cbGroup.call(context, this.rules[i]) === false;
+ }
+ }
+ else if (!!cbRule) {
+ stop = cbRule.call(context, this.rules[i]) === false;
+ }
+
+ if (stop) {
+ break;
+ }
+ }
+
+ return !stop;
+};
+
+/**
+ * Checks if the group contains a particular Node
+ * @param {Node} node
+ * @param {boolean} [recursive=false]
+ * @returns {boolean}
+ */
+Group.prototype.contains = function(node, recursive) {
+ if (this.getNodePos(node) !== -1) {
+ return true;
+ }
+ else if (!recursive) {
+ return false;
+ }
+ else {
+ // the loop will return with false as soon as the Node is found
+ return !this.each(function() {
+ return true;
+ }, function(group) {
+ return !group.contains(node, true);
+ });
+ }
+};
+
+
+/**
+ * Rule object
+ * @constructor
+ * @extends Node
+ * @param {Group} parent
+ * @param {jQuery} $el
+ */
+var Rule = function(parent, $el) {
+ if (!(this instanceof Rule)) {
+ return new Rule(parent, $el);
+ }
+
+ Node.call(this, parent, $el);
+
+ this._updating_value = false;
+ this._updating_input = false;
+
+ /**
+ * @name filter
+ * @member {QueryBuilder.Filter}
+ * @memberof Rule
+ * @instance
+ */
+ this.__.filter = null;
+
+ /**
+ * @name operator
+ * @member {QueryBuilder.Operator}
+ * @memberof Rule
+ * @instance
+ */
+ this.__.operator = null;
+
+ /**
+ * @name value
+ * @member {*}
+ * @memberof Rule
+ * @instance
+ */
+ this.__.value = undefined;
+};
+
+Rule.prototype = Object.create(Node.prototype);
+Rule.prototype.constructor = Rule;
+
+Utils.defineModelProperties(Rule, ['filter', 'operator', 'value']);
+
+/**
+ * Checks if this Node is the root
+ * @returns {boolean} always false
+ */
+Rule.prototype.isRoot = function() {
+ return false;
+};
+
+
+/**
+ * @member {function}
+ * @memberof QueryBuilder
+ * @see Group
+ */
+QueryBuilder.Group = Group;
+
+/**
+ * @member {function}
+ * @memberof QueryBuilder
+ * @see Rule
+ */
+QueryBuilder.Rule = Rule;
+
+
+/**
+ * The {@link http://learn.jquery.com/plugins/|jQuery Plugins} namespace
+ * @external "jQuery.fn"
+ */
+
+/**
+ * Instanciates or accesses the {@link QueryBuilder} on an element
+ * @function
+ * @memberof external:"jQuery.fn"
+ * @param {*} option - initial configuration or method name
+ * @param {...*} args - method arguments
+ *
+ * @example
+ * $('#builder').queryBuilder({ /** configuration object *\/ });
+ * @example
+ * $('#builder').queryBuilder('methodName', methodParam1, methodParam2);
+ */
+$.fn.queryBuilder = function(option) {
+ if (this.length === 0) {
+ Utils.error('Config', 'No target defined');
+ }
+ if (this.length > 1) {
+ Utils.error('Config', 'Unable to initialize on multiple target');
+ }
+
+ var data = this.data('queryBuilder');
+ var options = (typeof option == 'object' && option) || {};
+
+ if (!data && option == 'destroy') {
+ return this;
+ }
+ if (!data) {
+ var builder = new QueryBuilder(this, options);
+ this.data('queryBuilder', builder);
+ builder.init(options.rules);
+ }
+ if (typeof option == 'string') {
+ return data[option].apply(data, Array.prototype.slice.call(arguments, 1));
+ }
+
+ return this;
+};
+
+/**
+ * @function
+ * @memberof external:"jQuery.fn"
+ * @see QueryBuilder
+ */
+$.fn.queryBuilder.constructor = QueryBuilder;
+
+/**
+ * @function
+ * @memberof external:"jQuery.fn"
+ * @see QueryBuilder.defaults
+ */
+$.fn.queryBuilder.defaults = QueryBuilder.defaults;
+
+/**
+ * @function
+ * @memberof external:"jQuery.fn"
+ * @see QueryBuilder.defaults
+ */
+$.fn.queryBuilder.extend = QueryBuilder.extend;
+
+/**
+ * @function
+ * @memberof external:"jQuery.fn"
+ * @see QueryBuilder.define
+ */
+$.fn.queryBuilder.define = QueryBuilder.define;
+
+/**
+ * @function
+ * @memberof external:"jQuery.fn"
+ * @see QueryBuilder.regional
+ */
+$.fn.queryBuilder.regional = QueryBuilder.regional;
+
+
+/**
+ * @class BtCheckbox
+ * @memberof module:plugins
+ * @description Applies Awesome Bootstrap Checkbox for checkbox and radio inputs.
+ * @param {object} [options]
+ * @param {string} [options.font='glyphicons']
+ * @param {string} [options.color='default']
+ */
+QueryBuilder.define('bt-checkbox', function(options) {
+ if (options.font == 'glyphicons') {
+ this.$el.addClass('bt-checkbox-glyphicons');
+ }
+
+ this.on('getRuleInput.filter', function(h, rule, name) {
+ var filter = rule.filter;
+
+ if ((filter.input === 'radio' || filter.input === 'checkbox') && !filter.plugin) {
+ h.value = '';
+
+ if (!filter.colors) {
+ filter.colors = {};
+ }
+ if (filter.color) {
+ filter.colors._def_ = filter.color;
+ }
+
+ var style = filter.vertical ? ' style="display:block"' : '';
+ var i = 0;
+
+ Utils.iterateOptions(filter.values, function(key, val) {
+ var color = filter.colors[key] || filter.colors._def_ || options.color;
+ var id = name + '_' + (i++);
+
+ h.value+= '\
+ \
+ \
+ ' + val + ' \
+
';
+ });
+ }
+ });
+}, {
+ font: 'glyphicons',
+ color: 'default'
+});
+
+
+/**
+ * @class BtSelectpicker
+ * @memberof module:plugins
+ * @descriptioon Applies Bootstrap Select on filters and operators combo-boxes.
+ * @param {object} [options]
+ * @param {string} [options.container='body']
+ * @param {string} [options.style='btn-inverse btn-sm']
+ * @param {int|string} [options.width='auto']
+ * @param {boolean} [options.showIcon=false]
+ * @throws MissingLibraryError
+ */
+QueryBuilder.define('bt-selectpicker', function(options) {
+ if (!$.fn.selectpicker || !$.fn.selectpicker.Constructor) {
+ Utils.error('MissingLibrary', 'Bootstrap Select is required to use "bt-selectpicker" plugin. Get it here: http://silviomoreto.github.io/bootstrap-select');
+ }
+
+ var Selectors = QueryBuilder.selectors;
+
+ // init selectpicker
+ this.on('afterCreateRuleFilters', function(e, rule) {
+ rule.$el.find(Selectors.rule_filter).removeClass('form-control').selectpicker(options);
+ });
+
+ this.on('afterCreateRuleOperators', function(e, rule) {
+ rule.$el.find(Selectors.rule_operator).removeClass('form-control').selectpicker(options);
+ });
+
+ // update selectpicker on change
+ this.on('afterUpdateRuleFilter', function(e, rule) {
+ rule.$el.find(Selectors.rule_filter).selectpicker('render');
+ });
+
+ this.on('afterUpdateRuleOperator', function(e, rule) {
+ rule.$el.find(Selectors.rule_operator).selectpicker('render');
+ });
+
+ this.on('beforeDeleteRule', function(e, rule) {
+ rule.$el.find(Selectors.rule_filter).selectpicker('destroy');
+ rule.$el.find(Selectors.rule_operator).selectpicker('destroy');
+ });
+}, {
+ container: 'body',
+ style: 'btn-inverse btn-sm',
+ width: 'auto',
+ showIcon: false
+});
+
+
+/**
+ * @class BtTooltipErrors
+ * @memberof module:plugins
+ * @description Applies Bootstrap Tooltips on validation error messages.
+ * @param {object} [options]
+ * @param {string} [options.placement='right']
+ * @throws MissingLibraryError
+ */
+QueryBuilder.define('bt-tooltip-errors', function(options) {
+ if (!$.fn.tooltip || !$.fn.tooltip.Constructor || !$.fn.tooltip.Constructor.prototype.fixTitle) {
+ Utils.error('MissingLibrary', 'Bootstrap Tooltip is required to use "bt-tooltip-errors" plugin. Get it here: http://getbootstrap.com');
+ }
+
+ var self = this;
+
+ // add BT Tooltip data
+ this.on('getRuleTemplate.filter getGroupTemplate.filter', function(h) {
+ var $h = $(h.value);
+ $h.find(QueryBuilder.selectors.error_container).attr('data-toggle', 'tooltip');
+ h.value = $h.prop('outerHTML');
+ });
+
+ // init/refresh tooltip when title changes
+ this.model.on('update', function(e, node, field) {
+ if (field == 'error' && self.settings.display_errors) {
+ node.$el.find(QueryBuilder.selectors.error_container).eq(0)
+ .tooltip(options)
+ .tooltip('hide')
+ .tooltip('fixTitle');
+ }
+ });
+}, {
+ placement: 'right'
+});
+
+
+/**
+ * @class ChangeFilters
+ * @memberof module:plugins
+ * @description Allows to change available filters after plugin initialization.
+ */
+
+QueryBuilder.extend(/** @lends module:plugins.ChangeFilters.prototype */ {
+ /**
+ * Change the filters of the builder
+ * @param {boolean} [deleteOrphans=false] - delete rules using old filters
+ * @param {QueryBuilder[]} filters
+ * @fires module:plugins.ChangeFilters.changer:setFilters
+ * @fires module:plugins.ChangeFilters.afterSetFilters
+ * @throws ChangeFilterError
+ */
+ setFilters: function(deleteOrphans, filters) {
+ var self = this;
+
+ if (filters === undefined) {
+ filters = deleteOrphans;
+ deleteOrphans = false;
+ }
+
+ filters = this.checkFilters(filters);
+
+ /**
+ * Modifies the filters before {@link module:plugins.ChangeFilters.setFilters} method
+ * @event changer:setFilters
+ * @memberof module:plugins.ChangeFilters
+ * @param {QueryBuilder.Filter[]} filters
+ * @returns {QueryBuilder.Filter[]}
+ */
+ filters = this.change('setFilters', filters);
+
+ var filtersIds = filters.map(function(filter) {
+ return filter.id;
+ });
+
+ // check for orphans
+ if (!deleteOrphans) {
+ (function checkOrphans(node) {
+ node.each(
+ function(rule) {
+ if (rule.filter && filtersIds.indexOf(rule.filter.id) === -1) {
+ Utils.error('ChangeFilter', 'A rule is using filter "{0}"', rule.filter.id);
+ }
+ },
+ checkOrphans
+ );
+ }(this.model.root));
+ }
+
+ // replace filters
+ this.filters = filters;
+
+ // apply on existing DOM
+ (function updateBuilder(node) {
+ node.each(true,
+ function(rule) {
+ if (rule.filter && filtersIds.indexOf(rule.filter.id) === -1) {
+ rule.drop();
+
+ self.trigger('rulesChanged');
+ }
+ else {
+ self.createRuleFilters(rule);
+
+ rule.$el.find(QueryBuilder.selectors.rule_filter).val(rule.filter ? rule.filter.id : '-1');
+ self.trigger('afterUpdateRuleFilter', rule);
+ }
+ },
+ updateBuilder
+ );
+ }(this.model.root));
+
+ // update plugins
+ if (this.settings.plugins) {
+ if (this.settings.plugins['unique-filter']) {
+ this.updateDisabledFilters();
+ }
+ if (this.settings.plugins['bt-selectpicker']) {
+ this.$el.find(QueryBuilder.selectors.rule_filter).selectpicker('render');
+ }
+ }
+
+ // reset the default_filter if does not exist anymore
+ if (this.settings.default_filter) {
+ try {
+ this.getFilterById(this.settings.default_filter);
+ }
+ catch (e) {
+ this.settings.default_filter = null;
+ }
+ }
+
+ /**
+ * After {@link module:plugins.ChangeFilters.setFilters} method
+ * @event afterSetFilters
+ * @memberof module:plugins.ChangeFilters
+ * @param {QueryBuilder.Filter[]} filters
+ */
+ this.trigger('afterSetFilters', filters);
+ },
+
+ /**
+ * Adds a new filter to the builder
+ * @param {QueryBuilder.Filter|Filter[]} newFilters
+ * @param {int|string} [position=#end] - index or '#start' or '#end'
+ * @fires module:plugins.ChangeFilters.changer:setFilters
+ * @fires module:plugins.ChangeFilters.afterSetFilters
+ * @throws ChangeFilterError
+ */
+ addFilter: function(newFilters, position) {
+ if (position === undefined || position == '#end') {
+ position = this.filters.length;
+ }
+ else if (position == '#start') {
+ position = 0;
+ }
+
+ if (!$.isArray(newFilters)) {
+ newFilters = [newFilters];
+ }
+
+ var filters = $.extend(true, [], this.filters);
+
+ // numeric position
+ if (parseInt(position) == position) {
+ Array.prototype.splice.apply(filters, [position, 0].concat(newFilters));
+ }
+ else {
+ // after filter by its id
+ if (this.filters.some(function(filter, index) {
+ if (filter.id == position) {
+ position = index + 1;
+ return true;
+ }
+ })
+ ) {
+ Array.prototype.splice.apply(filters, [position, 0].concat(newFilters));
+ }
+ // defaults to end of list
+ else {
+ Array.prototype.push.apply(filters, newFilters);
+ }
+ }
+
+ this.setFilters(filters);
+ },
+
+ /**
+ * Removes a filter from the builder
+ * @param {string|string[]} filterIds
+ * @param {boolean} [deleteOrphans=false] delete rules using old filters
+ * @fires module:plugins.ChangeFilters.changer:setFilters
+ * @fires module:plugins.ChangeFilters.afterSetFilters
+ * @throws ChangeFilterError
+ */
+ removeFilter: function(filterIds, deleteOrphans) {
+ var filters = $.extend(true, [], this.filters);
+ if (typeof filterIds === 'string') {
+ filterIds = [filterIds];
+ }
+
+ filters = filters.filter(function(filter) {
+ return filterIds.indexOf(filter.id) === -1;
+ });
+
+ this.setFilters(deleteOrphans, filters);
+ }
+});
+
+
+/**
+ * @class ChosenSelectpicker
+ * @memberof module:plugins
+ * @descriptioon Applies chosen-js Select on filters and operators combo-boxes.
+ * @param {object} [options] Supports all the options for chosen
+ * @throws MissingLibraryError
+ */
+QueryBuilder.define('chosen-selectpicker', function(options) {
+
+ if (!$.fn.chosen) {
+ Utils.error('MissingLibrary', 'chosen is required to use "chosen-selectpicker" plugin. Get it here: https://github.com/harvesthq/chosen');
+ }
+
+ if (this.settings.plugins['bt-selectpicker']) {
+ Utils.error('Conflict', 'bt-selectpicker is already selected as the dropdown plugin. Please remove chosen-selectpicker from the plugin list');
+ }
+
+ var Selectors = QueryBuilder.selectors;
+
+ // init selectpicker
+ this.on('afterCreateRuleFilters', function(e, rule) {
+ rule.$el.find(Selectors.rule_filter).removeClass('form-control').chosen(options);
+ });
+
+ this.on('afterCreateRuleOperators', function(e, rule) {
+ if (e.builder.getOperators(rule.filter).length > 1) {
+ rule.$el.find(Selectors.rule_operator).removeClass('form-control').chosen(options);
+ }
+ });
+
+ // update selectpicker on change
+ this.on('afterUpdateRuleFilter', function(e, rule) {
+ rule.$el.find(Selectors.rule_filter).trigger('chosen:updated');
+ });
+
+ this.on('afterUpdateRuleOperator', function(e, rule) {
+ rule.$el.find(Selectors.rule_operator).trigger('chosen:updated');
+ });
+
+ this.on('beforeDeleteRule', function(e, rule) {
+ rule.$el.find(Selectors.rule_filter).chosen('destroy');
+ rule.$el.find(Selectors.rule_operator).chosen('destroy');
+ });
+});
+
+
+/**
+ * @class FilterDescription
+ * @memberof module:plugins
+ * @description Provides three ways to display a description about a filter: inline, Bootsrap Popover or Bootbox.
+ * @param {object} [options]
+ * @param {string} [options.icon='glyphicon glyphicon-info-sign']
+ * @param {string} [options.mode='popover'] - inline, popover or bootbox
+ * @throws ConfigError
+ */
+QueryBuilder.define('filter-description', function(options) {
+ // INLINE
+ if (options.mode === 'inline') {
+ this.on('afterUpdateRuleFilter afterUpdateRuleOperator', function(e, rule) {
+ var $p = rule.$el.find('p.filter-description');
+ var description = e.builder.getFilterDescription(rule.filter, rule);
+
+ if (!description) {
+ $p.hide();
+ }
+ else {
+ if ($p.length === 0) {
+ $p = $('
');
+ $p.appendTo(rule.$el);
+ }
+ else {
+ $p.css('display', '');
+ }
+
+ $p.html(' ' + description);
+ }
+ });
+ }
+ // POPOVER
+ else if (options.mode === 'popover') {
+ if (!$.fn.popover || !$.fn.popover.Constructor || !$.fn.popover.Constructor.prototype.fixTitle) {
+ Utils.error('MissingLibrary', 'Bootstrap Popover is required to use "filter-description" plugin. Get it here: http://getbootstrap.com');
+ }
+
+ this.on('afterUpdateRuleFilter afterUpdateRuleOperator', function(e, rule) {
+ var $b = rule.$el.find('button.filter-description');
+ var description = e.builder.getFilterDescription(rule.filter, rule);
+
+ if (!description) {
+ $b.hide();
+
+ if ($b.data('bs.popover')) {
+ $b.popover('hide');
+ }
+ }
+ else {
+ if ($b.length === 0) {
+ $b = $(' ');
+ $b.prependTo(rule.$el.find(QueryBuilder.selectors.rule_actions));
+
+ $b.popover({
+ placement: 'left',
+ container: 'body',
+ html: true
+ });
+
+ $b.on('mouseout', function() {
+ $b.popover('hide');
+ });
+ }
+ else {
+ $b.css('display', '');
+ }
+
+ $b.data('bs.popover').options.content = description;
+
+ if ($b.attr('aria-describedby')) {
+ $b.popover('show');
+ }
+ }
+ });
+ }
+ // BOOTBOX
+ else if (options.mode === 'bootbox') {
+ if (!('bootbox' in window)) {
+ Utils.error('MissingLibrary', 'Bootbox is required to use "filter-description" plugin. Get it here: http://bootboxjs.com');
+ }
+
+ this.on('afterUpdateRuleFilter afterUpdateRuleOperator', function(e, rule) {
+ var $b = rule.$el.find('button.filter-description');
+ var description = e.builder.getFilterDescription(rule.filter, rule);
+
+ if (!description) {
+ $b.hide();
+ }
+ else {
+ if ($b.length === 0) {
+ $b = $(' ');
+ $b.prependTo(rule.$el.find(QueryBuilder.selectors.rule_actions));
+
+ $b.on('click', function() {
+ bootbox.alert($b.data('description'));
+ });
+ }
+ else {
+ $b.css('display', '');
+ }
+
+ $b.data('description', description);
+ }
+ });
+ }
+}, {
+ icon: 'glyphicon glyphicon-info-sign',
+ mode: 'popover'
+});
+
+QueryBuilder.extend(/** @lends module:plugins.FilterDescription.prototype */ {
+ /**
+ * Returns the description of a filter for a particular rule (if present)
+ * @param {object} filter
+ * @param {Rule} [rule]
+ * @returns {string}
+ * @private
+ */
+ getFilterDescription: function(filter, rule) {
+ if (!filter) {
+ return undefined;
+ }
+ else if (typeof filter.description == 'function') {
+ return filter.description.call(this, rule);
+ }
+ else {
+ return filter.description;
+ }
+ }
+});
+
+
+/**
+ * @class Invert
+ * @memberof module:plugins
+ * @description Allows to invert a rule operator, a group condition or the entire builder.
+ * @param {object} [options]
+ * @param {string} [options.icon='glyphicon glyphicon-random']
+ * @param {boolean} [options.recursive=true]
+ * @param {boolean} [options.invert_rules=true]
+ * @param {boolean} [options.display_rules_button=false]
+ * @param {boolean} [options.silent_fail=false]
+ */
+QueryBuilder.define('invert', function(options) {
+ var self = this;
+ var Selectors = QueryBuilder.selectors;
+
+ // Bind events
+ this.on('afterInit', function() {
+ self.$el.on('click.queryBuilder', '[data-invert=group]', function() {
+ var $group = $(this).closest(Selectors.group_container);
+ self.invert(self.getModel($group), options);
+ });
+
+ if (options.display_rules_button && options.invert_rules) {
+ self.$el.on('click.queryBuilder', '[data-invert=rule]', function() {
+ var $rule = $(this).closest(Selectors.rule_container);
+ self.invert(self.getModel($rule), options);
+ });
+ }
+ });
+
+ // Modify templates
+ if (!options.disable_template) {
+ this.on('getGroupTemplate.filter', function(h) {
+ var $h = $(h.value);
+ $h.find(Selectors.condition_container).after(
+ '' +
+ ' ' + self.translate('invert') +
+ ' '
+ );
+ h.value = $h.prop('outerHTML');
+ });
+
+ if (options.display_rules_button && options.invert_rules) {
+ this.on('getRuleTemplate.filter', function(h) {
+ var $h = $(h.value);
+ $h.find(Selectors.rule_actions).prepend(
+ '' +
+ ' ' + self.translate('invert') +
+ ' '
+ );
+ h.value = $h.prop('outerHTML');
+ });
+ }
+ }
+}, {
+ icon: 'glyphicon glyphicon-random',
+ recursive: true,
+ invert_rules: true,
+ display_rules_button: false,
+ silent_fail: false,
+ disable_template: false
+});
+
+QueryBuilder.defaults({
+ operatorOpposites: {
+ 'equal': 'not_equal',
+ 'not_equal': 'equal',
+ 'in': 'not_in',
+ 'not_in': 'in',
+ 'less': 'greater_or_equal',
+ 'less_or_equal': 'greater',
+ 'greater': 'less_or_equal',
+ 'greater_or_equal': 'less',
+ 'between': 'not_between',
+ 'not_between': 'between',
+ 'begins_with': 'not_begins_with',
+ 'not_begins_with': 'begins_with',
+ 'contains': 'not_contains',
+ 'not_contains': 'contains',
+ 'ends_with': 'not_ends_with',
+ 'not_ends_with': 'ends_with',
+ 'is_empty': 'is_not_empty',
+ 'is_not_empty': 'is_empty',
+ 'is_null': 'is_not_null',
+ 'is_not_null': 'is_null'
+ },
+
+ conditionOpposites: {
+ 'AND': 'OR',
+ 'OR': 'AND'
+ }
+});
+
+QueryBuilder.extend(/** @lends module:plugins.Invert.prototype */ {
+ /**
+ * Invert a Group, a Rule or the whole builder
+ * @param {Node} [node]
+ * @param {object} [options] {@link module:plugins.Invert}
+ * @fires module:plugins.Invert.afterInvert
+ * @throws InvertConditionError, InvertOperatorError
+ */
+ invert: function(node, options) {
+ if (!(node instanceof Node)) {
+ if (!this.model.root) return;
+ options = node;
+ node = this.model.root;
+ }
+
+ if (typeof options != 'object') options = {};
+ if (options.recursive === undefined) options.recursive = true;
+ if (options.invert_rules === undefined) options.invert_rules = true;
+ if (options.silent_fail === undefined) options.silent_fail = false;
+ if (options.trigger === undefined) options.trigger = true;
+
+ if (node instanceof Group) {
+ // invert group condition
+ if (this.settings.conditionOpposites[node.condition]) {
+ node.condition = this.settings.conditionOpposites[node.condition];
+ }
+ else if (!options.silent_fail) {
+ Utils.error('InvertCondition', 'Unknown inverse of condition "{0}"', node.condition);
+ }
+
+ // recursive call
+ if (options.recursive) {
+ var tempOpts = $.extend({}, options, { trigger: false });
+ node.each(function(rule) {
+ if (options.invert_rules) {
+ this.invert(rule, tempOpts);
+ }
+ }, function(group) {
+ this.invert(group, tempOpts);
+ }, this);
+ }
+ }
+ else if (node instanceof Rule) {
+ if (node.operator && !node.filter.no_invert) {
+ // invert rule operator
+ if (this.settings.operatorOpposites[node.operator.type]) {
+ var invert = this.settings.operatorOpposites[node.operator.type];
+ // check if the invert is "authorized"
+ if (!node.filter.operators || node.filter.operators.indexOf(invert) != -1) {
+ node.operator = this.getOperatorByType(invert);
+ }
+ }
+ else if (!options.silent_fail) {
+ Utils.error('InvertOperator', 'Unknown inverse of operator "{0}"', node.operator.type);
+ }
+ }
+ }
+
+ if (options.trigger) {
+ /**
+ * After {@link module:plugins.Invert.invert} method
+ * @event afterInvert
+ * @memberof module:plugins.Invert
+ * @param {Node} node - the main group or rule that has been modified
+ * @param {object} options
+ */
+ this.trigger('afterInvert', node, options);
+
+ this.trigger('rulesChanged');
+ }
+ }
+});
+
+
+/**
+ * @class MongoDbSupport
+ * @memberof module:plugins
+ * @description Allows to export rules as a MongoDB find object as well as populating the builder from a MongoDB object.
+ */
+
+QueryBuilder.defaults({
+ mongoOperators: {
+ // @formatter:off
+ equal: function(v) { return v[0]; },
+ not_equal: function(v) { return { '$ne': v[0] }; },
+ in: function(v) { return { '$in': v }; },
+ not_in: function(v) { return { '$nin': v }; },
+ less: function(v) { return { '$lt': v[0] }; },
+ less_or_equal: function(v) { return { '$lte': v[0] }; },
+ greater: function(v) { return { '$gt': v[0] }; },
+ greater_or_equal: function(v) { return { '$gte': v[0] }; },
+ between: function(v) { return { '$gte': v[0], '$lte': v[1] }; },
+ not_between: function(v) { return { '$lt': v[0], '$gt': v[1] }; },
+ begins_with: function(v) { return { '$regex': '^' + Utils.escapeRegExp(v[0]) }; },
+ not_begins_with: function(v) { return { '$regex': '^(?!' + Utils.escapeRegExp(v[0]) + ')' }; },
+ contains: function(v) { return { '$regex': Utils.escapeRegExp(v[0]) }; },
+ not_contains: function(v) { return { '$regex': '^((?!' + Utils.escapeRegExp(v[0]) + ').)*$', '$options': 's' }; },
+ ends_with: function(v) { return { '$regex': Utils.escapeRegExp(v[0]) + '$' }; },
+ not_ends_with: function(v) { return { '$regex': '(? 0) {
+ parts.push(parse(rule));
+ }
+ else {
+ var mdb = self.settings.mongoOperators[rule.operator];
+ var ope = self.getOperatorByType(rule.operator);
+
+ if (mdb === undefined) {
+ Utils.error('UndefinedMongoOperator', 'Unknown MongoDB operation for operator "{0}"', rule.operator);
+ }
+
+ if (ope.nb_inputs !== 0) {
+ if (!(rule.value instanceof Array)) {
+ rule.value = [rule.value];
+ }
+ }
+
+ /**
+ * Modifies the MongoDB field used by a rule
+ * @event changer:getMongoDBField
+ * @memberof module:plugins.MongoDbSupport
+ * @param {string} field
+ * @param {Rule} rule
+ * @returns {string}
+ */
+ var field = self.change('getMongoDBField', rule.field, rule);
+
+ var ruleExpression = {};
+ ruleExpression[field] = mdb.call(self, rule.value);
+
+ /**
+ * Modifies the MongoDB expression generated for a rul
+ * @event changer:ruleToMongo
+ * @memberof module:plugins.MongoDbSupport
+ * @param {object} expression
+ * @param {Rule} rule
+ * @param {*} value
+ * @param {function} valueWrapper - function that takes the value and adds the operator
+ * @returns {object}
+ */
+ parts.push(self.change('ruleToMongo', ruleExpression, rule, rule.value, mdb));
+ }
+ });
+
+ var groupExpression = {};
+ groupExpression['$' + group.condition.toLowerCase()] = parts;
+
+ /**
+ * Modifies the MongoDB expression generated for a group
+ * @event changer:groupToMongo
+ * @memberof module:plugins.MongoDbSupport
+ * @param {object} expression
+ * @param {Group} group
+ * @returns {object}
+ */
+ return self.change('groupToMongo', groupExpression, group);
+ }(data));
+ },
+
+ /**
+ * Converts a MongoDB query to rules
+ * @param {object} query
+ * @returns {object}
+ * @fires module:plugins.MongoDbSupport.changer:parseMongoNode
+ * @fires module:plugins.MongoDbSupport.changer:getMongoDBFieldID
+ * @fires module:plugins.MongoDbSupport.changer:mongoToRule
+ * @fires module:plugins.MongoDbSupport.changer:mongoToGroup
+ * @throws MongoParseError, UndefinedMongoConditionError, UndefinedMongoOperatorError
+ */
+ getRulesFromMongo: function(query) {
+ if (query === undefined || query === null) {
+ return null;
+ }
+
+ var self = this;
+
+ /**
+ * Custom parsing of a MongoDB expression, you can return a sub-part of the expression, or a well formed group or rule JSON
+ * @event changer:parseMongoNode
+ * @memberof module:plugins.MongoDbSupport
+ * @param {object} expression
+ * @returns {object} expression, rule or group
+ */
+ query = self.change('parseMongoNode', query);
+
+ // a plugin returned a group
+ if ('rules' in query && 'condition' in query) {
+ return query;
+ }
+
+ // a plugin returned a rule
+ if ('id' in query && 'operator' in query && 'value' in query) {
+ return {
+ condition: this.settings.default_condition,
+ rules: [query]
+ };
+ }
+
+ var key = self.getMongoCondition(query);
+ if (!key) {
+ Utils.error('MongoParse', 'Invalid MongoDB query format');
+ }
+
+ return (function parse(data, topKey) {
+ var rules = data[topKey];
+ var parts = [];
+
+ rules.forEach(function(data) {
+ // allow plugins to manually parse or handle special cases
+ data = self.change('parseMongoNode', data);
+
+ // a plugin returned a group
+ if ('rules' in data && 'condition' in data) {
+ parts.push(data);
+ return;
+ }
+
+ // a plugin returned a rule
+ if ('id' in data && 'operator' in data && 'value' in data) {
+ parts.push(data);
+ return;
+ }
+
+ var key = self.getMongoCondition(data);
+ if (key) {
+ parts.push(parse(data, key));
+ }
+ else {
+ var field = Object.keys(data)[0];
+ var value = data[field];
+
+ var operator = self.getMongoOperator(value);
+ if (operator === undefined) {
+ Utils.error('MongoParse', 'Invalid MongoDB query format');
+ }
+
+ var mdbrl = self.settings.mongoRuleOperators[operator];
+ if (mdbrl === undefined) {
+ Utils.error('UndefinedMongoOperator', 'JSON Rule operation unknown for operator "{0}"', operator);
+ }
+
+ var opVal = mdbrl.call(self, value);
+
+ var id = self.getMongoDBFieldID(field, value);
+
+ /**
+ * Modifies the rule generated from the MongoDB expression
+ * @event changer:mongoToRule
+ * @memberof module:plugins.MongoDbSupport
+ * @param {object} rule
+ * @param {object} expression
+ * @returns {object}
+ */
+ var rule = self.change('mongoToRule', {
+ id: id,
+ field: field,
+ operator: opVal.op,
+ value: opVal.val
+ }, data);
+
+ parts.push(rule);
+ }
+ });
+
+ /**
+ * Modifies the group generated from the MongoDB expression
+ * @event changer:mongoToGroup
+ * @memberof module:plugins.MongoDbSupport
+ * @param {object} group
+ * @param {object} expression
+ * @returns {object}
+ */
+ return self.change('mongoToGroup', {
+ condition: topKey.replace('$', '').toUpperCase(),
+ rules: parts
+ }, data);
+ }(query, key));
+ },
+
+ /**
+ * Sets rules a from MongoDB query
+ * @see module:plugins.MongoDbSupport.getRulesFromMongo
+ */
+ setRulesFromMongo: function(query) {
+ this.setRules(this.getRulesFromMongo(query));
+ },
+
+ /**
+ * Returns a filter identifier from the MongoDB field.
+ * Automatically use the only one filter with a matching field, fires a changer otherwise.
+ * @param {string} field
+ * @param {*} value
+ * @fires module:plugins.MongoDbSupport:changer:getMongoDBFieldID
+ * @returns {string}
+ * @private
+ */
+ getMongoDBFieldID: function(field, value) {
+ var matchingFilters = this.filters.filter(function(filter) {
+ return filter.field === field;
+ });
+
+ var id;
+ if (matchingFilters.length === 1) {
+ id = matchingFilters[0].id;
+ }
+ else {
+ /**
+ * Returns a filter identifier from the MongoDB field
+ * @event changer:getMongoDBFieldID
+ * @memberof module:plugins.MongoDbSupport
+ * @param {string} field
+ * @param {*} value
+ * @returns {string}
+ */
+ id = this.change('getMongoDBFieldID', field, value);
+ }
+
+ return id;
+ },
+
+ /**
+ * Finds which operator is used in a MongoDB sub-object
+ * @param {*} data
+ * @returns {string|undefined}
+ * @private
+ */
+ getMongoOperator: function(data) {
+ if (data !== null && typeof data === 'object') {
+ if (data.$gte !== undefined && data.$lte !== undefined) {
+ return 'between';
+ }
+ if (data.$lt !== undefined && data.$gt !== undefined) {
+ return 'not_between';
+ }
+
+ var knownKeys = Object.keys(data).filter(function(key) {
+ return !!this.settings.mongoRuleOperators[key];
+ }.bind(this));
+
+ if (knownKeys.length === 1) {
+ return knownKeys[0];
+ }
+ }
+ else {
+ return '$eq';
+ }
+ },
+
+
+ /**
+ * Returns the key corresponding to "$or" or "$and"
+ * @param {object} data
+ * @returns {string|undefined}
+ * @private
+ */
+ getMongoCondition: function(data) {
+ var keys = Object.keys(data);
+
+ for (var i = 0, l = keys.length; i < l; i++) {
+ if (keys[i].toLowerCase() === '$or' || keys[i].toLowerCase() === '$and') {
+ return keys[i];
+ }
+ }
+ }
+});
+
+
+/**
+ * @class NotGroup
+ * @memberof module:plugins
+ * @description Adds a "Not" checkbox in front of group conditions.
+ * @param {object} [options]
+ * @param {string} [options.icon_checked='glyphicon glyphicon-checked']
+ * @param {string} [options.icon_unchecked='glyphicon glyphicon-unchecked']
+ */
+QueryBuilder.define('not-group', function(options) {
+ var self = this;
+
+ // Bind events
+ this.on('afterInit', function() {
+ self.$el.on('click.queryBuilder', '[data-not=group]', function() {
+ var $group = $(this).closest(QueryBuilder.selectors.group_container);
+ var group = self.getModel($group);
+ group.not = !group.not;
+ });
+
+ self.model.on('update', function(e, node, field) {
+ if (node instanceof Group && field === 'not') {
+ self.updateGroupNot(node);
+ }
+ });
+ });
+
+ // Init "not" property
+ this.on('afterAddGroup', function(e, group) {
+ group.__.not = false;
+ });
+
+ // Modify templates
+ if (!options.disable_template) {
+ this.on('getGroupTemplate.filter', function(h) {
+ var $h = $(h.value);
+ $h.find(QueryBuilder.selectors.condition_container).prepend(
+ '' +
+ ' ' + self.translate('NOT') +
+ ' '
+ );
+ h.value = $h.prop('outerHTML');
+ });
+ }
+
+ // Export "not" to JSON
+ this.on('groupToJson.filter', function(e, group) {
+ e.value.not = group.not;
+ });
+
+ // Read "not" from JSON
+ this.on('jsonToGroup.filter', function(e, json) {
+ e.value.not = !!json.not;
+ });
+
+ // Export "not" to SQL
+ this.on('groupToSQL.filter', function(e, group) {
+ if (group.not) {
+ e.value = 'NOT ( ' + e.value + ' )';
+ }
+ });
+
+ // Parse "NOT" function from sqlparser
+ this.on('parseSQLNode.filter', function(e) {
+ if (e.value.name && e.value.name.toUpperCase() == 'NOT') {
+ e.value = e.value.arguments.value[0];
+
+ // if the there is no sub-group, create one
+ if (['AND', 'OR'].indexOf(e.value.operation.toUpperCase()) === -1) {
+ e.value = new SQLParser.nodes.Op(
+ self.settings.default_condition,
+ e.value,
+ null
+ );
+ }
+
+ e.value.not = true;
+ }
+ });
+
+ // Request to create sub-group if the "not" flag is set
+ this.on('sqlGroupsDistinct.filter', function(e, group, data, i) {
+ if (data.not && i > 0) {
+ e.value = true;
+ }
+ });
+
+ // Read "not" from parsed SQL
+ this.on('sqlToGroup.filter', function(e, data) {
+ e.value.not = !!data.not;
+ });
+
+ // Export "not" to Mongo
+ this.on('groupToMongo.filter', function(e, group) {
+ var key = '$' + group.condition.toLowerCase();
+ if (group.not && e.value[key]) {
+ e.value = { '$nor': [e.value] };
+ }
+ });
+
+ // Parse "$nor" operator from Mongo
+ this.on('parseMongoNode.filter', function(e) {
+ var keys = Object.keys(e.value);
+
+ if (keys[0] == '$nor') {
+ e.value = e.value[keys[0]][0];
+ e.value.not = true;
+ }
+ });
+
+ // Read "not" from parsed Mongo
+ this.on('mongoToGroup.filter', function(e, data) {
+ e.value.not = !!data.not;
+ });
+}, {
+ icon_unchecked: 'glyphicon glyphicon-unchecked',
+ icon_checked: 'glyphicon glyphicon-check',
+ disable_template: false
+});
+
+/**
+ * From {@link module:plugins.NotGroup}
+ * @name not
+ * @member {boolean}
+ * @memberof Group
+ * @instance
+ */
+Utils.defineModelProperties(Group, ['not']);
+
+QueryBuilder.selectors.group_not = QueryBuilder.selectors.group_header + ' [data-not=group]';
+
+QueryBuilder.extend(/** @lends module:plugins.NotGroup.prototype */ {
+ /**
+ * Performs actions when a group's not changes
+ * @param {Group} group
+ * @fires module:plugins.NotGroup.afterUpdateGroupNot
+ * @private
+ */
+ updateGroupNot: function(group) {
+ var options = this.plugins['not-group'];
+ group.$el.find('>' + QueryBuilder.selectors.group_not)
+ .toggleClass('active', group.not)
+ .find('i').attr('class', group.not ? options.icon_checked : options.icon_unchecked);
+
+ /**
+ * After the group's not flag has been modified
+ * @event afterUpdateGroupNot
+ * @memberof module:plugins.NotGroup
+ * @param {Group} group
+ */
+ this.trigger('afterUpdateGroupNot', group);
+
+ this.trigger('rulesChanged');
+ }
+});
+
+
+/**
+ * @class Sortable
+ * @memberof module:plugins
+ * @description Enables drag & drop sort of rules.
+ * @param {object} [options]
+ * @param {boolean} [options.inherit_no_drop=true]
+ * @param {boolean} [options.inherit_no_sortable=true]
+ * @param {string} [options.icon='glyphicon glyphicon-sort']
+ * @throws MissingLibraryError, ConfigError
+ */
+QueryBuilder.define('sortable', function(options) {
+ if (!('interact' in window)) {
+ Utils.error('MissingLibrary', 'interact.js is required to use "sortable" plugin. Get it here: http://interactjs.io');
+ }
+
+ if (options.default_no_sortable !== undefined) {
+ Utils.error(false, 'Config', 'Sortable plugin : "default_no_sortable" options is deprecated, use standard "default_rule_flags" and "default_group_flags" instead');
+ this.settings.default_rule_flags.no_sortable = this.settings.default_group_flags.no_sortable = options.default_no_sortable;
+ }
+
+ // recompute drop-zones during drag (when a rule is hidden)
+ interact.dynamicDrop(true);
+
+ // set move threshold to 10px
+ interact.pointerMoveTolerance(10);
+
+ var placeholder;
+ var ghost;
+ var src;
+ var moved;
+
+ // Init drag and drop
+ this.on('afterAddRule afterAddGroup', function(e, node) {
+ if (node == placeholder) {
+ return;
+ }
+
+ var self = e.builder;
+
+ // Inherit flags
+ if (options.inherit_no_sortable && node.parent && node.parent.flags.no_sortable) {
+ node.flags.no_sortable = true;
+ }
+ if (options.inherit_no_drop && node.parent && node.parent.flags.no_drop) {
+ node.flags.no_drop = true;
+ }
+
+ // Configure drag
+ if (!node.flags.no_sortable) {
+ interact(node.$el[0])
+ .draggable({
+ allowFrom: QueryBuilder.selectors.drag_handle,
+ onstart: function(event) {
+ moved = false;
+
+ // get model of dragged element
+ src = self.getModel(event.target);
+
+ // create ghost
+ ghost = src.$el.clone()
+ .appendTo(src.$el.parent())
+ .width(src.$el.outerWidth())
+ .addClass('dragging');
+
+ // create drop placeholder
+ var ph = $('
')
+ .height(src.$el.outerHeight());
+
+ placeholder = src.parent.addRule(ph, src.getPos());
+
+ // hide dragged element
+ src.$el.hide();
+ },
+ onmove: function(event) {
+ // make the ghost follow the cursor
+ ghost[0].style.top = event.clientY - 15 + 'px';
+ ghost[0].style.left = event.clientX - 15 + 'px';
+ },
+ onend: function(event) {
+ // starting from Interact 1.3.3, onend is called before ondrop
+ if (event.dropzone) {
+ moveSortableToTarget(src, $(event.relatedTarget), self);
+ moved = true;
+ }
+
+ // remove ghost
+ ghost.remove();
+ ghost = undefined;
+
+ // remove placeholder
+ placeholder.drop();
+ placeholder = undefined;
+
+ // show element
+ src.$el.css('display', '');
+
+ /**
+ * After a node has been moved with {@link module:plugins.Sortable}
+ * @event afterMove
+ * @memberof module:plugins.Sortable
+ * @param {Node} node
+ */
+ self.trigger('afterMove', src);
+
+ self.trigger('rulesChanged');
+ }
+ });
+ }
+
+ if (!node.flags.no_drop) {
+ // Configure drop on groups and rules
+ interact(node.$el[0])
+ .dropzone({
+ accept: QueryBuilder.selectors.rule_and_group_containers,
+ ondragenter: function(event) {
+ moveSortableToTarget(placeholder, $(event.target), self);
+ },
+ ondrop: function(event) {
+ if (!moved) {
+ moveSortableToTarget(src, $(event.target), self);
+ }
+ }
+ });
+
+ // Configure drop on group headers
+ if (node instanceof Group) {
+ interact(node.$el.find(QueryBuilder.selectors.group_header)[0])
+ .dropzone({
+ accept: QueryBuilder.selectors.rule_and_group_containers,
+ ondragenter: function(event) {
+ moveSortableToTarget(placeholder, $(event.target), self);
+ },
+ ondrop: function(event) {
+ if (!moved) {
+ moveSortableToTarget(src, $(event.target), self);
+ }
+ }
+ });
+ }
+ }
+ });
+
+ // Detach interactables
+ this.on('beforeDeleteRule beforeDeleteGroup', function(e, node) {
+ if (!e.isDefaultPrevented()) {
+ interact(node.$el[0]).unset();
+
+ if (node instanceof Group) {
+ interact(node.$el.find(QueryBuilder.selectors.group_header)[0]).unset();
+ }
+ }
+ });
+
+ // Remove drag handle from non-sortable items
+ this.on('afterApplyRuleFlags afterApplyGroupFlags', function(e, node) {
+ if (node.flags.no_sortable) {
+ node.$el.find('.drag-handle').remove();
+ }
+ });
+
+ // Modify templates
+ if (!options.disable_template) {
+ this.on('getGroupTemplate.filter', function(h, level) {
+ if (level > 1) {
+ var $h = $(h.value);
+ $h.find(QueryBuilder.selectors.condition_container).after('
');
+ h.value = $h.prop('outerHTML');
+ }
+ });
+
+ this.on('getRuleTemplate.filter', function(h) {
+ var $h = $(h.value);
+ $h.find(QueryBuilder.selectors.rule_header).after('
');
+ h.value = $h.prop('outerHTML');
+ });
+ }
+}, {
+ inherit_no_sortable: true,
+ inherit_no_drop: true,
+ icon: 'glyphicon glyphicon-sort',
+ disable_template: false
+});
+
+QueryBuilder.selectors.rule_and_group_containers = QueryBuilder.selectors.rule_container + ', ' + QueryBuilder.selectors.group_container;
+QueryBuilder.selectors.drag_handle = '.drag-handle';
+
+QueryBuilder.defaults({
+ default_rule_flags: {
+ no_sortable: false,
+ no_drop: false
+ },
+ default_group_flags: {
+ no_sortable: false,
+ no_drop: false
+ }
+});
+
+/**
+ * Moves an element (placeholder or actual object) depending on active target
+ * @memberof module:plugins.Sortable
+ * @param {Node} node
+ * @param {jQuery} target
+ * @param {QueryBuilder} [builder]
+ * @private
+ */
+function moveSortableToTarget(node, target, builder) {
+ var parent, method;
+ var Selectors = QueryBuilder.selectors;
+
+ // on rule
+ parent = target.closest(Selectors.rule_container);
+ if (parent.length) {
+ method = 'moveAfter';
+ }
+
+ // on group header
+ if (!method) {
+ parent = target.closest(Selectors.group_header);
+ if (parent.length) {
+ parent = target.closest(Selectors.group_container);
+ method = 'moveAtBegin';
+ }
+ }
+
+ // on group
+ if (!method) {
+ parent = target.closest(Selectors.group_container);
+ if (parent.length) {
+ method = 'moveAtEnd';
+ }
+ }
+
+ if (method) {
+ node[method](builder.getModel(parent));
+
+ // refresh radio value
+ if (builder && node instanceof Rule) {
+ builder.setRuleInputValue(node, node.value);
+ }
+ }
+}
+
+
+/**
+ * @class SqlSupport
+ * @memberof module:plugins
+ * @description Allows to export rules as a SQL WHERE statement as well as populating the builder from an SQL query.
+ * @param {object} [options]
+ * @param {boolean} [options.boolean_as_integer=true] - `true` to convert boolean values to integer in the SQL output
+ */
+QueryBuilder.define('sql-support', function(options) {
+
+}, {
+ boolean_as_integer: true
+});
+
+QueryBuilder.defaults({
+ // operators for internal -> SQL conversion
+ sqlOperators: {
+ equal: { op: '= ?' },
+ not_equal: { op: '!= ?' },
+ in: { op: 'IN(?)', sep: ', ' },
+ not_in: { op: 'NOT IN(?)', sep: ', ' },
+ less: { op: '< ?' },
+ less_or_equal: { op: '<= ?' },
+ greater: { op: '> ?' },
+ greater_or_equal: { op: '>= ?' },
+ between: { op: 'BETWEEN ?', sep: ' AND ' },
+ not_between: { op: 'NOT BETWEEN ?', sep: ' AND ' },
+ begins_with: { op: 'LIKE(?)', mod: '{0}%' },
+ not_begins_with: { op: 'NOT LIKE(?)', mod: '{0}%' },
+ contains: { op: 'LIKE(?)', mod: '%{0}%' },
+ not_contains: { op: 'NOT LIKE(?)', mod: '%{0}%' },
+ ends_with: { op: 'LIKE(?)', mod: '%{0}' },
+ not_ends_with: { op: 'NOT LIKE(?)', mod: '%{0}' },
+ is_empty: { op: '= \'\'' },
+ is_not_empty: { op: '!= \'\'' },
+ is_null: { op: 'IS NULL' },
+ is_not_null: { op: 'IS NOT NULL' }
+ },
+
+ // operators for SQL -> internal conversion
+ sqlRuleOperator: {
+ '=': function(v) {
+ return {
+ val: v,
+ op: v === '' ? 'is_empty' : 'equal'
+ };
+ },
+ '!=': function(v) {
+ return {
+ val: v,
+ op: v === '' ? 'is_not_empty' : 'not_equal'
+ };
+ },
+ 'LIKE': function(v) {
+ if (v.slice(0, 1) == '%' && v.slice(-1) == '%') {
+ return {
+ val: v.slice(1, -1),
+ op: 'contains'
+ };
+ }
+ else if (v.slice(0, 1) == '%') {
+ return {
+ val: v.slice(1),
+ op: 'ends_with'
+ };
+ }
+ else if (v.slice(-1) == '%') {
+ return {
+ val: v.slice(0, -1),
+ op: 'begins_with'
+ };
+ }
+ else {
+ Utils.error('SQLParse', 'Invalid value for LIKE operator "{0}"', v);
+ }
+ },
+ 'NOT LIKE': function(v) {
+ if (v.slice(0, 1) == '%' && v.slice(-1) == '%') {
+ return {
+ val: v.slice(1, -1),
+ op: 'not_contains'
+ };
+ }
+ else if (v.slice(0, 1) == '%') {
+ return {
+ val: v.slice(1),
+ op: 'not_ends_with'
+ };
+ }
+ else if (v.slice(-1) == '%') {
+ return {
+ val: v.slice(0, -1),
+ op: 'not_begins_with'
+ };
+ }
+ else {
+ Utils.error('SQLParse', 'Invalid value for NOT LIKE operator "{0}"', v);
+ }
+ },
+ 'IN': function(v) {
+ return { val: v, op: 'in' };
+ },
+ 'NOT IN': function(v) {
+ return { val: v, op: 'not_in' };
+ },
+ '<': function(v) {
+ return { val: v, op: 'less' };
+ },
+ '<=': function(v) {
+ return { val: v, op: 'less_or_equal' };
+ },
+ '>': function(v) {
+ return { val: v, op: 'greater' };
+ },
+ '>=': function(v) {
+ return { val: v, op: 'greater_or_equal' };
+ },
+ 'BETWEEN': function(v) {
+ return { val: v, op: 'between' };
+ },
+ 'NOT BETWEEN': function(v) {
+ return { val: v, op: 'not_between' };
+ },
+ 'IS': function(v) {
+ if (v !== null) {
+ Utils.error('SQLParse', 'Invalid value for IS operator');
+ }
+ return { val: null, op: 'is_null' };
+ },
+ 'IS NOT': function(v) {
+ if (v !== null) {
+ Utils.error('SQLParse', 'Invalid value for IS operator');
+ }
+ return { val: null, op: 'is_not_null' };
+ }
+ },
+
+ // statements for internal -> SQL conversion
+ sqlStatements: {
+ 'question_mark': function() {
+ var params = [];
+ return {
+ add: function(rule, value) {
+ params.push(value);
+ return '?';
+ },
+ run: function() {
+ return params;
+ }
+ };
+ },
+
+ 'numbered': function(char) {
+ if (!char || char.length > 1) char = '$';
+ var index = 0;
+ var params = [];
+ return {
+ add: function(rule, value) {
+ params.push(value);
+ index++;
+ return char + index;
+ },
+ run: function() {
+ return params;
+ }
+ };
+ },
+
+ 'named': function(char) {
+ if (!char || char.length > 1) char = ':';
+ var indexes = {};
+ var params = {};
+ return {
+ add: function(rule, value) {
+ if (!indexes[rule.field]) indexes[rule.field] = 1;
+ var key = rule.field + '_' + (indexes[rule.field]++);
+ params[key] = value;
+ return char + key;
+ },
+ run: function() {
+ return params;
+ }
+ };
+ }
+ },
+
+ // statements for SQL -> internal conversion
+ sqlRuleStatement: {
+ 'question_mark': function(values) {
+ var index = 0;
+ return {
+ parse: function(v) {
+ return v == '?' ? values[index++] : v;
+ },
+ esc: function(sql) {
+ return sql.replace(/\?/g, '\'?\'');
+ }
+ };
+ },
+
+ 'numbered': function(values, char) {
+ if (!char || char.length > 1) char = '$';
+ var regex1 = new RegExp('^\\' + char + '[0-9]+$');
+ var regex2 = new RegExp('\\' + char + '([0-9]+)', 'g');
+ return {
+ parse: function(v) {
+ return regex1.test(v) ? values[v.slice(1) - 1] : v;
+ },
+ esc: function(sql) {
+ return sql.replace(regex2, '\'' + (char == '$' ? '$$' : char) + '$1\'');
+ }
+ };
+ },
+
+ 'named': function(values, char) {
+ if (!char || char.length > 1) char = ':';
+ var regex1 = new RegExp('^\\' + char);
+ var regex2 = new RegExp('\\' + char + '(' + Object.keys(values).join('|') + ')', 'g');
+ return {
+ parse: function(v) {
+ return regex1.test(v) ? values[v.slice(1)] : v;
+ },
+ esc: function(sql) {
+ return sql.replace(regex2, '\'' + (char == '$' ? '$$' : char) + '$1\'');
+ }
+ };
+ }
+ }
+});
+
+/**
+ * @typedef {object} SqlQuery
+ * @memberof module:plugins.SqlSupport
+ * @property {string} sql
+ * @property {object} params
+ */
+
+QueryBuilder.extend(/** @lends module:plugins.SqlSupport.prototype */ {
+ /**
+ * Returns rules as a SQL query
+ * @param {boolean|string} [stmt] - use prepared statements: false, 'question_mark', 'numbered', 'numbered(@)', 'named', 'named(@)'
+ * @param {boolean} [nl=false] output with new lines
+ * @param {object} [data] - current rules by default
+ * @returns {module:plugins.SqlSupport.SqlQuery}
+ * @fires module:plugins.SqlSupport.changer:getSQLField
+ * @fires module:plugins.SqlSupport.changer:ruleToSQL
+ * @fires module:plugins.SqlSupport.changer:groupToSQL
+ * @throws UndefinedSQLConditionError, UndefinedSQLOperatorError
+ */
+ getSQL: function(stmt, nl, data) {
+ data = (data === undefined) ? this.getRules() : data;
+
+ if (!data) {
+ return null;
+ }
+
+ nl = !!nl ? '\n' : ' ';
+ var boolean_as_integer = this.getPluginOptions('sql-support', 'boolean_as_integer');
+
+ if (stmt === true) {
+ stmt = 'question_mark';
+ }
+ if (typeof stmt == 'string') {
+ var config = getStmtConfig(stmt);
+ stmt = this.settings.sqlStatements[config[1]](config[2]);
+ }
+
+ var self = this;
+
+ var sql = (function parse(group) {
+ if (!group.condition) {
+ group.condition = self.settings.default_condition;
+ }
+ if (['AND', 'OR'].indexOf(group.condition.toUpperCase()) === -1) {
+ Utils.error('UndefinedSQLCondition', 'Unable to build SQL query with condition "{0}"', group.condition);
+ }
+
+ if (!group.rules) {
+ return '';
+ }
+
+ var parts = [];
+
+ group.rules.forEach(function(rule) {
+ if (rule.rules && rule.rules.length > 0) {
+ parts.push('(' + nl + parse(rule) + nl + ')' + nl);
+ }
+ else {
+ var sql = self.settings.sqlOperators[rule.operator];
+ var ope = self.getOperatorByType(rule.operator);
+ var value = '';
+
+ if (sql === undefined) {
+ Utils.error('UndefinedSQLOperator', 'Unknown SQL operation for operator "{0}"', rule.operator);
+ }
+
+ if (ope.nb_inputs !== 0) {
+ if (!(rule.value instanceof Array)) {
+ rule.value = [rule.value];
+ }
+
+ rule.value.forEach(function(v, i) {
+ if (i > 0) {
+ value += sql.sep;
+ }
+
+ if (rule.type == 'boolean' && boolean_as_integer) {
+ v = v ? 1 : 0;
+ }
+ else if (!stmt && rule.type !== 'integer' && rule.type !== 'double' && rule.type !== 'boolean') {
+ v = Utils.escapeString(v);
+ }
+
+ if (sql.mod) {
+ v = Utils.fmt(sql.mod, v);
+ }
+
+ if (stmt) {
+ value += stmt.add(rule, v);
+ }
+ else {
+ if (typeof v == 'string') {
+ v = '\'' + v + '\'';
+ }
+
+ value += v;
+ }
+ });
+ }
+
+ var sqlFn = function(v) {
+ return sql.op.replace('?', function() {
+ return v;
+ });
+ };
+
+ /**
+ * Modifies the SQL field used by a rule
+ * @event changer:getSQLField
+ * @memberof module:plugins.SqlSupport
+ * @param {string} field
+ * @param {Rule} rule
+ * @returns {string}
+ */
+ var field = self.change('getSQLField', rule.field, rule);
+
+ var ruleExpression = field + ' ' + sqlFn(value);
+
+ /**
+ * Modifies the SQL generated for a rule
+ * @event changer:ruleToSQL
+ * @memberof module:plugins.SqlSupport
+ * @param {string} expression
+ * @param {Rule} rule
+ * @param {*} value
+ * @param {function} valueWrapper - function that takes the value and adds the operator
+ * @returns {string}
+ */
+ parts.push(self.change('ruleToSQL', ruleExpression, rule, value, sqlFn));
+ }
+ });
+
+ var groupExpression = parts.join(' ' + group.condition + nl);
+
+ /**
+ * Modifies the SQL generated for a group
+ * @event changer:groupToSQL
+ * @memberof module:plugins.SqlSupport
+ * @param {string} expression
+ * @param {Group} group
+ * @returns {string}
+ */
+ return self.change('groupToSQL', groupExpression, group);
+ }(data));
+
+ if (stmt) {
+ return {
+ sql: sql,
+ params: stmt.run()
+ };
+ }
+ else {
+ return {
+ sql: sql
+ };
+ }
+ },
+
+ /**
+ * Convert a SQL query to rules
+ * @param {string|module:plugins.SqlSupport.SqlQuery} query
+ * @param {boolean|string} stmt
+ * @returns {object}
+ * @fires module:plugins.SqlSupport.changer:parseSQLNode
+ * @fires module:plugins.SqlSupport.changer:getSQLFieldID
+ * @fires module:plugins.SqlSupport.changer:sqlToRule
+ * @fires module:plugins.SqlSupport.changer:sqlToGroup
+ * @throws MissingLibraryError, SQLParseError, UndefinedSQLOperatorError
+ */
+ getRulesFromSQL: function(query, stmt) {
+ if (!('SQLParser' in window)) {
+ Utils.error('MissingLibrary', 'SQLParser is required to parse SQL queries. Get it here https://github.com/mistic100/sql-parser');
+ }
+
+ var self = this;
+
+ if (typeof query == 'string') {
+ query = { sql: query };
+ }
+
+ if (stmt === true) stmt = 'question_mark';
+ if (typeof stmt == 'string') {
+ var config = getStmtConfig(stmt);
+ stmt = this.settings.sqlRuleStatement[config[1]](query.params, config[2]);
+ }
+
+ if (stmt) {
+ query.sql = stmt.esc(query.sql);
+ }
+
+ if (query.sql.toUpperCase().indexOf('SELECT') !== 0) {
+ query.sql = 'SELECT * FROM table WHERE ' + query.sql;
+ }
+
+ var parsed = SQLParser.parse(query.sql);
+
+ if (!parsed.where) {
+ Utils.error('SQLParse', 'No WHERE clause found');
+ }
+
+ /**
+ * Custom parsing of an AST node generated by SQLParser, you can return a sub-part of the tree, or a well formed group or rule JSON
+ * @event changer:parseSQLNode
+ * @memberof module:plugins.SqlSupport
+ * @param {object} AST node
+ * @returns {object} tree, rule or group
+ */
+ var data = self.change('parseSQLNode', parsed.where.conditions);
+
+ // a plugin returned a group
+ if ('rules' in data && 'condition' in data) {
+ return data;
+ }
+
+ // a plugin returned a rule
+ if ('id' in data && 'operator' in data && 'value' in data) {
+ return {
+ condition: this.settings.default_condition,
+ rules: [data]
+ };
+ }
+
+ // create root group
+ var out = self.change('sqlToGroup', {
+ condition: this.settings.default_condition,
+ rules: []
+ }, data);
+
+ // keep track of current group
+ var curr = out;
+
+ (function flatten(data, i) {
+ if (data === null) {
+ return;
+ }
+
+ // allow plugins to manually parse or handle special cases
+ data = self.change('parseSQLNode', data);
+
+ // a plugin returned a group
+ if ('rules' in data && 'condition' in data) {
+ curr.rules.push(data);
+ return;
+ }
+
+ // a plugin returned a rule
+ if ('id' in data && 'operator' in data && 'value' in data) {
+ curr.rules.push(data);
+ return;
+ }
+
+ // data must be a SQL parser node
+ if (!('left' in data) || !('right' in data) || !('operation' in data)) {
+ Utils.error('SQLParse', 'Unable to parse WHERE clause');
+ }
+
+ // it's a node
+ if (['AND', 'OR'].indexOf(data.operation.toUpperCase()) !== -1) {
+ // create a sub-group if the condition is not the same and it's not the first level
+
+ /**
+ * Given an existing group and an AST node, determines if a sub-group must be created
+ * @event changer:sqlGroupsDistinct
+ * @memberof module:plugins.SqlSupport
+ * @param {boolean} create - true by default if the group condition is different
+ * @param {object} group
+ * @param {object} AST
+ * @param {int} current group level
+ * @returns {boolean}
+ */
+ var createGroup = self.change('sqlGroupsDistinct', i > 0 && curr.condition != data.operation.toUpperCase(), curr, data, i);
+
+ if (createGroup) {
+ /**
+ * Modifies the group generated from the SQL expression (this is called before the group is filled with rules)
+ * @event changer:sqlToGroup
+ * @memberof module:plugins.SqlSupport
+ * @param {object} group
+ * @param {object} AST
+ * @returns {object}
+ */
+ var group = self.change('sqlToGroup', {
+ condition: self.settings.default_condition,
+ rules: []
+ }, data);
+
+ curr.rules.push(group);
+ curr = group;
+ }
+
+ curr.condition = data.operation.toUpperCase();
+ i++;
+
+ // some magic !
+ var next = curr;
+ flatten(data.left, i);
+
+ curr = next;
+ flatten(data.right, i);
+ }
+ // it's a leaf
+ else {
+ if ($.isPlainObject(data.right.value)) {
+ Utils.error('SQLParse', 'Value format not supported for {0}.', data.left.value);
+ }
+
+ // convert array
+ var value;
+ if ($.isArray(data.right.value)) {
+ value = data.right.value.map(function(v) {
+ return v.value;
+ });
+ }
+ else {
+ value = data.right.value;
+ }
+
+ // get actual values
+ if (stmt) {
+ if ($.isArray(value)) {
+ value = value.map(stmt.parse);
+ }
+ else {
+ value = stmt.parse(value);
+ }
+ }
+
+ // convert operator
+ var operator = data.operation.toUpperCase();
+ if (operator == '<>') {
+ operator = '!=';
+ }
+
+ var sqlrl = self.settings.sqlRuleOperator[operator];
+ if (sqlrl === undefined) {
+ Utils.error('UndefinedSQLOperator', 'Invalid SQL operation "{0}".', data.operation);
+ }
+
+ var opVal = sqlrl.call(this, value, data.operation);
+
+ // find field name
+ var field;
+ if ('values' in data.left) {
+ field = data.left.values.join('.');
+ }
+ else if ('value' in data.left) {
+ field = data.left.value;
+ }
+ else {
+ Utils.error('SQLParse', 'Cannot find field name in {0}', JSON.stringify(data.left));
+ }
+
+ var id = self.getSQLFieldID(field, value);
+
+ /**
+ * Modifies the rule generated from the SQL expression
+ * @event changer:sqlToRule
+ * @memberof module:plugins.SqlSupport
+ * @param {object} rule
+ * @param {object} AST
+ * @returns {object}
+ */
+ var rule = self.change('sqlToRule', {
+ id: id,
+ field: field,
+ operator: opVal.op,
+ value: opVal.val
+ }, data);
+
+ curr.rules.push(rule);
+ }
+ }(data, 0));
+
+ return out;
+ },
+
+ /**
+ * Sets the builder's rules from a SQL query
+ * @see module:plugins.SqlSupport.getRulesFromSQL
+ */
+ setRulesFromSQL: function(query, stmt) {
+ this.setRules(this.getRulesFromSQL(query, stmt));
+ },
+
+ /**
+ * Returns a filter identifier from the SQL field.
+ * Automatically use the only one filter with a matching field, fires a changer otherwise.
+ * @param {string} field
+ * @param {*} value
+ * @fires module:plugins.SqlSupport:changer:getSQLFieldID
+ * @returns {string}
+ * @private
+ */
+ getSQLFieldID: function(field, value) {
+ var matchingFilters = this.filters.filter(function(filter) {
+ return filter.field.toLowerCase() === field.toLowerCase();
+ });
+
+ var id;
+ if (matchingFilters.length === 1) {
+ id = matchingFilters[0].id;
+ }
+ else {
+ /**
+ * Returns a filter identifier from the SQL field
+ * @event changer:getSQLFieldID
+ * @memberof module:plugins.SqlSupport
+ * @param {string} field
+ * @param {*} value
+ * @returns {string}
+ */
+ id = this.change('getSQLFieldID', field, value);
+ }
+
+ return id;
+ }
+});
+
+/**
+ * Parses the statement configuration
+ * @memberof module:plugins.SqlSupport
+ * @param {string} stmt
+ * @returns {Array} null, mode, option
+ * @private
+ */
+function getStmtConfig(stmt) {
+ var config = stmt.match(/(question_mark|numbered|named)(?:\((.)\))?/);
+ if (!config) config = [null, 'question_mark', undefined];
+ return config;
+}
+
+
+/**
+ * @class UniqueFilter
+ * @memberof module:plugins
+ * @description Allows to define some filters as "unique": ie which can be used for only one rule, globally or in the same group.
+ */
+QueryBuilder.define('unique-filter', function() {
+ this.status.used_filters = {};
+
+ this.on('afterUpdateRuleFilter', this.updateDisabledFilters);
+ this.on('afterDeleteRule', this.updateDisabledFilters);
+ this.on('afterCreateRuleFilters', this.applyDisabledFilters);
+ this.on('afterReset', this.clearDisabledFilters);
+ this.on('afterClear', this.clearDisabledFilters);
+
+ // Ensure that the default filter is not already used if unique
+ this.on('getDefaultFilter.filter', function(e, model) {
+ var self = e.builder;
+
+ self.updateDisabledFilters();
+
+ if (e.value.id in self.status.used_filters) {
+ var found = self.filters.some(function(filter) {
+ if (!(filter.id in self.status.used_filters) || self.status.used_filters[filter.id].length > 0 && self.status.used_filters[filter.id].indexOf(model.parent) === -1) {
+ e.value = filter;
+ return true;
+ }
+ });
+
+ if (!found) {
+ Utils.error(false, 'UniqueFilter', 'No more non-unique filters available');
+ e.value = undefined;
+ }
+ }
+ });
+});
+
+QueryBuilder.extend(/** @lends module:plugins.UniqueFilter.prototype */ {
+ /**
+ * Updates the list of used filters
+ * @param {$.Event} [e]
+ * @private
+ */
+ updateDisabledFilters: function(e) {
+ var self = e ? e.builder : this;
+
+ self.status.used_filters = {};
+
+ if (!self.model) {
+ return;
+ }
+
+ // get used filters
+ (function walk(group) {
+ group.each(function(rule) {
+ if (rule.filter && rule.filter.unique) {
+ if (!self.status.used_filters[rule.filter.id]) {
+ self.status.used_filters[rule.filter.id] = [];
+ }
+ if (rule.filter.unique == 'group') {
+ self.status.used_filters[rule.filter.id].push(rule.parent);
+ }
+ }
+ }, function(group) {
+ walk(group);
+ });
+ }(self.model.root));
+
+ self.applyDisabledFilters(e);
+ },
+
+ /**
+ * Clear the list of used filters
+ * @param {$.Event} [e]
+ * @private
+ */
+ clearDisabledFilters: function(e) {
+ var self = e ? e.builder : this;
+
+ self.status.used_filters = {};
+
+ self.applyDisabledFilters(e);
+ },
+
+ /**
+ * Disabled filters depending on the list of used ones
+ * @param {$.Event} [e]
+ * @private
+ */
+ applyDisabledFilters: function(e) {
+ var self = e ? e.builder : this;
+
+ // re-enable everything
+ self.$el.find(QueryBuilder.selectors.filter_container + ' option').prop('disabled', false);
+
+ // disable some
+ $.each(self.status.used_filters, function(filterId, groups) {
+ if (groups.length === 0) {
+ self.$el.find(QueryBuilder.selectors.filter_container + ' option[value="' + filterId + '"]:not(:selected)').prop('disabled', true);
+ }
+ else {
+ groups.forEach(function(group) {
+ group.each(function(rule) {
+ rule.$el.find(QueryBuilder.selectors.filter_container + ' option[value="' + filterId + '"]:not(:selected)').prop('disabled', true);
+ });
+ });
+ }
+ });
+
+ // update Selectpicker
+ if (self.settings.plugins && self.settings.plugins['bt-selectpicker']) {
+ self.$el.find(QueryBuilder.selectors.rule_filter).selectpicker('render');
+ }
+ }
+});
+
+
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Locale: English (en)
+ * Author: Damien "Mistic" Sorel, http://www.strangeplanet.fr
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+QueryBuilder.regional['en'] = {
+ "__locale": "English (en)",
+ "__author": "Damien \"Mistic\" Sorel, http://www.strangeplanet.fr",
+ "add_rule": "Add rule",
+ "add_group": "Add group",
+ "delete_rule": "Delete",
+ "delete_group": "Delete",
+ "conditions": {
+ "AND": "AND",
+ "OR": "OR"
+ },
+ "operators": {
+ "equal": "equal",
+ "not_equal": "not equal",
+ "in": "in",
+ "not_in": "not in",
+ "less": "less",
+ "less_or_equal": "less or equal",
+ "greater": "greater",
+ "greater_or_equal": "greater or equal",
+ "between": "between",
+ "not_between": "not between",
+ "begins_with": "begins with",
+ "not_begins_with": "doesn't begin with",
+ "contains": "contains",
+ "not_contains": "doesn't contain",
+ "ends_with": "ends with",
+ "not_ends_with": "doesn't end with",
+ "is_empty": "is empty",
+ "is_not_empty": "is not empty",
+ "is_null": "is null",
+ "is_not_null": "is not null"
+ },
+ "errors": {
+ "no_filter": "No filter selected",
+ "empty_group": "The group is empty",
+ "radio_empty": "No value selected",
+ "checkbox_empty": "No value selected",
+ "select_empty": "No value selected",
+ "string_empty": "Empty value",
+ "string_exceed_min_length": "Must contain at least {0} characters",
+ "string_exceed_max_length": "Must not contain more than {0} characters",
+ "string_invalid_format": "Invalid format ({0})",
+ "number_nan": "Not a number",
+ "number_not_integer": "Not an integer",
+ "number_not_double": "Not a real number",
+ "number_exceed_min": "Must be greater than {0}",
+ "number_exceed_max": "Must be lower than {0}",
+ "number_wrong_step": "Must be a multiple of {0}",
+ "number_between_invalid": "Invalid values, {0} is greater than {1}",
+ "datetime_empty": "Empty value",
+ "datetime_invalid": "Invalid date format ({0})",
+ "datetime_exceed_min": "Must be after {0}",
+ "datetime_exceed_max": "Must be before {0}",
+ "datetime_between_invalid": "Invalid values, {0} is greater than {1}",
+ "boolean_not_valid": "Not a boolean",
+ "operator_not_multiple": "Operator \"{1}\" cannot accept multiple values"
+ },
+ "invert": "Invert",
+ "NOT": "NOT"
+};
+
+QueryBuilder.defaults({ lang_code: 'en' });
+return QueryBuilder;
+
+}));
diff --git a/dist/js/query-builder.standalone.min.js b/dist/js/query-builder.standalone.min.js
new file mode 100644
index 00000000..6767c7e3
--- /dev/null
+++ b/dist/js/query-builder.standalone.min.js
@@ -0,0 +1,8 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Copyright 2014-2020 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+!function(){"use strict";var a,u={name:"doT",version:"1.1.1",templateSettings:{evaluate:/\{\{([\s\S]+?(\}?)+)\}\}/g,interpolate:/\{\{=([\s\S]+?)\}\}/g,encode:/\{\{!([\s\S]+?)\}\}/g,use:/\{\{#([\s\S]+?)\}\}/g,useParams:/(^|[^\w$])def(?:\.|\[[\'\"])([\w$\.]+)(?:[\'\"]\])?\s*\:\s*([\w$\.]+|\"[^\"]+\"|\'[^\']+\'|\{[^\}]+\})/g,define:/\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,defineParams:/^\s*([\w$]+):([\s\S]+)/,conditional:/\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g,iterate:/\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g,varname:"it",strip:!0,append:!0,selfcontained:!1,doNotSkipEncoded:!1},template:void 0,compile:void 0,log:!0};u.encodeHTMLSource=function(e){var t={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"},r=e?/[&<>"'\/]/g:/&(?!#?\w+;)|<|>|"|'|\//g;return function(e){return e?e.toString().replace(r,function(e){return t[e]||e}):""}},a=function(){return this||(0,eval)("this")}(),"undefined"!=typeof module&&module.exports?module.exports=u:"function"==typeof define&&define.amd?define("doT",function(){return u}):a.doT=u;var p={append:{start:"'+(",end:")+'",startencode:"'+encodeHTML("},split:{start:"';out+=(",end:");out+='",startencode:"';out+=encodeHTML("}},d=/$^/;function c(e){return e.replace(/\\('|\\)/g,"$1").replace(/[\r\t\n]/g," ")}u.template=function(e,t,r){var i,n,o=(t=t||u.templateSettings).append?p.append:p.split,l=0,s=t.use||t.define?function i(n,e,o){return("string"==typeof e?e:e.toString()).replace(n.define||d,function(e,i,t,r){return 0===i.indexOf("def.")&&(i=i.substring(4)),i in o||(":"===t?(n.defineParams&&r.replace(n.defineParams,function(e,t,r){o[i]={arg:t,text:r}}),i in o||(o[i]=r)):new Function("def","def['"+i+"']="+r)(o)),""}).replace(n.use||d,function(e,t){n.useParams&&(t=t.replace(n.useParams,function(e,t,r,i){if(o[r]&&o[r].arg&&i){var n=(r+":"+i).replace(/'|\\/g,"_");return o.__exp=o.__exp||{},o.__exp[n]=o[r].text.replace(new RegExp("(^|[^\\w$])"+o[r].arg+"([^\\w$])","g"),"$1"+i+"$2"),t+"def.__exp['"+n+"']"}}));var r=new Function("def","return "+t)(o);return r?i(n,r,o):r})}(t,e,r||{}):e;s=("var out='"+(t.strip?s.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g," ").replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,""):s).replace(/'|\\/g,"\\$&").replace(t.interpolate||d,function(e,t){return o.start+c(t)+o.end}).replace(t.encode||d,function(e,t){return i=!0,o.startencode+c(t)+o.end}).replace(t.conditional||d,function(e,t,r){return t?r?"';}else if("+c(r)+"){out+='":"';}else{out+='":r?"';if("+c(r)+"){out+='":"';}out+='"}).replace(t.iterate||d,function(e,t,r,i){return t?(l+=1,n=i||"i"+l,t=c(t),"';var arr"+l+"="+t+";if(arr"+l+"){var "+r+","+n+"=-1,l"+l+"=arr"+l+".length-1;while("+n+".rules-list",group_condition:".rules-group-header [name$=_cond]",rule_filter:".rule-filter-container [name$=_filter]",rule_operator:".rule-operator-container [name$=_operator]",rule_value:".rule-value-container [name*=_value_]",add_rule:"[data-add=rule]",delete_rule:"[data-delete=rule]",add_group:"[data-add=group]",delete_group:"[data-delete=group]"},c.templates={},c.regional={},c.OPERATORS={equal:{type:"equal",nb_inputs:1,multiple:!1,apply_to:["string","number","datetime","boolean"]},not_equal:{type:"not_equal",nb_inputs:1,multiple:!1,apply_to:["string","number","datetime","boolean"]},in:{type:"in",nb_inputs:1,multiple:!0,apply_to:["string","number","datetime"]},not_in:{type:"not_in",nb_inputs:1,multiple:!0,apply_to:["string","number","datetime"]},less:{type:"less",nb_inputs:1,multiple:!1,apply_to:["number","datetime"]},less_or_equal:{type:"less_or_equal",nb_inputs:1,multiple:!1,apply_to:["number","datetime"]},greater:{type:"greater",nb_inputs:1,multiple:!1,apply_to:["number","datetime"]},greater_or_equal:{type:"greater_or_equal",nb_inputs:1,multiple:!1,apply_to:["number","datetime"]},between:{type:"between",nb_inputs:2,multiple:!1,apply_to:["number","datetime"]},not_between:{type:"not_between",nb_inputs:2,multiple:!1,apply_to:["number","datetime"]},begins_with:{type:"begins_with",nb_inputs:1,multiple:!1,apply_to:["string"]},not_begins_with:{type:"not_begins_with",nb_inputs:1,multiple:!1,apply_to:["string"]},contains:{type:"contains",nb_inputs:1,multiple:!1,apply_to:["string"]},not_contains:{type:"not_contains",nb_inputs:1,multiple:!1,apply_to:["string"]},ends_with:{type:"ends_with",nb_inputs:1,multiple:!1,apply_to:["string"]},not_ends_with:{type:"not_ends_with",nb_inputs:1,multiple:!1,apply_to:["string"]},is_empty:{type:"is_empty",nb_inputs:0,multiple:!1,apply_to:["string"]},is_not_empty:{type:"is_not_empty",nb_inputs:0,multiple:!1,apply_to:["string"]},is_null:{type:"is_null",nb_inputs:0,multiple:!1,apply_to:["string","number","datetime","boolean"]},is_not_null:{type:"is_not_null",nb_inputs:0,multiple:!1,apply_to:["string","number","datetime","boolean"]}},c.DEFAULTS={filters:[],plugins:[],sort_filters:!1,display_errors:!0,allow_groups:-1,allow_empty:!1,conditions:["AND","OR"],default_condition:"AND",inputs_separator:" , ",select_placeholder:"------",display_empty_filter:!0,default_filter:null,optgroups:{},default_rule_flags:{filter_readonly:!1,operator_readonly:!1,value_readonly:!1,no_delete:!1},default_group_flags:{condition_readonly:!1,no_add_rule:!1,no_add_group:!1,no_delete:!1},templates:{group:null,rule:null,filterSelect:null,operatorSelect:null,ruleValueSelect:null},lang_code:"en",lang:{},operators:["equal","not_equal","in","not_in","less","less_or_equal","greater","greater_or_equal","between","not_between","begins_with","not_begins_with","contains","not_contains","ends_with","not_ends_with","is_empty","is_not_empty","is_null","is_not_null"],icons:{add_group:"fas fa-plus-circle",add_rule:"fas fa-plus",remove_group:"fas fa-times",remove_rule:"fas fa-times",error:"fas fa-exclamation-triangle"}},c.plugins={},c.defaults=function(e){if("object"!=typeof e)return"string"==typeof e?"object"==typeof c.DEFAULTS[e]?$.extend(!0,{},c.DEFAULTS[e]):c.DEFAULTS[e]:$.extend(!0,{},c.DEFAULTS);$.extendext(!0,"replace",c.DEFAULTS,e)},c.define=function(e,t,r){c.plugins[e]={fct:t,def:r||{}}},c.extend=function(e){$.extend(c.prototype,e)},c.prototype.initPlugins=function(){if(this.plugins){if($.isArray(this.plugins)){var t={};this.plugins.forEach(function(e){t[e]=null}),this.plugins=t}Object.keys(this.plugins).forEach(function(e){e in c.plugins?(this.plugins[e]=$.extend(!0,{},c.plugins[e].def,this.plugins[e]||{}),c.plugins[e].fct.call(this,this.plugins[e])):h.error("Config",'Unable to find plugin "{0}"',e)},this)}},c.prototype.getPluginOptions=function(e,t){var r;if(this.plugins&&this.plugins[e]?r=this.plugins[e]:c.plugins[e]&&(r=c.plugins[e].def),r)return t?r[t]:r;h.error("Config",'Unable to find plugin "{0}"',e)},c.prototype.init=function(e){this.trigger("afterInit"),e?(this.setRules(e),delete this.settings.rules):this.setRoot(!0)},c.prototype.checkFilters=function(e){var t=[];if(e&&0!==e.length||h.error("Config","Missing filters list"),e.forEach(function(i,e){switch(i.id||h.error("Config","Missing filter {0} id",e),-1!=t.indexOf(i.id)&&h.error("Config",'Filter "{0}" already defined',i.id),t.push(i.id),i.type?c.types[i.type]||h.error("Config",'Invalid type "{0}"',i.type):i.type="string",i.input?"function"!=typeof i.input&&-1==c.inputs.indexOf(i.input)&&h.error("Config",'Invalid input "{0}"',i.input):i.input="number"===c.types[i.type]?"number":"text",i.operators&&i.operators.forEach(function(e){"string"!=typeof e&&h.error("Config","Filter operators must be global operators types (string)")}),i.field||(i.field=i.id),i.label||(i.label=i.field),i.optgroup?(this.status.has_optgroup=!0,this.settings.optgroups[i.optgroup]||(this.settings.optgroups[i.optgroup]=i.optgroup)):i.optgroup=null,i.input){case"radio":case"checkbox":(!i.values||i.values.length<1)&&h.error("Config",'Missing filter "{0}" values',i.id);break;case"select":var n=[];i.has_optgroup=!1,h.iterateOptions(i.values,function(e,t,r){n.push({value:e,label:t,optgroup:r||null}),r&&(i.has_optgroup=!0,this.settings.optgroups[r]||(this.settings.optgroups[r]=r))}.bind(this)),i.has_optgroup?i.values=h.groupSort(n,"optgroup"):i.values=n,i.placeholder&&(void 0===i.placeholder_value&&(i.placeholder_value=-1),i.values.forEach(function(e){e.value==i.placeholder_value&&h.error("Config",'Placeholder of filter "{0}" overlaps with one of its values',i.id)}))}},this),this.settings.sort_filters)if("function"==typeof this.settings.sort_filters)e.sort(this.settings.sort_filters);else{var r=this;e.sort(function(e,t){return r.translate(e.label).localeCompare(r.translate(t.label))})}return this.status.has_optgroup&&(e=h.groupSort(e,"optgroup")),e},c.prototype.checkOperators=function(r){var i=[];return r.forEach(function(e,t){"string"==typeof e?(c.OPERATORS[e]||h.error("Config",'Unknown operator "{0}"',e),r[t]=e=$.extendext(!0,"replace",{},c.OPERATORS[e])):(e.type||h.error("Config",'Missing "type" for operator {0}',t),c.OPERATORS[e.type]&&(r[t]=e=$.extendext(!0,"replace",{},c.OPERATORS[e.type],e)),void 0!==e.nb_inputs&&void 0!==e.apply_to||h.error("Config",'Missing "nb_inputs" and/or "apply_to" for operator "{0}"',e.type)),-1!=i.indexOf(e.type)&&h.error("Config",'Operator "{0}" already defined',e.type),i.push(e.type),e.optgroup?(this.status.has_operator_optgroup=!0,this.settings.optgroups[e.optgroup]||(this.settings.optgroups[e.optgroup]=e.optgroup)):e.optgroup=null},this),this.status.has_operator_optgroup&&(r=h.groupSort(r,"optgroup")),r},c.prototype.bindEvents=function(){var o=this,t=c.selectors;this.$el.on("change.queryBuilder",t.group_condition,function(){if($(this).is(":checked")){var e=$(this).closest(t.group_container);o.getModel(e).condition=$(this).val()}}),this.$el.on("change.queryBuilder",t.rule_filter,function(){var e=$(this).closest(t.rule_container);o.getModel(e).filter=o.getFilterById($(this).val())}),this.$el.on("change.queryBuilder",t.rule_operator,function(){var e=$(this).closest(t.rule_container);o.getModel(e).operator=o.getOperatorByType($(this).val())}),this.$el.on("click.queryBuilder",t.add_rule,function(){var e=$(this).closest(t.group_container);o.addRule(o.getModel(e))}),this.$el.on("click.queryBuilder",t.delete_rule,function(){var e=$(this).closest(t.rule_container);o.deleteRule(o.getModel(e))}),0!==this.settings.allow_groups&&(this.$el.on("click.queryBuilder",t.add_group,function(){var e=$(this).closest(t.group_container);o.addGroup(o.getModel(e))}),this.$el.on("click.queryBuilder",t.delete_group,function(){var e=$(this).closest(t.group_container);o.deleteGroup(o.getModel(e))})),this.model.on({drop:function(e,t){t.$el.remove(),o.refreshGroupsConditions()},add:function(e,t,r,i){0===i?r.$el.prependTo(t.$el.find(">"+c.selectors.rules_list)):r.$el.insertAfter(t.rules[i-1].$el),o.refreshGroupsConditions()},move:function(e,t,r,i){t.$el.detach(),0===i?t.$el.prependTo(r.$el.find(">"+c.selectors.rules_list)):t.$el.insertAfter(r.rules[i-1].$el),o.refreshGroupsConditions()},update:function(e,t,r,i,n){if(t instanceof l)switch(r){case"error":o.updateError(t);break;case"flags":o.applyRuleFlags(t);break;case"filter":o.updateRuleFilter(t,n);break;case"operator":o.updateRuleOperator(t,n);break;case"value":o.updateRuleValue(t,n)}else switch(r){case"error":o.updateError(t);break;case"flags":o.applyGroupFlags(t);break;case"condition":o.updateGroupCondition(t,n)}}})},c.prototype.setRoot=function(e,t,r){e=void 0===e||!0===e;var i=this.nextGroupId(),n=$(this.getGroupTemplate(i,1));return this.$el.append(n),this.model.root=new a(null,n),this.model.root.model=this.model,this.model.root.data=t,this.model.root.flags=$.extend({},this.settings.default_group_flags,r),this.model.root.condition=this.settings.default_condition,this.trigger("afterAddGroup",this.model.root),e&&this.addRule(this.model.root),this.model.root},c.prototype.addGroup=function(e,t,r,i){t=void 0===t||!0===t;var n=e.level+1;if(this.trigger("beforeAddGroup",e,t,n).isDefaultPrevented())return null;var o=this.nextGroupId(),l=$(this.getGroupTemplate(o,n)),s=e.addGroup(l);return s.data=r,s.flags=$.extend({},this.settings.default_group_flags,i),s.condition=this.settings.default_condition,this.trigger("afterAddGroup",s),this.trigger("rulesChanged"),t&&this.addRule(s),s},c.prototype.deleteGroup=function(e){if(e.isRoot())return!1;if(this.trigger("beforeDeleteGroup",e).isDefaultPrevented())return!1;var t=!0;return e.each("reverse",function(e){t&=this.deleteRule(e)},function(e){t&=this.deleteGroup(e)},this),t&&(e.drop(),this.trigger("afterDeleteGroup"),this.trigger("rulesChanged")),t},c.prototype.updateGroupCondition=function(t,e){t.$el.find(">"+c.selectors.group_condition).each(function(){var e=$(this);e.prop("checked",e.val()===t.condition),e.parent().toggleClass("active",e.val()===t.condition)}),this.trigger("afterUpdateGroupCondition",t,e),this.trigger("rulesChanged")},c.prototype.refreshGroupsConditions=function(){!function t(e){(!e.flags||e.flags&&!e.flags.condition_readonly)&&e.$el.find(">"+c.selectors.group_condition).prop("disabled",e.rules.length<=1).parent().toggleClass("disabled",e.rules.length<=1),e.each(null,function(e){t(e)},this)}(this.model.root)},c.prototype.addRule=function(e,t,r){if(this.trigger("beforeAddRule",e).isDefaultPrevented())return null;var i=this.nextRuleId(),n=$(this.getRuleTemplate(i)),o=e.addRule(n);return o.data=t,o.flags=$.extend({},this.settings.default_rule_flags,r),this.trigger("afterAddRule",o),this.trigger("rulesChanged"),this.createRuleFilters(o),!this.settings.default_filter&&this.settings.display_empty_filter||(o.filter=this.change("getDefaultFilter",this.getFilterById(this.settings.default_filter||this.filters[0].id),o)),o},c.prototype.deleteRule=function(e){return!e.flags.no_delete&&(!this.trigger("beforeDeleteRule",e).isDefaultPrevented()&&(e.drop(),this.trigger("afterDeleteRule"),this.trigger("rulesChanged"),!0))},c.prototype.createRuleFilters=function(e){var t=this.change("getRuleFilters",this.filters,e),r=$(this.getRuleFilterSelect(e,t));e.$el.find(c.selectors.filter_container).html(r),this.trigger("afterCreateRuleFilters",e),this.applyRuleFlags(e)},c.prototype.createRuleOperators=function(e){var t=e.$el.find(c.selectors.operator_container).empty();if(e.filter){var r=this.getOperators(e.filter),i=$(this.getRuleOperatorSelect(e,r));t.html(i),e.filter.default_operator?e.__.operator=this.getOperatorByType(e.filter.default_operator):e.__.operator=r[0],e.$el.find(c.selectors.rule_operator).val(e.operator.type),this.trigger("afterCreateRuleOperators",e,r),this.applyRuleFlags(e)}},c.prototype.createRuleInput=function(e){var t=e.$el.find(c.selectors.value_container).empty();if(e.__.value=void 0,e.filter&&e.operator&&0!==e.operator.nb_inputs){for(var r=this,i=$(),n=e.filter,o=0;o"+r.group_condition).prop("disabled",t.condition_readonly).parent().toggleClass("readonly",t.condition_readonly),t.no_add_rule&&e.$el.find(r.add_rule).remove(),t.no_add_group&&e.$el.find(r.add_group).remove(),t.no_delete&&e.$el.find(r.delete_group).remove(),this.trigger("afterApplyGroupFlags",e)},c.prototype.clearErrors=function(e){(e=e||this.model.root)&&(e.error=null,e instanceof a&&e.each(function(e){e.error=null},function(e){this.clearErrors(e)},this))},c.prototype.updateError=function(e){if(this.settings.display_errors)if(null===e.error)e.$el.removeClass("has-error");else{var t=this.translate("errors",e.error[0]);t=h.fmt(t,e.error.slice(1)),t=this.change("displayError",t,e.error,e),e.$el.addClass("has-error").find(c.selectors.error_container).eq(0).attr("title",t)}},c.prototype.triggerValidationError=function(e,t,r){$.isArray(t)||(t=[t]),this.trigger("validationError",e,t,r).isDefaultPrevented()||(e.error=t)},c.prototype.destroy=function(){this.trigger("beforeDestroy"),this.status.generated_id&&this.$el.removeAttr("id"),this.clear(),this.model=null,this.$el.off(".queryBuilder").removeClass("query-builder").removeData("queryBuilder"),delete this.$el[0].queryBuilder},c.prototype.reset=function(){this.trigger("beforeReset").isDefaultPrevented()||(this.status.group_id=1,this.status.rule_id=0,this.model.root.empty(),this.model.root.data=void 0,this.model.root.flags=$.extend({},this.settings.default_group_flags),this.model.root.condition=this.settings.default_condition,this.addRule(this.model.root),this.trigger("afterReset"),this.trigger("rulesChanged"))},c.prototype.clear=function(){this.trigger("beforeClear").isDefaultPrevented()||(this.status.group_id=0,this.status.rule_id=0,this.model.root&&(this.model.root.drop(),this.model.root=null),this.trigger("afterClear"),this.trigger("rulesChanged"))},c.prototype.setOptions=function(e){$.each(e,function(e,t){-1!==c.modifiable_options.indexOf(e)&&(this.settings[e]=t)}.bind(this))},c.prototype.getModel=function(e){return e?e instanceof n?e:$(e).data("queryBuilderModel"):this.model.root},c.prototype.validate=function(o){o=$.extend({skip_empty:!1},o),this.clearErrors();var l=this,e=function r(e){var i=0,n=0;return e.each(function(e){if(e.filter||!o.skip_empty){if(!e.filter)return l.triggerValidationError(e,"no_filter",null),void n++;if(!e.operator)return l.triggerValidationError(e,"no_operator",null),void n++;if(0!==e.operator.nb_inputs){var t=l.validateValue(e,e.value);if(!0!==t)return l.triggerValidationError(e,t,e.value),void n++}i++}},function(e){var t=r(e);!0===t?i++:!1===t&&n++}),!(0parseInt(l.max)){s=[this.getValidationMessage(l,"max","string_exceed_max_length"),l.max];break}if(!l.format||("string"==typeof l.format&&(l.format=new RegExp(l.format)),l.format.test(i[u])))break;s=[this.getValidationMessage(l,"format","string_invalid_format"),l.format];break;case"number":if(void 0===i[u]||0===i[u].length){l.allow_empty_value||(s=["number_nan"]);break}if(isNaN(i[u])){s=["number_nan"];break}if("integer"==n.type){if(parseInt(i[u])!=i[u]){s=["number_not_integer"];break}}else if(parseFloat(i[u])!=i[u]){s=["number_not_double"];break}if(void 0!==l.min&&i[u]parseFloat(l.max)){s=[this.getValidationMessage(l,"max","number_exceed_max"),l.max];break}if(void 0!==l.step&&"any"!==l.step){var p=(i[u]/l.step).toPrecision(14);if(parseInt(p)!=p){s=[this.getValidationMessage(l,"step","number_wrong_step"),l.step];break}}break;case"datetime":if(void 0===i[u]||0===i[u].length){l.allow_empty_value||(s=["datetime_empty"]);break}if(l.format){"moment"in window||h.error("MissingLibrary","MomentJS is required for Date/Time validation. Get it here http://momentjs.com");var d=moment(i[u],l.format);if(!d.isValid()){s=[this.getValidationMessage(l,"format","datetime_invalid"),l.format];break}if(l.min&&dmoment(l.max,l.format)){s=[this.getValidationMessage(l,"max","datetime_exceed_max"),l.max];break}}break;case"boolean":if(void 0===i[u]||0===i[u].length){l.allow_empty_value||(s=["boolean_not_valid"]);break}if("true"!==(r=(""+i[u]).trim().toLowerCase())&&"false"!==r&&"1"!==r&&"0"!==r&&1!==i[u]&&0!==i[u]){s=["boolean_not_valid"];break}}if(!0!==s)break}}if(!0!==s)break}if(("between"===e.operator.type||"not_between"===e.operator.type)&&2===t.length)switch(c.types[n.type]){case"number":t[0]>t[1]&&(s=["number_between_invalid",t[0],t[1]]);break;case"datetime":l.format&&("moment"in window||h.error("MissingLibrary","MomentJS is required for Date/Time validation. Get it here http://momentjs.com"),moment(t[0],l.format).isAfter(moment(t[1],l.format))&&(s=["datetime_between_invalid",t[0],t[1]]))}return s},c.prototype.nextGroupId=function(){return this.status.id+"_group_"+this.status.group_id++},c.prototype.nextRuleId=function(){return this.status.id+"_rule_"+this.status.rule_id++},c.prototype.getOperators=function(r){"string"==typeof r&&(r=this.getFilterById(r));for(var e=[],t=0,i=this.operators.length;t ',c.templates.rule=' {{? it.settings.display_errors }}
{{?}}
',c.templates.filterSelect='{{ var optgroup = null; }} {{? it.settings.display_empty_filter }} {{= it.settings.select_placeholder }} {{?}} {{~ it.filters: filter }} {{? optgroup !== filter.optgroup }} {{? optgroup !== null }}{{?}} {{? (optgroup = filter.optgroup) !== null }} {{?}} {{?}} {{= it.translate(filter.label) }} {{~}} {{? optgroup !== null }} {{?}} ',c.templates.operatorSelect='{{? it.operators.length === 1 }} {{= it.translate("operators", it.operators[0].type) }} {{?}} {{ var optgroup = null; }} {{~ it.operators: operator }} {{? optgroup !== operator.optgroup }} {{? optgroup !== null }}{{?}} {{? (optgroup = operator.optgroup) !== null }} {{?}} {{?}} {{= it.translate("operators", operator.type) }} {{~}} {{? optgroup !== null }} {{?}} ',c.templates.ruleValueSelect='{{ var optgroup = null; }} {{? it.rule.filter.placeholder }} {{= it.rule.filter.placeholder }} {{?}} {{~ it.rule.filter.values: entry }} {{? optgroup !== entry.optgroup }} {{? optgroup !== null }}{{?}} {{? (optgroup = entry.optgroup) !== null }} {{?}} {{?}} {{= entry.label }} {{~}} {{? optgroup !== null }} {{?}} ',c.prototype.getGroupTemplate=function(e,t){var r=this.templates.group({builder:this,group_id:e,level:t,conditions:this.settings.conditions,icons:this.icons,settings:this.settings,translate:this.translate.bind(this)});return this.change("getGroupTemplate",r,t)},c.prototype.getRuleTemplate=function(e){var t=this.templates.rule({builder:this,rule_id:e,icons:this.icons,settings:this.settings,translate:this.translate.bind(this)});return this.change("getRuleTemplate",t)},c.prototype.getRuleFilterSelect=function(e,t){var r=this.templates.filterSelect({builder:this,rule:e,filters:t,icons:this.icons,settings:this.settings,translate:this.translate.bind(this)});return this.change("getRuleFilterSelect",r,e,t)},c.prototype.getRuleOperatorSelect=function(e,t){var r=this.templates.operatorSelect({builder:this,rule:e,operators:t,icons:this.icons,settings:this.settings,translate:this.translate.bind(this)});return this.change("getRuleOperatorSelect",r,e,t)},c.prototype.getRuleValueSelect=function(e,t){var r=this.templates.ruleValueSelect({builder:this,name:e,rule:t,icons:this.icons,settings:this.settings,translate:this.translate.bind(this)});return this.change("getRuleValueSelect",r,e,t)},c.prototype.getRuleInput=function(e,t){var r=e.filter,i=e.filter.validation||{},n=e.id+"_value_"+t,o=r.vertical?" class=block":"",l="",s=Array.isArray(r.placeholder)?r.placeholder[t]:r.placeholder;if("function"==typeof r.input)l=r.input.call(this,e,n);else switch(r.input){case"radio":case"checkbox":h.iterateOptions(r.values,function(e,t){l+=" '+t+" "});break;case"select":l=this.getRuleValueSelect(n,e);break;case"textarea":l+='";break;case"number":l+=' " ;break;default:l=' " }return this.change getRuleInput ,l,e,n)};var h="{};function" i(){this.root='null,this.$=$(this)}(c.utils=h).iterateOptions=function(e,r){e&&($.isArray(e)?e.forEach(function(e){$.isPlainObject(e)?"value"in' e?r(e.value,e.label||e.value,e.optgroup):$.each(e,function(e,t){return r(e,t),!1}):r(e,e)}):$.each(e,function(e,t){r(e,t)}))},h.fmt="function(e,r){return" Array.isArray(r)||(r="Array.prototype.slice.call(arguments,1)),e.replace(/{([0-9]+)}/g,function(e,t){return" r[parseInt(t)]})},h.error="function(){var" e='0,t="boolean"!=typeof' arguments[e]||arguments[e++],r="arguments[e++],i=arguments[e++],n=Array.isArray(arguments[e])?arguments[e]:Array.prototype.slice.call(arguments,e);if(t){var" o="new" Error(h.fmt(i,n));throw o.name='r+"Error",o.args=n,o}console.error(r+"Error:' +h.fmt(i,n))},h.changeType='function(e,t){if(""!==e&&void' 0='=e)switch(t){case"integer":return"string"!=typeof' e||/^-?\d+$/.test(e)?parseInt(e):e;case double :return string !="typeof" e||/^-?\d+\.?\d*$/.test(e)?parseFloat(e):e;case boolean :return string !="typeof" e||/^(0|1|true|false){1}$/i.test(e)?!0='==e||1===e||"true"===e.toLowerCase()||"1"===e:e;default:return' e}},h.escapeString='function(e){return"string"!=typeof' e?e:e.replace(/[\0\n\r\b \ ]/g,function(e){switch(e){case \0 :return \\0 ;case \n :return \\n ;case \r :return \\r ;case \b :return \\b ;default:return \ +e}}).replace(/\t/g \\t ).replace(/\x1a/g \\Z )},h.escapeRegExp="function(e){return" e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g \ )},h.escapeElementId="function(e){return" e?e.replace(/(\\)?([:.\[\],])/g,function(e,t,r){return t?e \ +r}):e},h.groupSort="function(e,r){var" i="[],n=[];return" e.forEach(function(e){var t;e[r]?-1="=(t=i.lastIndexOf(e[r]))?t=i.length:t++:t=i.length,i.splice(t,0,e[r]),n.splice(t,0,e)}),n},h.defineModelProperties=function(e,t){t.forEach(function(r){Object.defineProperty(e.prototype,r,{enumerable:!0,get:function(){return" this.__[r]},set:function(e){var t='null!==this.__[r]&&"object"==typeof' this.__[r]?$.extend({},this.__[r]):this.__[r];this.__[r='e,null!==this.model&&this.model.trigger("update",this,r,e,t)}})})},$.extend(i.prototype,{trigger:function(e){var' t="new" $.Event(e);return this.$.triggerHandler(t,Array.prototype.slice.call(arguments,1)),t},on:function(){return this.$.on.apply(this.$,Array.prototype.slice.call(arguments)),this},off:function(){return this.$.off.apply(this.$,Array.prototype.slice.call(arguments)),this},once:function(){return this.$.one.apply(this.$,Array.prototype.slice.call(arguments)),this}});var n="function(e,t){if(!(this" instanceof n))return new n(e,t);Object.defineProperty(this _ ,{value:{}}),t.data queryBuilderModel ,this),this.__.level="1,this.__.error=null,this.__.flags={},this.__.data=void" 0,this.$el='t,this.id=t[0].id,this.model=null,this.parent=e};h.defineModelProperties(n,["level","error","data","flags"]),Object.defineProperty(n.prototype,"parent",{enumerable:!0,get:function(){return' this.__.parent},set:function(e){this.__.parent="e,this.level=null===e?1:e.level+1,this.model=null===e?null:e.model}}),n.prototype.isRoot=function(){return" 1="==this.level},n.prototype.getPos=function(){return" this.isRoot()?-1:this.parent.getNodePos(this)},n.prototype.drop="function(){var" e='this.model;this.parent&&this.parent.removeNode(this),this.$el.removeData("queryBuilderModel"),null!==e&&e.trigger("drop",this)},n.prototype.moveAfter=function(e){this.isRoot()||this.move(e.parent,e.getPos()+1)},n.prototype.moveAtBegin=function(e){this.isRoot()||(void' 0="==e&&(e=this.parent),this.move(e,0))},n.prototype.moveAtEnd=function(e){this.isRoot()||(void" 0='==e&&(e=this.parent),this.move(e,0===e.length()?0:e.length()-1))},n.prototype.move=function(e,t){this.isRoot()||("number"==typeof' e&&(t='e,e=this.parent),this.parent.removeNode(this),e.insertNode(this,t,!1),null!==this.model&&this.model.trigger("move",this,e,t))};var' a="function(e,t){if(!(this" instanceof a))return new a(e,t);n.call(this,e,t),this.rules='[],this.__.condition=null};a.prototype=Object.create(n.prototype),a.prototype.constructor=a,h.defineModelProperties(a,["condition"]),a.prototype.empty=function(){this.each("reverse",function(e){e.drop()},function(e){e.drop()})},a.prototype.drop=function(){this.empty(),n.prototype.drop.call(this)},a.prototype.length=function(){return' this.rules.length},a.prototype.insertNode="function(e,t,r){return" void 0='==t&&(t=this.length()),this.rules.splice(t,0,e),e.parent=this,r&&null!==this.model&&this.model.trigger("add",this,e,t),e},a.prototype.addGroup=function(e,t){return' this.insertNode(new a(this,e),t,!0)},a.prototype.addRule="function(e,t){return" this.insertNode(new l(this,e),t,!0)},a.prototype.removeNode="function(e){var" t="this.getNodePos(e);-1!==t&&(e.parent=null,this.rules.splice(t,1))},a.prototype.getNodePos=function(e){return" this.rules.indexOf(e)},a.prototype.each='function(e,t,r,i){"boolean"!=typeof' e string !="typeof" e&&(i="r,r=t,t=e,e=!1),i=void" 0="==i?null:i;for(var" n="e?this.rules.length-1:0,o=e?0:this.rules.length-1,l=e?-1:1,s=!1;(e?o<=n:n<=o)&&(this.rules[n]instanceof" a?r&&(s="!1===r.call(i,this.rules[n])):t&&(s=!1===t.call(i,this.rules[n])),!s);n+=l);return!s},a.prototype.contains=function(t,e){return-1!==this.getNodePos(t)||!!e&&!this.each(function(){return!0},function(e){return!e.contains(t,!0)})};var" l="function(e,t){if(!(this" instanceof l))return new l(e,t);n.call(this,e,t),this._updating_value="!1,this._updating_input=!1,this.__.filter=null,this.__.operator=null,this.__.value=void" 0};function u(e,t,r){var i,n,o='c.selectors;(i=t.closest(o.rule_container)).length&&(n="moveAfter"),n||(i=t.closest(o.group_header)).length&&(i=t.closest(o.group_container),n="moveAtBegin"),n||(i=t.closest(o.group_container)).length&&(n="moveAtEnd"),n&&(e[n](r.getModel(i)),r&&e' instanceof l&&r.setRuleInputValue(e,e.value))}function o(e){var t="e.match(/(question_mark|numbered|named)(?:\((.)\))?/);return" t||(t='[null,"question_mark",void' 0]),t}return l.prototype='Object.create(n.prototype),l.prototype.constructor=l,h.defineModelProperties(l,["filter","operator","value"]),l.prototype.isRoot=function(){return!1},c.Group=a,c.Rule=l,$.fn.queryBuilder=function(e){0===this.length&&h.error("Config","No' target defined ),1> '+t+" "})}})},{font:"glyphicons",color:"default"}),c.define("bt-selectpicker",function(r){$.fn.selectpicker&&$.fn.selectpicker.Constructor||h.error("MissingLibrary",'Bootstrap Select is required to use "bt-selectpicker" plugin. Get it here: http://silviomoreto.github.io/bootstrap-select');var i=c.selectors;this.on("afterCreateRuleFilters",function(e,t){t.$el.find(i.rule_filter).removeClass("form-control").selectpicker(r)}),this.on("afterCreateRuleOperators",function(e,t){t.$el.find(i.rule_operator).removeClass("form-control").selectpicker(r)}),this.on("afterUpdateRuleFilter",function(e,t){t.$el.find(i.rule_filter).selectpicker("render")}),this.on("afterUpdateRuleOperator",function(e,t){t.$el.find(i.rule_operator).selectpicker("render")}),this.on("beforeDeleteRule",function(e,t){t.$el.find(i.rule_filter).selectpicker("destroy"),t.$el.find(i.rule_operator).selectpicker("destroy")})},{container:"body",style:"btn-inverse btn-sm",width:"auto",showIcon:!1}),c.define("bt-tooltip-errors",function(i){$.fn.tooltip&&$.fn.tooltip.Constructor&&$.fn.tooltip.Constructor.prototype.fixTitle||h.error("MissingLibrary",'Bootstrap Tooltip is required to use "bt-tooltip-errors" plugin. Get it here: http://getbootstrap.com');var n=this;this.on("getRuleTemplate.filter getGroupTemplate.filter",function(e){var t=$(e.value);t.find(c.selectors.error_container).attr("data-toggle","tooltip"),e.value=t.prop("outerHTML")}),this.model.on("update",function(e,t,r){"error"==r&&n.settings.display_errors&&t.$el.find(c.selectors.error_container).eq(0).tooltip(i).tooltip("hide").tooltip("fixTitle")})},{placement:"right"}),c.extend({setFilters:function(e,t){var r=this;void 0===t&&(t=e,e=!1),t=this.checkFilters(t);var i=(t=this.change("setFilters",t)).map(function(e){return e.id});if(e||function e(t){t.each(function(e){e.filter&&-1===i.indexOf(e.filter.id)&&h.error("ChangeFilter",'A rule is using filter "{0}"',e.filter.id)},e)}(this.model.root),this.filters=t,function e(t){t.each(!0,function(e){e.filter&&-1===i.indexOf(e.filter.id)?(e.drop(),r.trigger("rulesChanged")):(r.createRuleFilters(e),e.$el.find(c.selectors.rule_filter).val(e.filter?e.filter.id:"-1"),r.trigger("afterUpdateRuleFilter",e))},e)}(this.model.root),this.settings.plugins&&(this.settings.plugins["unique-filter"]&&this.updateDisabledFilters(),this.settings.plugins["bt-selectpicker"]&&this.$el.find(c.selectors.rule_filter).selectpicker("render")),this.settings.default_filter)try{this.getFilterById(this.settings.default_filter)}catch(e){this.settings.default_filter=null}this.trigger("afterSetFilters",t)},addFilter:function(e,r){void 0===r||"#end"==r?r=this.filters.length:"#start"==r&&(r=0),$.isArray(e)||(e=[e]);var t=$.extend(!0,[],this.filters);parseInt(r)==r?Array.prototype.splice.apply(t,[r,0].concat(e)):this.filters.some(function(e,t){if(e.id==r)return r=t+1,!0})?Array.prototype.splice.apply(t,[r,0].concat(e)):Array.prototype.push.apply(t,e),this.setFilters(t)},removeFilter:function(t,e){var r=$.extend(!0,[],this.filters);"string"==typeof t&&(t=[t]),r=r.filter(function(e){return-1===t.indexOf(e.id)}),this.setFilters(e,r)}}),c.define("chosen-selectpicker",function(r){$.fn.chosen||h.error("MissingLibrary",'chosen is required to use "chosen-selectpicker" plugin. Get it here: https://github.com/harvesthq/chosen'),this.settings.plugins["bt-selectpicker"]&&h.error("Conflict","bt-selectpicker is already selected as the dropdown plugin. Please remove chosen-selectpicker from the plugin list");var i=c.selectors;this.on("afterCreateRuleFilters",function(e,t){t.$el.find(i.rule_filter).removeClass("form-control").chosen(r)}),this.on("afterCreateRuleOperators",function(e,t){1')).appendTo(t.$el):r.css("display",""),r.html(' '+i)):r.hide()}):"popover"===n.mode?($.fn.popover&&$.fn.popover.Constructor&&$.fn.popover.Constructor.prototype.fixTitle||h.error("MissingLibrary",'Bootstrap Popover is required to use "filter-description" plugin. Get it here: http://getbootstrap.com'),this.on("afterUpdateRuleFilter afterUpdateRuleOperator",function(e,t){var r=t.$el.find("button.filter-description"),i=e.builder.getFilterDescription(t.filter,t);i?(0===r.length?((r=$(' ')).prependTo(t.$el.find(c.selectors.rule_actions)),r.popover({placement:"left",container:"body",html:!0}),r.on("mouseout",function(){r.popover("hide")})):r.css("display",""),r.data("bs.popover").options.content=i,r.attr("aria-describedby")&&r.popover("show")):(r.hide(),r.data("bs.popover")&&r.popover("hide"))})):"bootbox"===n.mode&&("bootbox"in window||h.error("MissingLibrary",'Bootbox is required to use "filter-description" plugin. Get it here: http://bootboxjs.com'),this.on("afterUpdateRuleFilter afterUpdateRuleOperator",function(e,t){var r=t.$el.find("button.filter-description"),i=e.builder.getFilterDescription(t.filter,t);i?(0===r.length?((r=$(' ')).prependTo(t.$el.find(c.selectors.rule_actions)),r.on("click",function(){bootbox.alert(r.data("description"))})):r.css("display",""),r.data("description",i)):r.hide()}))},{icon:"glyphicon glyphicon-info-sign",mode:"popover"}),c.extend({getFilterDescription:function(e,t){return e?"function"==typeof e.description?e.description.call(this,t):e.description:void 0}}),c.define("invert",function(r){var i=this,n=c.selectors;this.on("afterInit",function(){i.$el.on("click.queryBuilder","[data-invert=group]",function(){var e=$(this).closest(n.group_container);i.invert(i.getModel(e),r)}),r.display_rules_button&&r.invert_rules&&i.$el.on("click.queryBuilder","[data-invert=rule]",function(){var e=$(this).closest(n.rule_container);i.invert(i.getModel(e),r)})}),r.disable_template||(this.on("getGroupTemplate.filter",function(e){var t=$(e.value);t.find(n.condition_container).after(' '+i.translate("invert")+" "),e.value=t.prop("outerHTML")}),r.display_rules_button&&r.invert_rules&&this.on("getRuleTemplate.filter",function(e){var t=$(e.value);t.find(n.rule_actions).prepend(' '+i.translate("invert")+" "),e.value=t.prop("outerHTML")}))},{icon:"glyphicon glyphicon-random",recursive:!0,invert_rules:!0,display_rules_button:!1,silent_fail:!1,disable_template:!1}),c.defaults({operatorOpposites:{equal:"not_equal",not_equal:"equal",in:"not_in",not_in:"in",less:"greater_or_equal",less_or_equal:"greater",greater:"less_or_equal",greater_or_equal:"less",between:"not_between",not_between:"between",begins_with:"not_begins_with",not_begins_with:"begins_with",contains:"not_contains",not_contains:"contains",ends_with:"not_ends_with",not_ends_with:"ends_with",is_empty:"is_not_empty",is_not_empty:"is_empty",is_null:"is_not_null",is_not_null:"is_null"},conditionOpposites:{AND:"OR",OR:"AND"}}),c.extend({invert:function(e,t){if(!(e instanceof n)){if(!this.model.root)return;t=e,e=this.model.root}if("object"!=typeof t&&(t={}),void 0===t.recursive&&(t.recursive=!0),void 0===t.invert_rules&&(t.invert_rules=!0),void 0===t.silent_fail&&(t.silent_fail=!1),void 0===t.trigger&&(t.trigger=!0),e instanceof a){if(this.settings.conditionOpposites[e.condition]?e.condition=this.settings.conditionOpposites[e.condition]:t.silent_fail||h.error("InvertCondition",'Unknown inverse of condition "{0}"',e.condition),t.recursive){var r=$.extend({},t,{trigger:!1});e.each(function(e){t.invert_rules&&this.invert(e,r)},function(e){this.invert(e,r)},this)}}else if(e instanceof l&&e.operator&&!e.filter.no_invert)if(this.settings.operatorOpposites[e.operator.type]){var i=this.settings.operatorOpposites[e.operator.type];e.filter.operators&&-1==e.filter.operators.indexOf(i)||(e.operator=this.getOperatorByType(i))}else t.silent_fail||h.error("InvertOperator",'Unknown inverse of operator "{0}"',e.operator.type);t.trigger&&(this.trigger("afterInvert",e,t),this.trigger("rulesChanged"))}}),c.defaults({mongoOperators:{equal:function(e){return e[0]},not_equal:function(e){return{$ne:e[0]}},in:function(e){return{$in:e}},not_in:function(e){return{$nin:e}},less:function(e){return{$lt:e[0]}},less_or_equal:function(e){return{$lte:e[0]}},greater:function(e){return{$gt:e[0]}},greater_or_equal:function(e){return{$gte:e[0]}},between:function(e){return{$gte:e[0],$lte:e[1]}},not_between:function(e){return{$lt:e[0],$gt:e[1]}},begins_with:function(e){return{$regex:"^"+h.escapeRegExp(e[0])}},not_begins_with:function(e){return{$regex:"^(?!"+h.escapeRegExp(e[0])+")"}},contains:function(e){return{$regex:h.escapeRegExp(e[0])}},not_contains:function(e){return{$regex:"^((?!"+h.escapeRegExp(e[0])+").)*$",$options:"s"}},ends_with:function(e){return{$regex:h.escapeRegExp(e[0])+"$"}},not_ends_with:function(e){return{$regex:"(? '+i.translate("NOT")+""),e.value=t.prop("outerHTML")}),this.on("groupToJson.filter",function(e,t){e.value.not=t.not}),this.on("jsonToGroup.filter",function(e,t){e.value.not=!!t.not}),this.on("groupToSQL.filter",function(e,t){t.not&&(e.value="NOT ( "+e.value+" )")}),this.on("parseSQLNode.filter",function(e){e.value.name&&"NOT"==e.value.name.toUpperCase()&&(e.value=e.value.arguments.value[0],-1===["AND","OR"].indexOf(e.value.operation.toUpperCase())&&(e.value=new SQLParser.nodes.Op(i.settings.default_condition,e.value,null)),e.value.not=!0)}),this.on("sqlGroupsDistinct.filter",function(e,t,r,i){r.not&&0"+c.selectors.group_not).toggleClass("active",e.not).find("i").attr("class",e.not?t.icon_checked:t.icon_unchecked),this.trigger("afterUpdateGroupNot",e),this.trigger("rulesChanged")}}),c.define("sortable",function(i){var n,o,l,s;"interact"in window||h.error("MissingLibrary",'interact.js is required to use "sortable" plugin. Get it here: http://interactjs.io'),void 0!==i.default_no_sortable&&(h.error(!1,"Config",'Sortable plugin : "default_no_sortable" options is deprecated, use standard "default_rule_flags" and "default_group_flags" instead'),this.settings.default_rule_flags.no_sortable=this.settings.default_group_flags.no_sortable=i.default_no_sortable),interact.dynamicDrop(!0),interact.pointerMoveTolerance(10),this.on("afterAddRule afterAddGroup",function(e,t){if(t!=n){var r=e.builder;i.inherit_no_sortable&&t.parent&&t.parent.flags.no_sortable&&(t.flags.no_sortable=!0),i.inherit_no_drop&&t.parent&&t.parent.flags.no_drop&&(t.flags.no_drop=!0),t.flags.no_sortable||interact(t.$el[0]).draggable({allowFrom:c.selectors.drag_handle,onstart:function(e){s=!1,l=r.getModel(e.target),o=l.$el.clone().appendTo(l.$el.parent()).width(l.$el.outerWidth()).addClass("dragging");var t=$('
').height(l.$el.outerHeight());n=l.parent.addRule(t,l.getPos()),l.$el.hide()},onmove:function(e){o[0].style.top=e.clientY-15+"px",o[0].style.left=e.clientX-15+"px"},onend:function(e){e.dropzone&&(u(l,$(e.relatedTarget),r),s=!0),o.remove(),o=void 0,n.drop(),n=void 0,l.$el.css("display",""),r.trigger("afterMove",l),r.trigger("rulesChanged")}}),t.flags.no_drop||(interact(t.$el[0]).dropzone({accept:c.selectors.rule_and_group_containers,ondragenter:function(e){u(n,$(e.target),r)},ondrop:function(e){s||u(l,$(e.target),r)}}),t instanceof a&&interact(t.$el.find(c.selectors.group_header)[0]).dropzone({accept:c.selectors.rule_and_group_containers,ondragenter:function(e){u(n,$(e.target),r)},ondrop:function(e){s||u(l,$(e.target),r)}}))}}),this.on("beforeDeleteRule beforeDeleteGroup",function(e,t){e.isDefaultPrevented()||(interact(t.$el[0]).unset(),t instanceof a&&interact(t.$el.find(c.selectors.group_header)[0]).unset())}),this.on("afterApplyRuleFlags afterApplyGroupFlags",function(e,t){t.flags.no_sortable&&t.$el.find(".drag-handle").remove()}),i.disable_template||(this.on("getGroupTemplate.filter",function(e,t){if(1 '),e.value=r.prop("outerHTML")}}),this.on("getRuleTemplate.filter",function(e){var t=$(e.value);t.find(c.selectors.rule_header).after('
'),e.value=t.prop("outerHTML")}))},{inherit_no_sortable:!0,inherit_no_drop:!0,icon:"glyphicon glyphicon-sort",disable_template:!1}),c.selectors.rule_and_group_containers=c.selectors.rule_container+", "+c.selectors.group_container,c.selectors.drag_handle=".drag-handle",c.defaults({default_rule_flags:{no_sortable:!1,no_drop:!1},default_group_flags:{no_sortable:!1,no_drop:!1}}),c.define("sql-support",function(e){},{boolean_as_integer:!0}),c.defaults({sqlOperators:{equal:{op:"= ?"},not_equal:{op:"!= ?"},in:{op:"IN(?)",sep:", "},not_in:{op:"NOT IN(?)",sep:", "},less:{op:"< ?"},less_or_equal:{op:"<= ?"},greater:{op:"> ?"},greater_or_equal:{op:">= ?"},between:{op:"BETWEEN ?",sep:" AND "},not_between:{op:"NOT BETWEEN ?",sep:" AND "},begins_with:{op:"LIKE(?)",mod:"{0}%"},not_begins_with:{op:"NOT LIKE(?)",mod:"{0}%"},contains:{op:"LIKE(?)",mod:"%{0}%"},not_contains:{op:"NOT LIKE(?)",mod:"%{0}%"},ends_with:{op:"LIKE(?)",mod:"%{0}"},not_ends_with:{op:"NOT LIKE(?)",mod:"%{0}"},is_empty:{op:"= ''"},is_not_empty:{op:"!= ''"},is_null:{op:"IS NULL"},is_not_null:{op:"IS NOT NULL"}},sqlRuleOperator:{"=":function(e){return{val:e,op:""===e?"is_empty":"equal"}},"!=":function(e){return{val:e,op:""===e?"is_not_empty":"not_equal"}},LIKE:function(e){return"%"==e.slice(0,1)&&"%"==e.slice(-1)?{val:e.slice(1,-1),op:"contains"}:"%"==e.slice(0,1)?{val:e.slice(1),op:"ends_with"}:"%"==e.slice(-1)?{val:e.slice(0,-1),op:"begins_with"}:void h.error("SQLParse",'Invalid value for LIKE operator "{0}"',e)},"NOT LIKE":function(e){return"%"==e.slice(0,1)&&"%"==e.slice(-1)?{val:e.slice(1,-1),op:"not_contains"}:"%"==e.slice(0,1)?{val:e.slice(1),op:"not_ends_with"}:"%"==e.slice(-1)?{val:e.slice(0,-1),op:"not_begins_with"}:void h.error("SQLParse",'Invalid value for NOT LIKE operator "{0}"',e)},IN:function(e){return{val:e,op:"in"}},"NOT IN":function(e){return{val:e,op:"not_in"}},"<":function(e){return{val:e,op:"less"}},"<=":function(e){return{val:e,op:"less_or_equal"}},">":function(e){return{val:e,op:"greater"}},">=":function(e){return{val:e,op:"greater_or_equal"}},BETWEEN:function(e){return{val:e,op:"between"}},"NOT BETWEEN":function(e){return{val:e,op:"not_between"}},IS:function(e){return null!==e&&h.error("SQLParse","Invalid value for IS operator"),{val:null,op:"is_null"}},"IS NOT":function(e){return null!==e&&h.error("SQLParse","Invalid value for IS operator"),{val:null,op:"is_not_null"}}},sqlStatements:{question_mark:function(){var r=[];return{add:function(e,t){return r.push(t),"?"},run:function(){return r}}},numbered:function(r){(!r||1"==l&&(l="!=");var s=f.settings.sqlRuleOperator[l];void 0===s&&h.error("UndefinedSQLOperator",'Invalid SQL operation "{0}".',t.operation);var a,u=s.call(this,o,t.operation);"values"in t.left?a=t.left.values.join("."):"value"in t.left?a=t.left.value:h.error("SQLParse","Cannot find field name in {0}",JSON.stringify(t.left));var p=f.getSQLFieldID(a,o),d=f.change("sqlToRule",{id:p,field:a,operator:u.op,value:u.val},t);g.rules.push(d)}}(i,0),n},setRulesFromSQL:function(e,t){this.setRules(this.getRulesFromSQL(e,t))},getSQLFieldID:function(t,e){var r=this.filters.filter(function(e){return e.field.toLowerCase()===t.toLowerCase()});return 1===r.length?r[0].id:this.change("getSQLFieldID",t,e)}}),c.define("unique-filter",function(){this.status.used_filters={},this.on("afterUpdateRuleFilter",this.updateDisabledFilters),this.on("afterDeleteRule",this.updateDisabledFilters),this.on("afterCreateRuleFilters",this.applyDisabledFilters),this.on("afterReset",this.clearDisabledFilters),this.on("afterClear",this.clearDisabledFilters),this.on("getDefaultFilter.filter",function(t,r){var i=t.builder;(i.updateDisabledFilters(),t.value.id in i.status.used_filters)&&(i.filters.some(function(e){if(!(e.id in i.status.used_filters)||0 <",">","\"","'","/","matchHTML","code","toString","replace","m","this","eval","module","exports","amd","startend","start","end","startencode","split","skip","unescape","tmpl","c","def","needhtmlencode","indv","cse","sid","str","resolveDefs","block","assign","value","indexOf","substring","param","v","arg","text","Function","s","d","rw","__exp","RegExp","elsecase","vname","iname","_encodeHTML","e","console","root","factory","require","jQuery","$","QueryBuilder","$el","options","queryBuilder","settings","extendext","DEFAULTS","model","Model","status","id","generated_id","group_id","rule_id","has_optgroup","has_operator_optgroup","filters","icons","operators","templates","plugins","lang","regional","Utils","error","lang_code","allow_groups","Object","keys","forEach","tpl","attr","Math","floor","random","addClass","checkFilters","checkOperators","bindEvents","initPlugins","extend","prototype","trigger","type","event","Event","_tojQueryEvent","builder","triggerHandler","Array","slice","call","arguments","change","on","cb","off","once","one","filter","map","join","types","string","integer","double","date","time","datetime","boolean","inputs","modifiable_options","selectors","group_container","rule_container","filter_container","operator_container","value_container","error_container","condition_container","rule_header","group_header","group_actions","rule_actions","rules_list","group_condition","rule_filter","rule_operator","rule_value","add_rule","delete_rule","add_group","delete_group","OPERATORS","equal","nb_inputs","multiple","apply_to","not_equal","in","not_in","less","less_or_equal","greater","greater_or_equal","between","not_between","begins_with","not_begins_with","contains","not_contains","ends_with","not_ends_with","is_empty","is_not_empty","is_null","is_not_null","sort_filters","display_errors","allow_empty","conditions","default_condition","inputs_separator","select_placeholder","display_empty_filter","default_filter","optgroups","default_rule_flags","filter_readonly","operator_readonly","value_readonly","no_delete","default_group_flags","condition_readonly","no_add_rule","no_add_group","group","rule","filterSelect","operatorSelect","ruleValueSelect","remove_group","remove_rule","defaults","fct","methods","isArray","tmp","plugin","getPluginOptions","property","init","rules","setRules","setRoot","definedFilters","length","i","push","input","operator","field","label","optgroup","values","cleanValues","iterateOptions","bind","groupSort","placeholder","placeholder_value","entry","sort","self","a","b","translate","localeCompare","definedOperators","Selectors","is","$group","closest","getModel","condition","val","$rule","getFilterById","getOperatorByType","addRule","deleteRule","addGroup","deleteGroup","drop","node","remove","refreshGroupsConditions","add","parent","index","prependTo","find","insertAfter","move","detach","update","oldValue","Rule","updateError","applyRuleFlags","updateRuleFilter","updateRuleOperator","updateRuleValue","applyGroupFlags","updateGroupCondition","data","flags","nextGroupId","getGroupTemplate","Group","level","isDefaultPrevented","isRoot","del","each","previousCondition","$this","prop","toggleClass","walk","nextRuleId","getRuleTemplate","createRuleFilters","$filterSelect","getRuleFilterSelect","html","createRuleOperators","$operatorContainer","empty","getOperators","$operatorSelect","getRuleOperatorSelect","default_operator","__","createRuleInput","$valueContainer","$inputs","$ruleInput","getRuleInput","css","input_event","_updating_input","_updating_value","getRuleInputValue","plugin_config","default_value","previousFilter","previousOperator","hide","previousValue","setRuleInputValue","clearErrors","removeClass","errorMessage","fmt","eq","triggerValidationError","destroy","removeAttr","clear","removeData","reset","setOptions","opt","target","Node","validate","skip_empty","valid","parse","done","errors","validateValue","res","getRules","get_flags","allow_invalid","out","groupData","getGroupFlags","isEmptyObject","ruleData","getRuleFlags","parseGroupFlags","item","parseRuleFlags","validation","result","callback","_validateValue","tempValue","allow_empty_value","j","min","parseInt","getValidationMessage","max","format","test","isNaN","parseFloat","step","toPrecision","window","moment","isValid","trim","toLowerCase","isAfter","l","doThrow","valueGetter","$value","escapeElementId","value_separator","subval","changeType","valueParser","valueSetter","readonly","all","ret","key","category","translation","messages","h","getRuleValueSelect","value_id","vertical","size","rows","utils","isPlainObject","args","message","err","Error","escapeString","escapeRegExp","$0","$1","$2","items","newItems","idx","lastIndexOf","splice","defineModelProperties","obj","fields","defineProperty","enumerable","get","set","apply","getPos","getNodePos","removeNode","moveAfter","moveAtBegin","moveAtEnd","insertNode","create","constructor","reverse","cbRule","cbGroup","context","stop","recursive","moveSortableToTarget","method","getStmtConfig","stmt","config","match","fn","option","font","colors","color","_def_","style","selectpicker","Constructor","container","width","showIcon","tooltip","fixTitle","$h","placement","setFilters","deleteOrphans","filtersIds","checkOrphans","updateBuilder","updateDisabledFilters","addFilter","newFilters","position","concat","some","removeFilter","filterIds","chosen","mode","$p","description","getFilterDescription","appendTo","icon","popover","$b","content","bootbox","alert","invert","display_rules_button","invert_rules","disable_template","after","prepend","silent_fail","operatorOpposites","conditionOpposites","AND","OR","tempOpts","no_invert","mongoOperators","$ne","$in","$nin","$lt","$lte","$gt","$gte","$regex","$options","mongoRuleOperators","$eq","op","getMongo","toUpperCase","parts","mdb","ope","ruleExpression","groupExpression","getRulesFromMongo","query","getMongoCondition","topKey","getMongoOperator","mdbrl","opVal","getMongoDBFieldID","setRulesFromMongo","matchingFilters","knownKeys","not","updateGroupNot","icon_unchecked","json","operation","SQLParser","nodes","Op","$nor","icon_checked","group_not","ghost","src","moved","default_no_sortable","no_sortable","interact","dynamicDrop","pointerMoveTolerance","inherit_no_sortable","inherit_no_drop","no_drop","draggable","allowFrom","drag_handle","onstart","clone","outerWidth","ph","height","outerHeight","onmove","top","clientY","left","clientX","onend","dropzone","relatedTarget","accept","rule_and_group_containers","ondragenter","ondrop","unset","boolean_as_integer","sqlOperators","sep","mod","sqlRuleOperator","=","!=","LIKE","NOT LIKE","IN","NOT IN","<=",">=","BETWEEN","NOT BETWEEN","IS","IS NOT","sqlStatements","question_mark","params","run","numbered","char","named","indexes","sqlRuleStatement","esc","sql","regex1","regex2","getSQL","nl","sqlFn","getRulesFromSQL","parsed","where","curr","flatten","next","right","sqlrl","JSON","stringify","getSQLFieldID","setRulesFromSQL","used_filters","applyDisabledFilters","clearDisabledFilters","unique","filterId","groups","__locale","__author","no_filter","empty_group","radio_empty","checkbox_empty","select_empty","string_empty","string_exceed_min_length","string_exceed_max_length","string_invalid_format","number_nan","number_not_integer","number_not_double","number_exceed_min","number_exceed_max","number_wrong_step","number_between_invalid","datetime_empty","datetime_invalid","datetime_exceed_min","datetime_exceed_max","datetime_between_invalid","boolean_not_valid","operator_not_multiple","NOT"],"mappings":"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","file":"query-builder.standalone.min.js"}
\ No newline at end of file
diff --git a/dist/scss/dark.scss b/dist/scss/dark.scss
new file mode 100644
index 00000000..d9ac03cb
--- /dev/null
+++ b/dist/scss/dark.scss
@@ -0,0 +1,19 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Copyright 2014-2020 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+$theme-name: dark;
+
+$group-background-color: rgba(50, 70, 80, .5);
+$group-border-color: #00164A;
+
+$rule-background-color: rgba(40, 40, 40, .9);
+$rule-border-color: #111;
+
+$error-border-color: #800;
+$error-background-color: #322;
+
+$ticks-color: #222;
+
+@import 'default';
diff --git a/dist/scss/default.scss b/dist/scss/default.scss
new file mode 100644
index 00000000..c91f96e6
--- /dev/null
+++ b/dist/scss/default.scss
@@ -0,0 +1,186 @@
+/*!
+ * jQuery QueryBuilder 2.5.0
+ * Copyright 2014-2020 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+$theme-name: default !default;
+
+// common
+$item-vertical-spacing: 4px !default;
+$item-border-radius: 5px !default;
+
+// groups
+$group-background-color: rgba(250, 240, 210, .5) !default;
+$group-border-color: #DCC896 !default;
+$group-border: 1px solid $group-border-color !default;
+$group-padding: 10px !default;
+
+// rules
+$rule-background-color: rgba(255, 255, 255, .9) !default;
+$rule-border-color: #EEE !default;
+$rule-border: 1px solid $rule-border-color !default;
+$rule-padding: 5px !default;
+// scss-lint:disable ColorVariable
+$rule-value-separator: 1px solid #DDD !default;
+
+// errors
+$error-icon-color: #F00 !default;
+$error-border-color: #F99 !default;
+$error-background-color: #FDD !default;
+
+// ticks
+$ticks-width: 2px !default;
+$ticks-color: #CCC !default;
+$ticks-position: 5px, 10px !default;
+
+
+// ABSTRACTS
+%base-container {
+ position: relative;
+ margin: $item-vertical-spacing 0;
+ border-radius: $item-border-radius;
+ padding: $rule-padding;
+ border: $rule-border;
+ background: $rule-background-color;
+}
+
+%rule-component {
+ display: inline-block;
+ margin: 0 5px 0 0;
+ vertical-align: middle;
+}
+
+.query-builder {
+
+ // GROUPS
+ .rules-group-container {
+ @extend %base-container;
+
+ padding: $group-padding;
+ padding-bottom: #{$group-padding - $item-vertical-spacing};
+ border: $group-border;
+ background: $group-background-color;
+ }
+
+ .rules-group-header {
+ margin-bottom: $group-padding;
+
+ .group-conditions {
+ .btn.readonly:not(.active),
+ input[name$='_cond'] {
+ border: 0;
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
+ white-space: nowrap;
+ }
+
+ .btn.readonly {
+ border-radius: 3px;
+ }
+ }
+ }
+
+ .rules-list {
+ list-style: none;
+ padding: 0 0 0 #{nth($ticks-position, 1) + nth($ticks-position, 2)};
+ margin: 0;
+ }
+
+ // RULES
+ .rule-container {
+ @extend %base-container;
+
+ .rule-filter-container,
+ .rule-operator-container,
+ .rule-value-container {
+ @extend %rule-component;
+ }
+ }
+
+ .rule-value-container {
+ border-left: $rule-value-separator;
+ padding-left: 5px;
+
+ label {
+ margin-bottom: 0;
+ font-weight: normal;
+
+ &.block {
+ display: block;
+ }
+ }
+
+ select,
+ input[type='text'],
+ input[type='number'] {
+ padding: 1px;
+ }
+ }
+
+ // ERRORS
+ .error-container {
+ @extend %rule-component;
+ display: none;
+ cursor: help;
+ color: $error-icon-color;
+ }
+
+ .has-error {
+ background-color: $error-background-color;
+ border-color: $error-border-color;
+
+ .error-container {
+ display: inline-block !important;
+ }
+ }
+
+ // TICKS
+ .rules-list>* {
+ &::before,
+ &::after {
+ content: '';
+ position: absolute;
+ left: #{-1 * nth($ticks-position, 2)};
+ width: nth($ticks-position, 2);
+ height: calc(50% + #{$item-vertical-spacing});
+ border-color: $ticks-color;
+ border-style: solid;
+ }
+
+ &::before {
+ top: #{-2 * $ticks-width};
+ border-width: 0 0 $ticks-width $ticks-width;
+ }
+
+ &::after {
+ top: 50%;
+ border-width: 0 0 0 $ticks-width;
+ }
+
+ &:first-child::before {
+ top: #{-$group-padding - $ticks-width};
+ height: calc(50% + #{$group-padding + $item-vertical-spacing});
+ }
+
+ &:last-child::before {
+ border-radius: 0 0 0 #{2 * $ticks-width};
+ }
+
+ &:last-child::after {
+ display: none;
+ }
+ }
+}
+
+// import
+@import "plugins/_bt-checkbox";
+@import "plugins/_bt-tooltip-errors";
+@import "plugins/_filter-description";
+@import "plugins/_invert";
+@import "plugins/_sortable";
+// endimport
diff --git a/dist/scss/plugins/_bt-checkbox.scss b/dist/scss/plugins/_bt-checkbox.scss
new file mode 100644
index 00000000..324f610f
--- /dev/null
+++ b/dist/scss/plugins/_bt-checkbox.scss
@@ -0,0 +1,12 @@
+.query-builder.bt-checkbox-glyphicons {
+ .checkbox input[type='checkbox']:checked + label::after {
+ font-family: 'Glyphicons Halflings';
+ content: '\e013';
+ }
+
+ .checkbox label::after {
+ padding-left: 4px;
+ padding-top: 2px;
+ font-size: 9px;
+ }
+}
diff --git a/dist/scss/plugins/_bt-tooltip-errors.scss b/dist/scss/plugins/_bt-tooltip-errors.scss
new file mode 100644
index 00000000..21323e5f
--- /dev/null
+++ b/dist/scss/plugins/_bt-tooltip-errors.scss
@@ -0,0 +1,9 @@
+$error-tooltip-color: #F99;
+
+@if $theme-name == 'dark' {
+ $error-tooltip-color: #F22;
+}
+
+.query-builder .error-container + .tooltip .tooltip-inner {
+ color: $error-tooltip-color !important;
+}
diff --git a/dist/scss/plugins/_filter-description.scss b/dist/scss/plugins/_filter-description.scss
new file mode 100644
index 00000000..80a2af71
--- /dev/null
+++ b/dist/scss/plugins/_filter-description.scss
@@ -0,0 +1,21 @@
+$description-background-color: #D9EDF7;
+$description-border-color: #BCE8F1;
+$description-text-color: #31708F;
+
+@if $theme-name == 'dark' {
+ $description-background-color: rgba(0, 170, 255, .2);
+ $description-text-color: #AAD1E4;
+ $description-border-color: #346F7B;
+}
+
+$description-border: 1px solid $description-border-color;
+
+.query-builder p.filter-description {
+ margin: $rule-padding 0 0 0;
+ background: $description-background-color;
+ border: $description-border;
+ color: $description-text-color;
+ border-radius: $item-border-radius;
+ padding: #{$rule-padding / 2} $rule-padding;
+ font-size: .8em;
+}
diff --git a/dist/scss/plugins/_invert.scss b/dist/scss/plugins/_invert.scss
new file mode 100644
index 00000000..5eb0458b
--- /dev/null
+++ b/dist/scss/plugins/_invert.scss
@@ -0,0 +1,5 @@
+.query-builder {
+ .rules-group-header [data-invert] {
+ margin-left: 5px;
+ }
+}
diff --git a/dist/scss/plugins/_sortable.scss b/dist/scss/plugins/_sortable.scss
new file mode 100644
index 00000000..ac902fe1
--- /dev/null
+++ b/dist/scss/plugins/_sortable.scss
@@ -0,0 +1,28 @@
+$placeholder-border-color: #BBB;
+$placeholder-border: 1px dashed $placeholder-border-color;
+
+.query-builder {
+ .drag-handle {
+ @extend %rule-component;
+ cursor: move;
+ vertical-align: middle;
+ margin-left: 5px;
+ }
+
+ .dragging {
+ position: fixed;
+ opacity: .5;
+ z-index: 100;
+
+ &::before,
+ &::after {
+ display: none;
+ }
+ }
+
+ .rule-placeholder {
+ @extend %base-container;
+ border: $placeholder-border;
+ opacity: .7;
+ }
+}
diff --git a/examples/index.html b/examples/index.html
index e6fc840f..9f53ea8a 100644
--- a/examples/index.html
+++ b/examples/index.html
@@ -28,7 +28,7 @@