diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index fe882f7e..be3320fd 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -3,6 +3,8 @@ ## Work on `dev` Any merge request should be created from and issued to the `dev` branch. +Do not add the `dist` files to your pull request. The directory is ignored for a reason: it is generated and pushed only when doing a release on `master`. + ## Core vs Plugins I want to keep the core clean of extra (and certainly awesome) functionalities. That includes, but is not limited to, export/import plugins, visual aids, etc. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 25399e11..7fe8317d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,6 +2,7 @@ - [ ] I read the [guidelines for contributing](https://github.com/mistic100/jQuery-QueryBuilder/blob/master/.github/CONTRIBUTING.md) - [ ] I created my branch from `dev` and I am issuing the PR to `dev` +- [ ] I didn't pushed the `dist` directory - [ ] Unit tests are OK - [ ] If it's a new feature, I added the necessary unit tests - [ ] If it's a new language, I filled the `__locale` and `__author` fields diff --git a/.npmignore b/.npmignore index 4dec3eec..54026ae7 100644 --- a/.npmignore +++ b/.npmignore @@ -2,4 +2,4 @@ build composer.json Gruntfile.js -bower_components +tests/ diff --git a/.travis.yml b/.travis.yml index 689c955f..6a2b5a40 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,6 @@ language: node_js node_js: - - "5" + - "8" before_install: - npm install -g grunt-cli - - npm install -g bower -before_script: - - bower install after_success: grunt coveralls diff --git a/Gruntfile.js b/Gruntfile.js index 40cdd50a..c98c3acd 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -27,8 +27,8 @@ module.exports = function(grunt) { 'src/jquery.js' ], js_files_for_standalone: [ - 'bower_components/jquery-extendext/jQuery.extendext.js', - 'bower_components/doT/doT.js', + 'node_modules/jquery-extendext/jQuery.extendext.js', + 'node_modules/dot/doT.js', 'dist/js/query-builder.js' ] }); @@ -57,6 +57,11 @@ module.exports = function(grunt) { port: 9000, livereload: true } + }, + test: { + options: { + port: 9001 + } } }, @@ -238,7 +243,7 @@ module.exports = function(grunt) { uglify: { options: { banner: '<%= banner %>\n', - mangle: { except: ['$'] } + mangle: { reserved: ['$'] } }, dist: { files: [{ @@ -346,7 +351,7 @@ module.exports = function(grunt) { qunit: { all: { options: { - urls: ['tests/index.html?coverage=true'], + urls: ['http://localhost:<%= connect.test.options.port %>/tests/index.html?coverage=true'], noGlobals: true } } @@ -360,7 +365,8 @@ module.exports = function(grunt) { src: ['src/*.js', 'src/plugins/**/plugin.js'] }], options: { - dest: '.coverage-results/all.lcov' + dest: '.coverage-results/all.lcov', + prefix: 'http://localhost:<%= connect.test.options.port %>/' } } }, @@ -414,6 +420,7 @@ module.exports = function(grunt) { 'build_css', 'injector:testSrc', 'injector:testModules', + 'connect:test', 'qunit_blanket_lcov', 'qunit' ]); @@ -423,7 +430,7 @@ module.exports = function(grunt) { 'build_css', 'injector:example', 'open', - 'connect', + 'connect:dev', 'watch' ]); diff --git a/README.md b/README.md index 6798d48e..14e526d2 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ [![jsDelivr CDN](https://data.jsdelivr.com/v1/package/npm/jQuery-QueryBuilder/badge)](https://www.jsdelivr.com/package/npm/jQuery-QueryBuilder) [![Build Status](https://img.shields.io/travis/mistic100/jQuery-QueryBuilder.svg?style=flat-square)](https://travis-ci.org/mistic100/jQuery-QueryBuilder) [![Coverage Status](https://img.shields.io/coveralls/mistic100/jQuery-QueryBuilder/master.svg?style=flat-square)](https://coveralls.io/r/mistic100/jQuery-QueryBuilder) +[![Dependencies Status](https://david-dm.org/mistic100/jQuery-QueryBuilder/status.svg?style=flat-square)](https://david-dm.org/mistic100/jQuery-QueryBuilder) jQuery plugin offering an simple interface to create complex queries. @@ -39,11 +40,12 @@ $ npm install jQuery-QueryBuilder jQuery-QueryBuilder is available on [jsDelivr](https://www.jsdelivr.com/package/npm/jQuery-QueryBuilder). ### Dependencies - * jQuery >= 1.10 - * Bootstrap >= 3.1 (CSS only) + * [jQuery 3](https://jquery.com) + * [Bootstrap 3](https://getbootstrap.com/docs/3.3) (CSS only) * [jQuery.extendext](https://github.com/mistic100/jQuery.extendext) - * [doT.js >= 1.0.3](http://olado.github.io/doT) + * [doT.js](http://olado.github.io/doT) * [MomentJS](http://momentjs.com) (optional, for Date/Time validation) + * [SQL Parser](https://github.com/mistic100/sql-parser) (optional, for SQL methods) * Other Bootstrap/jQuery plugins used by plugins ($.extendext and doT.js are directly included in the [standalone](https://github.com/mistic100/jQuery-QueryBuilder/blob/master/dist/js/query-builder.standalone.js) file) @@ -60,11 +62,10 @@ jQuery-QueryBuilder is available on [jsDelivr](https://www.jsdelivr.com/package/ * NodeJS + NPM: `apt-get install nodejs-legacy npm` * Grunt CLI: `npm install -g grunt-cli` - * Bower: `npm install -g bower` #### Run -Install Node and Bower dependencies `npm install & bower install` then run `grunt` in the root directory to generate production files inside `dist`. +Install Node and Bower dependencies `npm install` then run `grunt` in the root directory to generate production files inside `dist`. #### Options diff --git a/bower.json b/bower.json index 8c6ce3a3..0a763480 100644 --- a/bower.json +++ b/bower.json @@ -13,22 +13,12 @@ "dist/css/query-builder.default.css" ], "dependencies": { - "jquery": ">=1.9.0", + "jquery": ">=1.10.0", "bootstrap": ">=3.1.0 <4", "moment": ">=2.6.0", "jquery-extendext": ">=0.1.2", "doT": ">=1.0.3" }, - "devDependencies": { - "blanket": "^1.1.0", - "qunit": "^1.23.0", - "bootstrap-select": "^1.10.0", - "bootbox": "^4.4.0", - "awesome-bootstrap-checkbox": "^0.3.0", - "sql-parser": "^1.1.0", - "bind-polyfill": "~1.0.0", - "interact": "^1.2.6" - }, "keywords": [ "jquery", "query", diff --git a/composer.json b/composer.json index 7fd8ad11..7402f37f 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ "description": "jQuery plugin for user friendly query/filter creator", "require": { "robloach/component-installer": "*", - "components/jquery": ">=1.9.0", + "components/jquery": ">=1.10.0", "moment/moment": ">=2.6.0", "components/bootstrap": ">=3.1.0 <4" }, diff --git a/dist/css/query-builder.dark.css b/dist/css/query-builder.dark.css index 01d3c6ac..979688f1 100644 --- a/dist/css/query-builder.dark.css +++ b/dist/css/query-builder.dark.css @@ -1,6 +1,6 @@ /*! - * jQuery QueryBuilder 2.4.5 - * Copyright 2014-2017 Damien "Mistic" Sorel (http://www.strangeplanet.fr) + * jQuery QueryBuilder 2.5.0 + * Copyright 2014-2018 Damien "Mistic" Sorel (http://www.strangeplanet.fr) * Licensed under MIT (http://opensource.org/licenses/MIT) */ .query-builder .rules-group-container, .query-builder .rule-container, .query-builder .rule-placeholder { diff --git a/dist/css/query-builder.dark.min.css b/dist/css/query-builder.dark.min.css index 56c37cbd..8f12aa0d 100644 --- a/dist/css/query-builder.dark.min.css +++ b/dist/css/query-builder.dark.min.css @@ -1,6 +1,6 @@ /*! - * jQuery QueryBuilder 2.4.5 - * Copyright 2014-2017 Damien "Mistic" Sorel (http://www.strangeplanet.fr) + * jQuery QueryBuilder 2.5.0 + * Copyright 2014-2018 Damien "Mistic" Sorel (http://www.strangeplanet.fr) * Licensed under MIT (http://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 10px 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=text],.query-builder .rule-value-container input[type=number],.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 .dragging::after,.query-builder .dragging::before,.query-builder .rules-list>:last-child::after{display:none}.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.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;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 .rule-placeholder{border:1px dashed #BBB;opacity:.7} \ No newline at end of file +.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 index f3e3a15a..783a24c3 100644 --- a/dist/css/query-builder.default.css +++ b/dist/css/query-builder.default.css @@ -1,6 +1,6 @@ /*! - * jQuery QueryBuilder 2.4.5 - * Copyright 2014-2017 Damien "Mistic" Sorel (http://www.strangeplanet.fr) + * jQuery QueryBuilder 2.5.0 + * Copyright 2014-2018 Damien "Mistic" Sorel (http://www.strangeplanet.fr) * Licensed under MIT (http://opensource.org/licenses/MIT) */ .query-builder .rules-group-container, .query-builder .rule-container, .query-builder .rule-placeholder { diff --git a/dist/css/query-builder.default.min.css b/dist/css/query-builder.default.min.css index 985eb9ba..4f3c27b3 100644 --- a/dist/css/query-builder.default.min.css +++ b/dist/css/query-builder.default.min.css @@ -1,6 +1,6 @@ /*! - * jQuery QueryBuilder 2.4.5 - * Copyright 2014-2017 Damien "Mistic" Sorel (http://www.strangeplanet.fr) + * jQuery QueryBuilder 2.5.0 + * Copyright 2014-2018 Damien "Mistic" Sorel (http://www.strangeplanet.fr) * Licensed under MIT (http://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 10px 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=text],.query-builder .rule-value-container input[type=number],.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 .dragging::after,.query-builder .dragging::before,.query-builder .rules-list>:last-child::after{display:none}.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.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;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 .rule-placeholder{border:1px dashed #BBB;opacity:.7} \ No newline at end of file +.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 index 345c6215..1d67dea3 100644 --- a/dist/i18n/query-builder.ar.js +++ b/dist/i18n/query-builder.ar.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Arabic (ar) * Author: Mohamed YOUNES, https://github.com/MedYOUNES * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.az.js b/dist/i18n/query-builder.az.js index 83eec512..fa42f028 100644 --- a/dist/i18n/query-builder.az.js +++ b/dist/i18n/query-builder.az.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Azerbaijan (az) * Author: Megaplan, mborisv * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.bg.js b/dist/i18n/query-builder.bg.js index 5e7106a5..8e321707 100644 --- a/dist/i18n/query-builder.bg.js +++ b/dist/i18n/query-builder.bg.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Bulgarian (bg) * Author: Valentin Hristov * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.cs.js b/dist/i18n/query-builder.cs.js index 49192f00..9d70dbd8 100644 --- a/dist/i18n/query-builder.cs.js +++ b/dist/i18n/query-builder.cs.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Čeština (cs) * Author: Megaplan, mborisv * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.da.js b/dist/i18n/query-builder.da.js index 83017c89..cff18b46 100644 --- a/dist/i18n/query-builder.da.js +++ b/dist/i18n/query-builder.da.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Danish (da) * Author: Jna Borup Coyle, github@coyle.dk * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.de.js b/dist/i18n/query-builder.de.js index 605b98d5..bf2699c7 100644 --- a/dist/i18n/query-builder.de.js +++ b/dist/i18n/query-builder.de.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: German (de) * Author: "raimu" * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.el.js b/dist/i18n/query-builder.el.js index fa9dddd1..e0a951b9 100644 --- a/dist/i18n/query-builder.el.js +++ b/dist/i18n/query-builder.el.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Greek (el) * Author: Stelios Patsatzis, https://www.linkedin.com/in/stelios-patsatzis-89841561 * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.en.js b/dist/i18n/query-builder.en.js index d4f55468..a3503dfc 100644 --- a/dist/i18n/query-builder.en.js +++ b/dist/i18n/query-builder.en.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: English (en) * Author: Damien "Mistic" Sorel, http://www.strangeplanet.fr * Licensed under MIT (http://opensource.org/licenses/MIT) @@ -71,7 +71,7 @@ QueryBuilder.regional['en'] = { "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} isgreater than {1}", + "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" }, diff --git a/dist/i18n/query-builder.es.js b/dist/i18n/query-builder.es.js index 80ded2b3..970f45e2 100644 --- a/dist/i18n/query-builder.es.js +++ b/dist/i18n/query-builder.es.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Spanish (es) * Author: "pyarza", "kddlb" * Licensed under MIT (http://opensource.org/licenses/MIT) @@ -38,6 +38,7 @@ QueryBuilder.regional['es'] = { "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", @@ -67,7 +68,12 @@ QueryBuilder.regional['es'] = { "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}" + "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" } }; diff --git a/dist/i18n/query-builder.fa-IR.js b/dist/i18n/query-builder.fa-IR.js index 4c2d3196..6af86edf 100644 --- a/dist/i18n/query-builder.fa-IR.js +++ b/dist/i18n/query-builder.fa-IR.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Farsi (fa-ir) * Author: Behzad Sedighzade, behzad.sedighzade@gmail.com * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.fr.js b/dist/i18n/query-builder.fr.js index a2f7acb2..7ff428d9 100644 --- a/dist/i18n/query-builder.fr.js +++ b/dist/i18n/query-builder.fr.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: French (fr) * Author: Damien "Mistic" Sorel, http://www.strangeplanet.fr * Licensed under MIT (http://opensource.org/licenses/MIT) @@ -29,14 +29,14 @@ QueryBuilder.regional['fr'] = { "OR": "OU" }, "operators": { - "equal": "égal", - "not_equal": "non égal", - "in": "dans", - "not_in": "pas dans", - "less": "inférieur", - "less_or_equal": "inférieur ou égal", - "greater": "supérieur", - "greater_or_equal": "supérieur ou égal", + "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", diff --git a/dist/i18n/query-builder.he.js b/dist/i18n/query-builder.he.js index 10f413cd..bb565def 100644 --- a/dist/i18n/query-builder.he.js +++ b/dist/i18n/query-builder.he.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Hebrew (he) * Author: Kfir Stri https://github.com/kfirstri * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.it.js b/dist/i18n/query-builder.it.js index d5dd2437..a2a8aa3b 100644 --- a/dist/i18n/query-builder.it.js +++ b/dist/i18n/query-builder.it.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Italian (it) * Author: davegraziosi * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.nl.js b/dist/i18n/query-builder.nl.js index 46a9e411..831c8c91 100644 --- a/dist/i18n/query-builder.nl.js +++ b/dist/i18n/query-builder.nl.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Dutch (nl) * Author: "Roywcm" * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.no.js b/dist/i18n/query-builder.no.js index 99a62f44..358817fa 100644 --- a/dist/i18n/query-builder.no.js +++ b/dist/i18n/query-builder.no.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Norwegian (no) * Author: Jna Borup Coyle, github@coyle.dk * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.pl.js b/dist/i18n/query-builder.pl.js index 574e26e5..f0af9af3 100644 --- a/dist/i18n/query-builder.pl.js +++ b/dist/i18n/query-builder.pl.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Polish (pl) * Author: Artur Smolarek * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.pt-BR.js b/dist/i18n/query-builder.pt-BR.js index 68781c7d..679eff99 100644 --- a/dist/i18n/query-builder.pt-BR.js +++ b/dist/i18n/query-builder.pt-BR.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Brazilian Portuguese (pr-BR) * Author: Leandro Gehlen, leandrogehlen@gmail.com; Marcos Ferretti, marcosvferretti@gmail.com * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.pt-PT.js b/dist/i18n/query-builder.pt-PT.js index 8779f84f..f3bea444 100644 --- a/dist/i18n/query-builder.pt-PT.js +++ b/dist/i18n/query-builder.pt-PT.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Portuguese (pt-PT) * Author: Miguel Guerreiro, migas.csi@gmail.com * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.ro.js b/dist/i18n/query-builder.ro.js index bac123d6..475b54ec 100644 --- a/dist/i18n/query-builder.ro.js +++ b/dist/i18n/query-builder.ro.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Romanian (ro) * Author: ArianServ * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.ru.js b/dist/i18n/query-builder.ru.js index 009c3276..750dfa70 100644 --- a/dist/i18n/query-builder.ru.js +++ b/dist/i18n/query-builder.ru.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Russian (ru) * Licensed under MIT (http://opensource.org/licenses/MIT) */ diff --git a/dist/i18n/query-builder.sq.js b/dist/i18n/query-builder.sq.js index fa49a0ea..ad3cba50 100644 --- a/dist/i18n/query-builder.sq.js +++ b/dist/i18n/query-builder.sq.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Albanian (sq) * Author: Tomor Pupovci * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.tr.js b/dist/i18n/query-builder.tr.js index ad72d35b..3f774a77 100644 --- a/dist/i18n/query-builder.tr.js +++ b/dist/i18n/query-builder.tr.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Turkish (tr) * Author: Aykut Alpgiray Ateş * Licensed under MIT (http://opensource.org/licenses/MIT) @@ -53,23 +53,25 @@ QueryBuilder.regional['tr'] = { "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ı", + "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ğilr", + "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" }, diff --git a/dist/i18n/query-builder.ua.js b/dist/i18n/query-builder.ua.js index cfbf57ac..bc215a59 100644 --- a/dist/i18n/query-builder.ua.js +++ b/dist/i18n/query-builder.ua.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Ukrainian (ua) * Author: Megaplan, mborisv * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/i18n/query-builder.zh-CN.js b/dist/i18n/query-builder.zh-CN.js index 4ef85f24..406baa7e 100644 --- a/dist/i18n/query-builder.zh-CN.js +++ b/dist/i18n/query-builder.zh-CN.js @@ -1,5 +1,5 @@ /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: Simplified Chinese (zh_CN) * Author: shadowwind, shatteredwindgo@gmail.com * Licensed under MIT (http://opensource.org/licenses/MIT) diff --git a/dist/js/query-builder.js b/dist/js/query-builder.js index 97850ced..0039cfa3 100644 --- a/dist/js/query-builder.js +++ b/dist/js/query-builder.js @@ -1,6 +1,6 @@ /*! - * jQuery QueryBuilder 2.4.5 - * Copyright 2014-2017 Damien "Mistic" Sorel (http://www.strangeplanet.fr) + * jQuery QueryBuilder 2.5.0 + * Copyright 2014-2018 Damien "Mistic" Sorel (http://www.strangeplanet.fr) * Licensed under MIT (http://opensource.org/licenses/MIT) */ (function(root, factory) { @@ -399,7 +399,8 @@ QueryBuilder.DEFAULTS = { group: null, rule: null, filterSelect: null, - operatorSelect: null + operatorSelect: null, + ruleValueSelect: null }, lang_code: 'en', @@ -649,12 +650,40 @@ QueryBuilder.prototype.checkFilters = function(filters) { 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; } - Utils.iterateOptions(filter.values, function(key) { - if (key == filter.placeholder_value) { + + 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); } }); @@ -1235,10 +1264,10 @@ QueryBuilder.prototype.createRuleInput = function(rule) { $inputs = $inputs.add($ruleInput); } - $valueContainer.show(); + $valueContainer.css('display', ''); $inputs.on('change ' + (filter.input_event || ''), function() { - if (!this._updating_input) { + if (!rule._updating_input) { rule._updating_value = true; rule.value = self.getRuleInputValue(rule); rule._updating_value = false; @@ -1306,7 +1335,6 @@ QueryBuilder.prototype.updateRuleFilter = function(rule, previousFilter) { */ QueryBuilder.prototype.updateRuleOperator = function(rule, previousOperator) { var $valueContainer = rule.$el.find(QueryBuilder.selectors.value_container); - var ruleValue = rule.value; if (!rule.operator || rule.operator.nb_inputs === 0) { $valueContainer.hide(); @@ -1314,7 +1342,7 @@ QueryBuilder.prototype.updateRuleOperator = function(rule, previousOperator) { rule.__.value = undefined; } else { - $valueContainer.show(); + $valueContainer.css('display', ''); if ($valueContainer.is(':empty') || !previousOperator || rule.operator.nb_inputs !== previousOperator.nb_inputs || @@ -1326,6 +1354,9 @@ QueryBuilder.prototype.updateRuleOperator = function(rule, previousOperator) { 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); } /** @@ -1338,9 +1369,6 @@ QueryBuilder.prototype.updateRuleOperator = function(rule, previousOperator) { this.trigger('afterUpdateRuleOperator', rule, previousOperator); this.trigger('rulesChanged'); - - // FIXME is it necessary ? - this.updateRuleValue(rule, ruleValue); }; /** @@ -2408,11 +2436,20 @@ QueryBuilder.prototype.getRuleInputValue = function(rule) { } } - if (operator.multiple && filter.value_separator) { - value = value.map(function(val) { - return val.split(filter.value_separator); - }); - } + 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]; @@ -2449,7 +2486,7 @@ QueryBuilder.prototype.setRuleInputValue = function(rule, value) { return; } - this._updating_input = true; + rule._updating_input = true; if (filter.valueSetter) { filter.valueSetter.call(this, rule, value); @@ -2490,7 +2527,7 @@ QueryBuilder.prototype.setRuleInputValue = function(rule, value) { } } - this._updating_input = false; + rule._updating_input = false; }; /** @@ -2652,8 +2689,8 @@ QueryBuilder.prototype.getValidationMessage = function(validation, type, def) { QueryBuilder.templates.group = '\ -
\ -
\ +
\ +
\
\
\ -
\ -
    \ -
    \ -
    '; + \ +
    \ +
    \ +
    \ +'; QueryBuilder.templates.rule = '\ -
  • \ +
    \
    \
    \
  • '; +'; QueryBuilder.templates.filterSelect = '\ {{ var optgroup = null; }} \ @@ -2715,7 +2752,7 @@ QueryBuilder.templates.filterSelect = '\ \ {{?}} \ {{?}} \ - \ + \ {{~}} \ {{? optgroup !== null }}{{?}} \ '; @@ -2735,7 +2772,25 @@ QueryBuilder.templates.operatorSelect = '\ \ {{?}} \ {{?}} \ - \ + \ + {{~}} \ + {{? optgroup !== null }}{{?}} \ +'; + +QueryBuilder.templates.ruleValueSelect = '\ +{{ var optgroup = null; }} \ +'; @@ -2856,6 +2911,36 @@ QueryBuilder.prototype.getRuleOperatorSelect = function(rule, operators) { 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 @@ -2884,14 +2969,7 @@ QueryBuilder.prototype.getRuleInput = function(rule, value_id) { break; case 'select': - h += ''; + h = this.getRuleValueSelect(name, rule); break; case 'textarea': @@ -2953,10 +3031,11 @@ QueryBuilder.utils = Utils; * @callback Utils#OptionsIteratee * @param {string} key * @param {string} value + * @param {string} [optgroup] */ /** - * Iterates over radio/checkbox/selection options, it accept three formats + * Iterates over radio/checkbox/selection options, it accept four formats * * @example * // array of values @@ -2967,6 +3046,9 @@ QueryBuilder.utils = Utils; * @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 @@ -2975,12 +3057,18 @@ Utils.iterateOptions = function(options, tpl) { if (options) { if ($.isArray(options)) { options.forEach(function(entry) { - // array of one-element maps if ($.isPlainObject(entry)) { - $.each(entry, function(key, val) { - tpl(key, val); - return false; // break after first 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 { @@ -3042,19 +3130,32 @@ Utils.error = function() { * Changes the type of a value to int, float or bool * @param {*} value * @param {string} type - 'integer', 'double', 'boolean' or anything else (passthrough) - * @param {boolean} [boolAsInt=false] - return 0 or 1 for booleans * @returns {*} */ -Utils.changeType = function(value, type, boolAsInt) { +Utils.changeType = function(value, type) { + if (value === '' || value === undefined) { + return undefined; + } + switch (type) { // @formatter:off - case 'integer': return parseInt(value); - case 'double': return parseFloat(value); - case 'boolean': - var bool = value.trim().toLowerCase() === 'true' || value.trim() === '1' || value === 1; - return boolAsInt ? (bool ? 1 : 0) : bool; - default: return value; - // @formatter:on + 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 } }; @@ -3072,12 +3173,12 @@ Utils.escapeString = function(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 + case '\0': return '\\0'; + case '\n': return '\\n'; + case '\r': return '\\r'; + case '\b': return '\\b'; + default: return '\\' + s; + // @formatter:off } }) // uglify compliant @@ -4115,6 +4216,50 @@ QueryBuilder.extend(/** @lends module:plugins.ChangeFilters.prototype */ { }); +/** + * @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) { + 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 @@ -4140,7 +4285,7 @@ QueryBuilder.define('filter-description', function(options) { $p.appendTo(rule.$el); } else { - $p.show(); + $p.css('display', ''); } $p.html(' ' + description); @@ -4180,7 +4325,7 @@ QueryBuilder.define('filter-description', function(options) { }); } else { - $b.show(); + $b.css('display', ''); } $b.data('bs.popover').options.content = description; @@ -4214,7 +4359,7 @@ QueryBuilder.define('filter-description', function(options) { }); } else { - $b.show(); + $b.css('display', ''); } $b.data('description', description); @@ -4279,25 +4424,36 @@ QueryBuilder.define('invert', function(options) { }); // Modify templates - this.on('getGroupTemplate.filter', function(h, level) { - var $h = $(h.value); - $h.find(Selectors.condition_container).after(''); - h.value = $h.prop('outerHTML'); - }); - - if (options.display_rules_button && options.invert_rules) { - this.on('getRuleTemplate.filter', function(h) { + if (!options.disable_template) { + this.on('getGroupTemplate.filter', function(h) { var $h = $(h.value); - $h.find(Selectors.rule_actions).prepend(''); + $h.find(Selectors.condition_container).after( + '' + ); 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( + '' + ); + h.value = $h.prop('outerHTML'); + }); + } } }, { icon: 'glyphicon glyphicon-random', recursive: true, invert_rules: true, display_rules_button: false, - silent_fail: false + silent_fail: false, + disable_template: false }); QueryBuilder.defaults({ @@ -4538,7 +4694,6 @@ QueryBuilder.extend(/** @lends module:plugins.MongoDbSupport.prototype */ { else { var mdb = self.settings.mongoOperators[rule.operator]; var ope = self.getOperatorByType(rule.operator); - var values = []; if (mdb === undefined) { Utils.error('UndefinedMongoOperator', 'Unknown MongoDB operation for operator "{0}"', rule.operator); @@ -4548,10 +4703,6 @@ QueryBuilder.extend(/** @lends module:plugins.MongoDbSupport.prototype */ { if (!(rule.value instanceof Array)) { rule.value = [rule.value]; } - - rule.value.forEach(function(v) { - values.push(Utils.changeType(v, rule.type, false)); - }); } /** @@ -4565,7 +4716,7 @@ QueryBuilder.extend(/** @lends module:plugins.MongoDbSupport.prototype */ { var field = self.change('getMongoDBField', rule.field, rule); var ruleExpression = {}; - ruleExpression[field] = mdb.call(self, values); + ruleExpression[field] = mdb.call(self, rule.value); /** * Modifies the MongoDB expression generated for a rul @@ -4577,7 +4728,7 @@ QueryBuilder.extend(/** @lends module:plugins.MongoDbSupport.prototype */ { * @param {function} valueWrapper - function that takes the value and adds the operator * @returns {object} */ - parts.push(self.change('ruleToMongo', ruleExpression, rule, values, mdb)); + parts.push(self.change('ruleToMongo', ruleExpression, rule, rule.value, mdb)); } }); @@ -4844,15 +4995,17 @@ QueryBuilder.define('not-group', function(options) { }); // Modify templates - this.on('getGroupTemplate.filter', function(h, level) { - var $h = $(h.value); - $h.find(QueryBuilder.selectors.condition_container).prepend( - '' - ); - h.value = $h.prop('outerHTML'); - }); + if (!options.disable_template) { + this.on('getGroupTemplate.filter', function(h) { + var $h = $(h.value); + $h.find(QueryBuilder.selectors.condition_container).prepend( + '' + ); + h.value = $h.prop('outerHTML'); + }); + } // Export "not" to JSON this.on('groupToJson.filter', function(e, group) { @@ -4875,10 +5028,27 @@ QueryBuilder.define('not-group', function(options) { 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 = { + left: e.value, + operation: self.settings.default_condition, + right: null + }; + } + e.value.not = true; } }); + // Request to create sub-group if the "not" flag is set + this.on('sqlGroupsDistinct.filter', function(e, group, data) { + if (data.not) { + e.value = true; + } + }); + // Read "not" from parsed SQL this.on('sqlToGroup.filter', function(e, data) { e.value.not = !!data.not; @@ -4908,7 +5078,8 @@ QueryBuilder.define('not-group', function(options) { }); }, { icon_unchecked: 'glyphicon glyphicon-unchecked', - icon_checked: 'glyphicon glyphicon-check' + icon_checked: 'glyphicon glyphicon-check', + disable_template: false }); /** @@ -4977,6 +5148,7 @@ QueryBuilder.define('sortable', function(options) { var placeholder; var ghost; var src; + var moved; // Init drag and drop this.on('afterAddRule afterAddGroup', function(e, node) { @@ -4997,9 +5169,11 @@ QueryBuilder.define('sortable', function(options) { // Configure drag if (!node.flags.no_sortable) { interact(node.$el[0]) - .allowFrom(QueryBuilder.selectors.drag_handle) .draggable({ + allowForm: QueryBuilder.selectors.drag_handle, onstart: function(event) { + moved = false; + // get model of dragged element src = self.getModel(event.target); @@ -5023,7 +5197,13 @@ QueryBuilder.define('sortable', function(options) { ghost[0].style.top = event.clientY - 15 + 'px'; ghost[0].style.left = event.clientX - 15 + 'px'; }, - onend: function() { + 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; @@ -5033,7 +5213,7 @@ QueryBuilder.define('sortable', function(options) { placeholder = undefined; // show element - src.$el.show(); + src.$el.css('display', ''); /** * After a node has been moved with {@link module:plugins.Sortable} @@ -5057,7 +5237,9 @@ QueryBuilder.define('sortable', function(options) { moveSortableToTarget(placeholder, $(event.target), self); }, ondrop: function(event) { - moveSortableToTarget(src, $(event.target), self); + if (!moved) { + moveSortableToTarget(src, $(event.target), self); + } } }); @@ -5070,7 +5252,9 @@ QueryBuilder.define('sortable', function(options) { moveSortableToTarget(placeholder, $(event.target), self); }, ondrop: function(event) { - moveSortableToTarget(src, $(event.target), self); + if (!moved) { + moveSortableToTarget(src, $(event.target), self); + } } }); } @@ -5096,23 +5280,26 @@ QueryBuilder.define('sortable', function(options) { }); // Modify templates - this.on('getGroupTemplate.filter', function(h, level) { - if (level > 1) { + 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.condition_container).after('
    '); + $h.find(QueryBuilder.selectors.rule_header).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' + icon: 'glyphicon glyphicon-sort', + disable_template: false }); QueryBuilder.selectors.rule_and_group_containers = QueryBuilder.selectors.rule_container + ', ' + QueryBuilder.selectors.group_container; @@ -5433,7 +5620,9 @@ QueryBuilder.extend(/** @lends module:plugins.SqlSupport.prototype */ { nl = !!nl ? '\n' : ' '; var boolean_as_integer = this.getPluginOptions('sql-support', 'boolean_as_integer'); - if (stmt === true) stmt = 'question_mark'; + if (stmt === true) { + stmt = 'question_mark'; + } if (typeof stmt == 'string') { var config = getStmtConfig(stmt); stmt = this.settings.sqlStatements[config[1]](config[2]); @@ -5478,10 +5667,10 @@ QueryBuilder.extend(/** @lends module:plugins.SqlSupport.prototype */ { value += sql.sep; } - if (rule.type == 'integer' || rule.type == 'double' || rule.type == 'boolean') { - v = Utils.changeType(v, rule.type, boolean_as_integer); + if (rule.type == 'boolean' && boolean_as_integer) { + v = v ? 1 : 0; } - else if (!stmt) { + else if (!stmt && rule.type !== 'integer' && rule.type !== 'double' && rule.type !== 'boolean') { v = Utils.escapeString(v); } @@ -5632,6 +5821,10 @@ QueryBuilder.extend(/** @lends module:plugins.SqlSupport.prototype */ { 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); @@ -5655,7 +5848,19 @@ QueryBuilder.extend(/** @lends module:plugins.SqlSupport.prototype */ { // 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 - if (i > 0 && curr.condition != data.operation.toUpperCase()) { + + /** + * 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 - try by default if the group condition is different + * @param {object} group + * @param {object} AST + * @returns {boolean} + */ + var createGroup = self.change('sqlGroupsDistinct', i > 0 && curr.condition != data.operation.toUpperCase(), curr, data); + + if (createGroup) { /** * Modifies the group generated from the SQL expression (this is called before the group is filled with rules) * @event changer:sqlToGroup @@ -5932,7 +6137,7 @@ QueryBuilder.extend(/** @lends module:plugins.UniqueFilter.prototype */ { /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: English (en) * Author: Damien "Mistic" Sorel, http://www.strangeplanet.fr * Licensed under MIT (http://opensource.org/licenses/MIT) @@ -5992,7 +6197,7 @@ QueryBuilder.regional['en'] = { "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} isgreater than {1}", + "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" }, diff --git a/dist/js/query-builder.min.js b/dist/js/query-builder.min.js index 9c515efb..6f7d465a 100644 --- a/dist/js/query-builder.min.js +++ b/dist/js/query-builder.min.js @@ -1,8 +1,7 @@ /*! - * jQuery QueryBuilder 2.4.5 - * Copyright 2014-2017 Damien "Mistic" Sorel (http://www.strangeplanet.fr) + * jQuery QueryBuilder 2.5.0 + * Copyright 2014-2018 Damien "Mistic" Sorel (http://www.strangeplanet.fr) * Licensed under MIT (http://opensource.org/licenses/MIT) */ -!function(a,b){"function"==typeof define&&define.amd?define(["jquery","dot/doT","jquery-extendext"],b):"object"==typeof module&&module.exports?module.exports=b(require("jquery"),require("dot/doT"),require("jquery-extendext")):b(a.jQuery,a.doT)}(this,function($,a){"use strict";function b(){this.root=null,this.$=$(this)}function c(a){if(null!==a&&"object"==typeof a){var b=Object.keys(a);return 1===b.length?b[0]:void 0!==a.$gte&&void 0!==a.$lte?"between":void 0!==a.$lt&&void 0!==a.$gt?"not_between":void 0!==a.$regex?"$regex":void 0}return"eq"}function d(a){for(var b=Object.keys(a),c=0,d=b.length;c.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]"},g.templates={},g.regional={},g.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"]}},g.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},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:"glyphicon glyphicon-plus-sign",add_rule:"glyphicon glyphicon-plus",remove_group:"glyphicon glyphicon-remove",remove_rule:"glyphicon glyphicon-remove",error:"glyphicon glyphicon-warning-sign"}},g.plugins={},g.defaults=function(a){return"object"!=typeof a?"string"==typeof a?"object"==typeof g.DEFAULTS[a]?$.extend(!0,{},g.DEFAULTS[a]):g.DEFAULTS[a]:$.extend(!0,{},g.DEFAULTS):void $.extendext(!0,"replace",g.DEFAULTS,a)},g.define=function(a,b,c){g.plugins[a]={fct:b,def:c||{}}},g.extend=function(a){$.extend(g.prototype,a)},g.prototype.initPlugins=function(){if(this.plugins){if($.isArray(this.plugins)){var a={};this.plugins.forEach(function(b){a[b]=null}),this.plugins=a}Object.keys(this.plugins).forEach(function(a){a in g.plugins?(this.plugins[a]=$.extend(!0,{},g.plugins[a].def,this.plugins[a]||{}),g.plugins[a].fct.call(this,this.plugins[a])):h.error("Config",'Unable to find plugin "{0}"',a)},this)}},g.prototype.getPluginOptions=function(a,b){var c;return this.plugins&&this.plugins[a]?c=this.plugins[a]:g.plugins[a]&&(c=g.plugins[a].def),c?b?c[b]:c:void h.error("Config",'Unable to find plugin "{0}"',a)},g.prototype.init=function(a){this.trigger("afterInit"),a?(this.setRules(a),delete this.settings.rules):this.setRoot(!0)},g.prototype.checkFilters=function(a){var b=[];if(a&&0!==a.length||h.error("Config","Missing filters list"),a.forEach(function(a,c){switch(a.id||h.error("Config","Missing filter {0} id",c),b.indexOf(a.id)!=-1&&h.error("Config",'Filter "{0}" already defined',a.id),b.push(a.id),a.type?g.types[a.type]||h.error("Config",'Invalid type "{0}"',a.type):a.type="string",a.input?"function"!=typeof a.input&&g.inputs.indexOf(a.input)==-1&&h.error("Config",'Invalid input "{0}"',a.input):a.input="number"===g.types[a.type]?"number":"text",a.operators&&a.operators.forEach(function(a){"string"!=typeof a&&h.error("Config","Filter operators must be global operators types (string)")}),a.field||(a.field=a.id),a.label||(a.label=a.field),a.optgroup?(this.status.has_optgroup=!0,this.settings.optgroups[a.optgroup]||(this.settings.optgroups[a.optgroup]=a.optgroup)):a.optgroup=null,a.input){case"radio":case"checkbox":(!a.values||a.values.length<1)&&h.error("Config",'Missing filter "{0}" values',a.id);break;case"select":a.placeholder&&(void 0===a.placeholder_value&&(a.placeholder_value=-1),h.iterateOptions(a.values,function(b){b==a.placeholder_value&&h.error("Config",'Placeholder of filter "{0}" overlaps with one of its values',a.id)}))}},this),this.settings.sort_filters)if("function"==typeof this.settings.sort_filters)a.sort(this.settings.sort_filters);else{var c=this;a.sort(function(a,b){return c.translate(a.label).localeCompare(c.translate(b.label))})}return this.status.has_optgroup&&(a=h.groupSort(a,"optgroup")),a},g.prototype.checkOperators=function(a){var b=[];return a.forEach(function(c,d){"string"==typeof c?(g.OPERATORS[c]||h.error("Config",'Unknown operator "{0}"',c),a[d]=c=$.extendext(!0,"replace",{},g.OPERATORS[c])):(c.type||h.error("Config",'Missing "type" for operator {0}',d),g.OPERATORS[c.type]&&(a[d]=c=$.extendext(!0,"replace",{},g.OPERATORS[c.type],c)),void 0!==c.nb_inputs&&void 0!==c.apply_to||h.error("Config",'Missing "nb_inputs" and/or "apply_to" for operator "{0}"',c.type)),b.indexOf(c.type)!=-1&&h.error("Config",'Operator "{0}" already defined',c.type),b.push(c.type),c.optgroup?(this.status.has_operator_optgroup=!0,this.settings.optgroups[c.optgroup]||(this.settings.optgroups[c.optgroup]=c.optgroup)):c.optgroup=null},this),this.status.has_operator_optgroup&&(a=h.groupSort(a,"optgroup")),a},g.prototype.bindEvents=function(){var a=this,b=g.selectors;this.$el.on("change.queryBuilder",b.group_condition,function(){if($(this).is(":checked")){var c=$(this).closest(b.group_container);a.getModel(c).condition=$(this).val()}}),this.$el.on("change.queryBuilder",b.rule_filter,function(){var c=$(this).closest(b.rule_container);a.getModel(c).filter=a.getFilterById($(this).val())}),this.$el.on("change.queryBuilder",b.rule_operator,function(){var c=$(this).closest(b.rule_container);a.getModel(c).operator=a.getOperatorByType($(this).val())}),this.$el.on("click.queryBuilder",b.add_rule,function(){var c=$(this).closest(b.group_container);a.addRule(a.getModel(c))}),this.$el.on("click.queryBuilder",b.delete_rule,function(){var c=$(this).closest(b.rule_container);a.deleteRule(a.getModel(c))}),0!==this.settings.allow_groups&&(this.$el.on("click.queryBuilder",b.add_group,function(){var c=$(this).closest(b.group_container);a.addGroup(a.getModel(c))}),this.$el.on("click.queryBuilder",b.delete_group,function(){var c=$(this).closest(b.group_container);a.deleteGroup(a.getModel(c))})),this.model.on({drop:function(b,c){c.$el.remove(),a.refreshGroupsConditions()},add:function(b,c,d,e){0===e?d.$el.prependTo(c.$el.find(">"+g.selectors.rules_list)):d.$el.insertAfter(c.rules[e-1].$el),a.refreshGroupsConditions()},move:function(b,c,d,e){c.$el.detach(),0===e?c.$el.prependTo(d.$el.find(">"+g.selectors.rules_list)):c.$el.insertAfter(d.rules[e-1].$el),a.refreshGroupsConditions()},update:function(b,c,d,e,f){if(c instanceof k)switch(d){case"error":a.updateError(c);break;case"flags":a.applyRuleFlags(c);break;case"filter":a.updateRuleFilter(c,f);break;case"operator":a.updateRuleOperator(c,f);break;case"value":a.updateRuleValue(c,f)}else switch(d){case"error":a.updateError(c);break;case"flags":a.applyGroupFlags(c);break;case"condition":a.updateGroupCondition(c,f)}}})},g.prototype.setRoot=function(a,b,c){a=void 0===a||a===!0;var d=this.nextGroupId(),e=$(this.getGroupTemplate(d,1));return this.$el.append(e),this.model.root=new j(null,e),this.model.root.model=this.model,this.model.root.data=b,this.model.root.__.flags=$.extend({},this.settings.default_group_flags,c),this.trigger("afterAddGroup",this.model.root),this.model.root.condition=this.settings.default_condition,a&&this.addRule(this.model.root),this.model.root},g.prototype.addGroup=function(a,b,c,d){b=void 0===b||b===!0;var e=a.level+1,f=this.trigger("beforeAddGroup",a,b,e);if(f.isDefaultPrevented())return null;var g=this.nextGroupId(),h=$(this.getGroupTemplate(g,e)),i=a.addGroup(h);return i.data=c,i.__.flags=$.extend({},this.settings.default_group_flags,d),this.trigger("afterAddGroup",i),this.trigger("rulesChanged"),i.condition=this.settings.default_condition,b&&this.addRule(i),i},g.prototype.deleteGroup=function(a){if(a.isRoot())return!1;var b=this.trigger("beforeDeleteGroup",a);if(b.isDefaultPrevented())return!1;var c=!0;return a.each("reverse",function(a){c&=this.deleteRule(a)},function(a){c&=this.deleteGroup(a)},this),c&&(a.drop(),this.trigger("afterDeleteGroup"),this.trigger("rulesChanged")),c},g.prototype.updateGroupCondition=function(a,b){a.$el.find(">"+g.selectors.group_condition).each(function(){var b=$(this);b.prop("checked",b.val()===a.condition),b.parent().toggleClass("active",b.val()===a.condition)}),this.trigger("afterUpdateGroupCondition",a,b),this.trigger("rulesChanged")},g.prototype.refreshGroupsConditions=function(){!function a(b){(!b.flags||b.flags&&!b.flags.condition_readonly)&&b.$el.find(">"+g.selectors.group_condition).prop("disabled",b.rules.length<=1).parent().toggleClass("disabled",b.rules.length<=1),b.each(null,function(b){a(b)},this)}(this.model.root)},g.prototype.addRule=function(a,b,c){var d=this.trigger("beforeAddRule",a);if(d.isDefaultPrevented())return null;var e=this.nextRuleId(),f=$(this.getRuleTemplate(e)),g=a.addRule(f);return void 0!==b&&(g.data=b),g.__.flags=$.extend({},this.settings.default_rule_flags,c),this.trigger("afterAddRule",g),this.trigger("rulesChanged"),this.createRuleFilters(g),!this.settings.default_filter&&this.settings.display_empty_filter||(g.filter=this.change("getDefaultFilter",this.getFilterById(this.settings.default_filter||this.filters[0].id),g)),g},g.prototype.deleteRule=function(a){if(a.flags.no_delete)return!1;var b=this.trigger("beforeDeleteRule",a);return!b.isDefaultPrevented()&&(a.drop(),this.trigger("afterDeleteRule"),this.trigger("rulesChanged"),!0)},g.prototype.createRuleFilters=function(a){var b=this.change("getRuleFilters",this.filters,a),c=$(this.getRuleFilterSelect(a,b));a.$el.find(g.selectors.filter_container).html(c),this.trigger("afterCreateRuleFilters",a)},g.prototype.createRuleOperators=function(a){var b=a.$el.find(g.selectors.operator_container).empty();if(a.filter){var c=this.getOperators(a.filter),d=$(this.getRuleOperatorSelect(a,c));b.html(d),a.filter.default_operator?a.__.operator=this.getOperatorByType(a.filter.default_operator):a.__.operator=c[0],a.$el.find(g.selectors.rule_operator).val(a.operator.type),this.trigger("afterCreateRuleOperators",a,c)}},g.prototype.createRuleInput=function(a){var b=a.$el.find(g.selectors.value_container).empty();if(a.__.value=void 0,a.filter&&a.operator&&0!==a.operator.nb_inputs){for(var c=this,d=$(),e=a.filter,f=0;f0&&b.append(this.settings.inputs_separator),b.append(h),d=d.add(h)}b.show(),d.on("change "+(e.input_event||""),function(){this._updating_input||(a._updating_value=!0,a.value=c.getRuleInputValue(a),a._updating_value=!1)}),e.plugin&&d[e.plugin](e.plugin_config||{}),this.trigger("afterCreateRuleInput",a),void 0!==e.default_value?a.value=e.default_value:(a._updating_value=!0,a.value=c.getRuleInputValue(a),a._updating_value=!1)}},g.prototype.updateRuleFilter=function(a,b){this.createRuleOperators(a),this.createRuleInput(a),a.$el.find(g.selectors.rule_filter).val(a.filter?a.filter.id:"-1"),b&&a.filter&&b.id!==a.filter.id&&(a.data=void 0),this.trigger("afterUpdateRuleFilter",a,b),this.trigger("rulesChanged")},g.prototype.updateRuleOperator=function(a,b){var c=a.$el.find(g.selectors.value_container),d=a.value;a.operator&&0!==a.operator.nb_inputs?(c.show(),!c.is(":empty")&&b&&a.operator.nb_inputs===b.nb_inputs&&a.operator.optgroup===b.optgroup||this.createRuleInput(a)):(c.hide(),a.__.value=void 0),a.operator&&a.$el.find(g.selectors.rule_operator).val(a.operator.type),this.trigger("afterUpdateRuleOperator",a,b),this.trigger("rulesChanged"),this.updateRuleValue(a,d)},g.prototype.updateRuleValue=function(a,b){a._updating_value||this.setRuleInputValue(a,a.value),this.trigger("afterUpdateRuleValue",a,b),this.trigger("rulesChanged")},g.prototype.applyRuleFlags=function(a){var b=a.flags,c=g.selectors;b.filter_readonly&&a.$el.find(c.rule_filter).prop("disabled",!0),b.operator_readonly&&a.$el.find(c.rule_operator).prop("disabled",!0),b.value_readonly&&a.$el.find(c.rule_value).prop("disabled",!0),b.no_delete&&a.$el.find(c.delete_rule).remove(),this.trigger("afterApplyRuleFlags",a)},g.prototype.applyGroupFlags=function(a){var b=a.flags,c=g.selectors;b.condition_readonly&&a.$el.find(">"+c.group_condition).prop("disabled",!0).parent().addClass("readonly"),b.no_add_rule&&a.$el.find(c.add_rule).remove(),b.no_add_group&&a.$el.find(c.add_group).remove(),b.no_delete&&a.$el.find(c.delete_group).remove(),this.trigger("afterApplyGroupFlags",a)},g.prototype.clearErrors=function(a){a=a||this.model.root,a&&(a.error=null,a instanceof j&&a.each(function(a){a.error=null},function(a){this.clearErrors(a)},this))},g.prototype.updateError=function(a){if(this.settings.display_errors)if(null===a.error)a.$el.removeClass("has-error");else{var b=this.translate("errors",a.error[0]);b=h.fmt(b,a.error.slice(1)),b=this.change("displayError",b,a.error,a),a.$el.addClass("has-error").find(g.selectors.error_container).eq(0).attr("title",b)}},g.prototype.triggerValidationError=function(a,b,c){$.isArray(b)||(b=[b]);var d=this.trigger("validationError",a,b,c);d.isDefaultPrevented()||(a.error=b)},g.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},g.prototype.reset=function(){var a=this.trigger("beforeReset");a.isDefaultPrevented()||(this.status.group_id=1,this.status.rule_id=0,this.model.root.empty(),this.addRule(this.model.root),this.trigger("afterReset"),this.trigger("rulesChanged"))},g.prototype.clear=function(){var a=this.trigger("beforeClear");a.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"))},g.prototype.setOptions=function(a){$.each(a,function(a,b){g.modifiable_options.indexOf(a)!==-1&&(this.settings[a]=b)}.bind(this))},g.prototype.getModel=function(a){return a?a instanceof i?a:$(a).data("queryBuilderModel"):this.model.root},g.prototype.validate=function(a){a=$.extend({skip_empty:!1},a),this.clearErrors();var b=this,c=function d(c){var e=0,f=0;return c.each(function(c){if(c.filter||!a.skip_empty){if(!c.filter)return b.triggerValidationError(c,"no_filter",null),void f++;if(!c.operator)return b.triggerValidationError(c,"no_operator",null),void f++;if(0!==c.operator.nb_inputs){var d=b.validateValue(c,c.value);if(d!==!0)return b.triggerValidationError(c,d,c.value),void f++}e++}},function(a){var b=d(a);b===!0?e++:b===!1&&f++}),!(f>0)&&(0===e&&!c.isRoot()&&a.skip_empty?null:!!(0!==e||b.settings.allow_empty&&c.isRoot())||(b.triggerValidationError(c,"empty_group",null),!1))}(this.model.root);return this.change("validate",c)},g.prototype.getRules=function(a){a=$.extend({get_flags:!1,allow_invalid:!1,skip_empty:!1},a);var b=this.validate(a);if(!b&&!a.allow_invalid)return null;var c=this,d=function e(b){var d={condition:b.condition,rules:[]};if(b.data&&(d.data=$.extendext(!0,"replace",{},b.data)),a.get_flags){var f=c.getGroupFlags(b.flags,"all"===a.get_flags);$.isEmptyObject(f)||(d.flags=f)}return b.each(function(b){if(b.filter||!a.skip_empty){var e=null;b.operator&&0===b.operator.nb_inputs||(e=b.value);var f={id:b.filter?b.filter.id:null,field:b.filter?b.filter.field:null,type:b.filter?b.filter.type:null,input:b.filter?b.filter.input:null,operator:b.operator?b.operator.type:null,value:e};if((b.filter&&b.filter.data||b.data)&&(f.data=$.extendext(!0,"replace",{},b.filter.data,b.data)),a.get_flags){var g=c.getRuleFlags(b.flags,"all"===a.get_flags);$.isEmptyObject(g)||(f.flags=g)}d.rules.push(c.change("ruleToJson",f,b))}},function(b){var c=e(b);0===c.rules.length&&a.skip_empty||d.rules.push(c)},this),c.change("groupToJson",d,b)}(this.model.root);return d.valid=b,this.change("getRules",d)},g.prototype.setRules=function(a,b){b=$.extend({allow_invalid:!1},b),$.isArray(a)&&(a={condition:this.settings.default_condition,rules:a}),a&&a.rules&&(0!==a.rules.length||this.settings.allow_empty)||h.error("RulesParse","Incorrect data object passed"),this.clear(),this.setRoot(!1,a.data,this.parseGroupFlags(a)),this.applyGroupFlags(this.model.root),a=this.change("setRules",a,b);var c=this;!function d(a,e){null!==e&&(void 0===a.condition?a.condition=c.settings.default_condition:c.settings.conditions.indexOf(a.condition)==-1&&(h.error(!b.allow_invalid,"UndefinedCondition",'Invalid condition "{0}"',a.condition),a.condition=c.settings.default_condition),e.condition=a.condition,a.rules.forEach(function(a){var f;if(void 0!==a.rules)if(c.settings.allow_groups!==-1&&c.settings.allow_groups1){j=["operator_not_multiple",f.type,this.translate("operators",f.type)];break}switch(e.input){case"radio":if(void 0===b[k]||0===b[k].length){i.allow_empty_value||(j=["radio_empty"]);break}break;case"checkbox":if(void 0===b[k]||0===b[k].length){i.allow_empty_value||(j=["checkbox_empty"]);break}break;case"select":if(void 0===b[k]||0===b[k].length||e.placeholder&&b[k]==e.placeholder_value){i.allow_empty_value||(j=["select_empty"]);break}break;default:d=$.isArray(b[k])?b[k]:[b[k]];for(var l=0;lparseInt(i.max)){j=[this.getValidationMessage(i,"max","string_exceed_max_length"),i.max];break}if(i.format&&("string"==typeof i.format&&(i.format=new RegExp(i.format)),!i.format.test(d[l]))){j=[this.getValidationMessage(i,"format","string_invalid_format"),i.format];break}break;case"number":if(void 0===d[l]||0===d[l].length){i.allow_empty_value||(j=["number_nan"]);break}if(isNaN(d[l])){j=["number_nan"];break}if("integer"==e.type){if(parseInt(d[l])!=d[l]){j=["number_not_integer"];break}}else if(parseFloat(d[l])!=d[l]){j=["number_not_double"];break}if(void 0!==i.min&&d[l]parseFloat(i.max)){j=[this.getValidationMessage(i,"max","number_exceed_max"),i.max];break}if(void 0!==i.step&&"any"!==i.step){var m=(d[l]/i.step).toPrecision(14);if(parseInt(m)!=m){j=[this.getValidationMessage(i,"step","number_wrong_step"),i.step];break}}break;case"datetime":if(void 0===d[l]||0===d[l].length){i.allow_empty_value||(j=["datetime_empty"]);break}if(i.format){"moment"in window||h.error("MissingLibrary","MomentJS is required for Date/Time validation. Get it here http://momentjs.com");var n=moment(d[l],i.format);if(!n.isValid()){j=[this.getValidationMessage(i,"format","datetime_invalid"),i.format];break}if(i.min&&nmoment(i.max,i.format)){j=[this.getValidationMessage(i,"max","datetime_exceed_max"),i.max];break}}break;case"boolean":if(void 0===d[l]||0===d[l].length){i.allow_empty_value||(j=["boolean_not_valid"]);break}if(c=(""+d[l]).trim().toLowerCase(),"true"!==c&&"false"!==c&&"1"!==c&&"0"!==c&&1!==d[l]&&0!==d[l]){j=["boolean_not_valid"];break}}if(j!==!0)break}}if(j!==!0)break}if(("between"===a.operator.type||"not_between"===a.operator.type)&&2===b.length)switch(g.types[e.type]){case"number":b[0]>b[1]&&(j=["number_between_invalid",b[0],b[1]]);break;case"datetime":i.format&&("moment"in window||h.error("MissingLibrary","MomentJS is required for Date/Time validation. Get it here http://momentjs.com"),moment(b[0],i.format).isAfter(moment(b[1],i.format))&&(j=["datetime_between_invalid",b[0],b[1]]))}return j},g.prototype.nextGroupId=function(){return this.status.id+"_group_"+this.status.group_id++},g.prototype.nextRuleId=function(){return this.status.id+"_rule_"+this.status.rule_id++},g.prototype.getOperators=function(a){"string"==typeof a&&(a=this.getFilterById(a));for(var b=[],c=0,d=this.operators.length;c '+b+" "});break;case"select":g+='";break;case"textarea":g+='";break;case"number":l+=' "})}})},{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-xs",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){t.$el.find(i.rule_operator).removeClass("form-control").chosen(r)}),this.on("afterUpdateRuleFilter",function(e,t){t.$el.find(i.rule_filter).trigger("chosen:updated")}),this.on("afterUpdateRuleOperator",function(e,t){t.$el.find(i.rule_operator).trigger("chosen:updated")}),this.on("beforeDeleteRule",function(e,t){t.$el.find(i.rule_filter).chosen("destroy"),t.$el.find(i.rule_operator).chosen("destroy")})}),c.define("filter-description",function(o){"inline"===o.mode?this.on("afterUpdateRuleFilter afterUpdateRuleOperator",function(e,t){var r=t.$el.find("p.filter-description"),i=e.builder.getFilterDescription(t.filter,t);i?(0===r.length?(r=$('

    ')).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('"),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('"),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={left:e.value,operation:i.settings.default_condition,right:null}),e.value.not=!0)}),this.on("sqlGroupsDistinct.filter",function(e,t,r){r.not&&(e.value=!0)}),this.on("sqlToGroup.filter",function(e,t){e.value.not=!!t.not}),this.on("groupToMongo.filter",function(e,t){var r="$"+t.condition.toLowerCase();t.not&&e.value[r]&&(e.value={$nor:[e.value]})}),this.on("parseMongoNode.filter",function(e){var t=Object.keys(e.value);"$nor"==t[0]&&(e.value=e.value[t[0]][0],e.value.not=!0)}),this.on("mongoToGroup.filter",function(e,t){e.value.not=!!t.not})},{icon_unchecked:"glyphicon glyphicon-unchecked",icon_checked:"glyphicon glyphicon-check",disable_template:!1}),h.defineModelProperties(a,["not"]),c.selectors.group_not=c.selectors.group_header+" [data-not=group]",c.extend({updateGroupNot:function(e){var t=this.plugins["not-group"];e.$el.find(">"+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({allowForm: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 \ {{?}} \ - \ -
    \ -
      \ -
      \ -'; + \ +
      \ +
      \ +
      \ +'; QueryBuilder.templates.rule = '\ -
    • \ +
      \
      \
      \
    • '; +'; QueryBuilder.templates.filterSelect = '\ {{ var optgroup = null; }} \ @@ -2989,7 +3029,7 @@ QueryBuilder.templates.filterSelect = '\ \ {{?}} \ {{?}} \ - \ + \ {{~}} \ {{? optgroup !== null }}{{?}} \ '; @@ -3009,7 +3049,25 @@ QueryBuilder.templates.operatorSelect = '\ \ {{?}} \ {{?}} \ - \ + \ + {{~}} \ + {{? optgroup !== null }}{{?}} \ +'; + +QueryBuilder.templates.ruleValueSelect = '\ +{{ var optgroup = null; }} \ +'; @@ -3130,6 +3188,36 @@ QueryBuilder.prototype.getRuleOperatorSelect = function(rule, operators) { 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 @@ -3158,14 +3246,7 @@ QueryBuilder.prototype.getRuleInput = function(rule, value_id) { break; case 'select': - h += ''; + h = this.getRuleValueSelect(name, rule); break; case 'textarea': @@ -3227,10 +3308,11 @@ QueryBuilder.utils = Utils; * @callback Utils#OptionsIteratee * @param {string} key * @param {string} value + * @param {string} [optgroup] */ /** - * Iterates over radio/checkbox/selection options, it accept three formats + * Iterates over radio/checkbox/selection options, it accept four formats * * @example * // array of values @@ -3241,6 +3323,9 @@ QueryBuilder.utils = Utils; * @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 @@ -3249,12 +3334,18 @@ Utils.iterateOptions = function(options, tpl) { if (options) { if ($.isArray(options)) { options.forEach(function(entry) { - // array of one-element maps if ($.isPlainObject(entry)) { - $.each(entry, function(key, val) { - tpl(key, val); - return false; // break after first 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 { @@ -3316,19 +3407,32 @@ Utils.error = function() { * Changes the type of a value to int, float or bool * @param {*} value * @param {string} type - 'integer', 'double', 'boolean' or anything else (passthrough) - * @param {boolean} [boolAsInt=false] - return 0 or 1 for booleans * @returns {*} */ -Utils.changeType = function(value, type, boolAsInt) { +Utils.changeType = function(value, type) { + if (value === '' || value === undefined) { + return undefined; + } + switch (type) { // @formatter:off - case 'integer': return parseInt(value); - case 'double': return parseFloat(value); - case 'boolean': - var bool = value.trim().toLowerCase() === 'true' || value.trim() === '1' || value === 1; - return boolAsInt ? (bool ? 1 : 0) : bool; - default: return value; - // @formatter:on + 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 } }; @@ -3346,12 +3450,12 @@ Utils.escapeString = function(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 + case '\0': return '\\0'; + case '\n': return '\\n'; + case '\r': return '\\r'; + case '\b': return '\\b'; + default: return '\\' + s; + // @formatter:off } }) // uglify compliant @@ -4389,6 +4493,50 @@ QueryBuilder.extend(/** @lends module:plugins.ChangeFilters.prototype */ { }); +/** + * @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) { + 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 @@ -4414,7 +4562,7 @@ QueryBuilder.define('filter-description', function(options) { $p.appendTo(rule.$el); } else { - $p.show(); + $p.css('display', ''); } $p.html(' ' + description); @@ -4454,7 +4602,7 @@ QueryBuilder.define('filter-description', function(options) { }); } else { - $b.show(); + $b.css('display', ''); } $b.data('bs.popover').options.content = description; @@ -4488,7 +4636,7 @@ QueryBuilder.define('filter-description', function(options) { }); } else { - $b.show(); + $b.css('display', ''); } $b.data('description', description); @@ -4553,25 +4701,36 @@ QueryBuilder.define('invert', function(options) { }); // Modify templates - this.on('getGroupTemplate.filter', function(h, level) { - var $h = $(h.value); - $h.find(Selectors.condition_container).after(''); - h.value = $h.prop('outerHTML'); - }); - - if (options.display_rules_button && options.invert_rules) { - this.on('getRuleTemplate.filter', function(h) { + if (!options.disable_template) { + this.on('getGroupTemplate.filter', function(h) { var $h = $(h.value); - $h.find(Selectors.rule_actions).prepend(''); + $h.find(Selectors.condition_container).after( + '' + ); 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( + '' + ); + h.value = $h.prop('outerHTML'); + }); + } } }, { icon: 'glyphicon glyphicon-random', recursive: true, invert_rules: true, display_rules_button: false, - silent_fail: false + silent_fail: false, + disable_template: false }); QueryBuilder.defaults({ @@ -4812,7 +4971,6 @@ QueryBuilder.extend(/** @lends module:plugins.MongoDbSupport.prototype */ { else { var mdb = self.settings.mongoOperators[rule.operator]; var ope = self.getOperatorByType(rule.operator); - var values = []; if (mdb === undefined) { Utils.error('UndefinedMongoOperator', 'Unknown MongoDB operation for operator "{0}"', rule.operator); @@ -4822,10 +4980,6 @@ QueryBuilder.extend(/** @lends module:plugins.MongoDbSupport.prototype */ { if (!(rule.value instanceof Array)) { rule.value = [rule.value]; } - - rule.value.forEach(function(v) { - values.push(Utils.changeType(v, rule.type, false)); - }); } /** @@ -4839,7 +4993,7 @@ QueryBuilder.extend(/** @lends module:plugins.MongoDbSupport.prototype */ { var field = self.change('getMongoDBField', rule.field, rule); var ruleExpression = {}; - ruleExpression[field] = mdb.call(self, values); + ruleExpression[field] = mdb.call(self, rule.value); /** * Modifies the MongoDB expression generated for a rul @@ -4851,7 +5005,7 @@ QueryBuilder.extend(/** @lends module:plugins.MongoDbSupport.prototype */ { * @param {function} valueWrapper - function that takes the value and adds the operator * @returns {object} */ - parts.push(self.change('ruleToMongo', ruleExpression, rule, values, mdb)); + parts.push(self.change('ruleToMongo', ruleExpression, rule, rule.value, mdb)); } }); @@ -5118,15 +5272,17 @@ QueryBuilder.define('not-group', function(options) { }); // Modify templates - this.on('getGroupTemplate.filter', function(h, level) { - var $h = $(h.value); - $h.find(QueryBuilder.selectors.condition_container).prepend( - '' - ); - h.value = $h.prop('outerHTML'); - }); + if (!options.disable_template) { + this.on('getGroupTemplate.filter', function(h) { + var $h = $(h.value); + $h.find(QueryBuilder.selectors.condition_container).prepend( + '' + ); + h.value = $h.prop('outerHTML'); + }); + } // Export "not" to JSON this.on('groupToJson.filter', function(e, group) { @@ -5149,10 +5305,27 @@ QueryBuilder.define('not-group', function(options) { 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 = { + left: e.value, + operation: self.settings.default_condition, + right: null + }; + } + e.value.not = true; } }); + // Request to create sub-group if the "not" flag is set + this.on('sqlGroupsDistinct.filter', function(e, group, data) { + if (data.not) { + e.value = true; + } + }); + // Read "not" from parsed SQL this.on('sqlToGroup.filter', function(e, data) { e.value.not = !!data.not; @@ -5182,7 +5355,8 @@ QueryBuilder.define('not-group', function(options) { }); }, { icon_unchecked: 'glyphicon glyphicon-unchecked', - icon_checked: 'glyphicon glyphicon-check' + icon_checked: 'glyphicon glyphicon-check', + disable_template: false }); /** @@ -5251,6 +5425,7 @@ QueryBuilder.define('sortable', function(options) { var placeholder; var ghost; var src; + var moved; // Init drag and drop this.on('afterAddRule afterAddGroup', function(e, node) { @@ -5271,9 +5446,11 @@ QueryBuilder.define('sortable', function(options) { // Configure drag if (!node.flags.no_sortable) { interact(node.$el[0]) - .allowFrom(QueryBuilder.selectors.drag_handle) .draggable({ + allowForm: QueryBuilder.selectors.drag_handle, onstart: function(event) { + moved = false; + // get model of dragged element src = self.getModel(event.target); @@ -5297,7 +5474,13 @@ QueryBuilder.define('sortable', function(options) { ghost[0].style.top = event.clientY - 15 + 'px'; ghost[0].style.left = event.clientX - 15 + 'px'; }, - onend: function() { + 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; @@ -5307,7 +5490,7 @@ QueryBuilder.define('sortable', function(options) { placeholder = undefined; // show element - src.$el.show(); + src.$el.css('display', ''); /** * After a node has been moved with {@link module:plugins.Sortable} @@ -5331,7 +5514,9 @@ QueryBuilder.define('sortable', function(options) { moveSortableToTarget(placeholder, $(event.target), self); }, ondrop: function(event) { - moveSortableToTarget(src, $(event.target), self); + if (!moved) { + moveSortableToTarget(src, $(event.target), self); + } } }); @@ -5344,7 +5529,9 @@ QueryBuilder.define('sortable', function(options) { moveSortableToTarget(placeholder, $(event.target), self); }, ondrop: function(event) { - moveSortableToTarget(src, $(event.target), self); + if (!moved) { + moveSortableToTarget(src, $(event.target), self); + } } }); } @@ -5370,23 +5557,26 @@ QueryBuilder.define('sortable', function(options) { }); // Modify templates - this.on('getGroupTemplate.filter', function(h, level) { - if (level > 1) { + 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.condition_container).after('
      '); + $h.find(QueryBuilder.selectors.rule_header).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' + icon: 'glyphicon glyphicon-sort', + disable_template: false }); QueryBuilder.selectors.rule_and_group_containers = QueryBuilder.selectors.rule_container + ', ' + QueryBuilder.selectors.group_container; @@ -5707,7 +5897,9 @@ QueryBuilder.extend(/** @lends module:plugins.SqlSupport.prototype */ { nl = !!nl ? '\n' : ' '; var boolean_as_integer = this.getPluginOptions('sql-support', 'boolean_as_integer'); - if (stmt === true) stmt = 'question_mark'; + if (stmt === true) { + stmt = 'question_mark'; + } if (typeof stmt == 'string') { var config = getStmtConfig(stmt); stmt = this.settings.sqlStatements[config[1]](config[2]); @@ -5752,10 +5944,10 @@ QueryBuilder.extend(/** @lends module:plugins.SqlSupport.prototype */ { value += sql.sep; } - if (rule.type == 'integer' || rule.type == 'double' || rule.type == 'boolean') { - v = Utils.changeType(v, rule.type, boolean_as_integer); + if (rule.type == 'boolean' && boolean_as_integer) { + v = v ? 1 : 0; } - else if (!stmt) { + else if (!stmt && rule.type !== 'integer' && rule.type !== 'double' && rule.type !== 'boolean') { v = Utils.escapeString(v); } @@ -5906,6 +6098,10 @@ QueryBuilder.extend(/** @lends module:plugins.SqlSupport.prototype */ { 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); @@ -5929,7 +6125,19 @@ QueryBuilder.extend(/** @lends module:plugins.SqlSupport.prototype */ { // 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 - if (i > 0 && curr.condition != data.operation.toUpperCase()) { + + /** + * 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 - try by default if the group condition is different + * @param {object} group + * @param {object} AST + * @returns {boolean} + */ + var createGroup = self.change('sqlGroupsDistinct', i > 0 && curr.condition != data.operation.toUpperCase(), curr, data); + + if (createGroup) { /** * Modifies the group generated from the SQL expression (this is called before the group is filled with rules) * @event changer:sqlToGroup @@ -6206,7 +6414,7 @@ QueryBuilder.extend(/** @lends module:plugins.UniqueFilter.prototype */ { /*! - * jQuery QueryBuilder 2.4.5 + * jQuery QueryBuilder 2.5.0 * Locale: English (en) * Author: Damien "Mistic" Sorel, http://www.strangeplanet.fr * Licensed under MIT (http://opensource.org/licenses/MIT) @@ -6266,7 +6474,7 @@ QueryBuilder.regional['en'] = { "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} isgreater than {1}", + "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" }, diff --git a/dist/js/query-builder.standalone.min.js b/dist/js/query-builder.standalone.min.js index b78c4632..284897c4 100644 --- a/dist/js/query-builder.standalone.min.js +++ b/dist/js/query-builder.standalone.min.js @@ -1,8 +1,7 @@ /*! - * jQuery QueryBuilder 2.4.5 - * Copyright 2014-2017 Damien "Mistic" Sorel (http://www.strangeplanet.fr) + * jQuery QueryBuilder 2.5.0 + * Copyright 2014-2018 Damien "Mistic" Sorel (http://www.strangeplanet.fr) * Licensed under MIT (http://opensource.org/licenses/MIT) */ -!function(a,b){"function"==typeof define&&define.amd?define("jQuery.extendext",["jquery"],b):"object"==typeof module&&module.exports?module.exports=b(require("jquery")):b(a.jQuery)}(this,function($){"use strict";$.extendext=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1,k="default";for("boolean"==typeof g&&(j=g,g=arguments[h++]||{}),"string"==typeof g&&(k=g.toLowerCase(),"concat"!==k&&"replace"!==k&&"extend"!==k&&(k="default"),g=arguments[h++]||{}),"object"==typeof g||$.isFunction(g)||(g={}),h===i&&(g=this,h--);h":">",'"':""","'":"'","/":"/"},c=a?/[&<>"'\/]/g:/&(?!#?\w+;)|<|>|"|'|\//g;return function(a){return a?a.toString().replace(c,function(a){return b[a]||a}):""}},c=function(){return this||(0,eval)("this")}(),"undefined"!=typeof module&&module.exports?module.exports=d:"function"==typeof define&&define.amd?define("doT",function(){return d}):c.doT=d;var e={append:{start:"'+(",end:")+'",startencode:"'+encodeHTML("},split:{start:"';out+=(",end:");out+='",startencode:"';out+=encodeHTML("}},f=/$^/;d.template=function(g,h,i){h=h||d.templateSettings;var j,k,l=h.append?e.append:e.split,m=0,n=h.use||h.define?a(h,g,i||{}):g;n=("var out='"+(h.strip?n.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g," ").replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,""):n).replace(/'|\\/g,"\\$&").replace(h.interpolate||f,function(a,c){return l.start+b(c)+l.end}).replace(h.encode||f,function(a,c){return j=!0,l.startencode+b(c)+l.end}).replace(h.conditional||f,function(a,c,d){return c?d?"';}else if("+b(d)+"){out+='":"';}else{out+='":d?"';if("+b(d)+"){out+='":"';}out+='"}).replace(h.iterate||f,function(a,c,d,e){return c?(m+=1,k=e||"i"+m,c=b(c),"';var arr"+m+"="+c+";if(arr"+m+"){var "+d+","+k+"=-1,l"+m+"=arr"+m+".length-1;while("+k+".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]"},g.templates={},g.regional={},g.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"]}},g.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},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:"glyphicon glyphicon-plus-sign",add_rule:"glyphicon glyphicon-plus",remove_group:"glyphicon glyphicon-remove",remove_rule:"glyphicon glyphicon-remove",error:"glyphicon glyphicon-warning-sign"}},g.plugins={},g.defaults=function(a){return"object"!=typeof a?"string"==typeof a?"object"==typeof g.DEFAULTS[a]?$.extend(!0,{},g.DEFAULTS[a]):g.DEFAULTS[a]:$.extend(!0,{},g.DEFAULTS):void $.extendext(!0,"replace",g.DEFAULTS,a)},g.define=function(a,b,c){g.plugins[a]={fct:b,def:c||{}}},g.extend=function(a){$.extend(g.prototype,a)},g.prototype.initPlugins=function(){if(this.plugins){if($.isArray(this.plugins)){var a={};this.plugins.forEach(function(b){a[b]=null}),this.plugins=a}Object.keys(this.plugins).forEach(function(a){a in g.plugins?(this.plugins[a]=$.extend(!0,{},g.plugins[a].def,this.plugins[a]||{}),g.plugins[a].fct.call(this,this.plugins[a])):h.error("Config",'Unable to find plugin "{0}"',a)},this)}},g.prototype.getPluginOptions=function(a,b){var c;return this.plugins&&this.plugins[a]?c=this.plugins[a]:g.plugins[a]&&(c=g.plugins[a].def),c?b?c[b]:c:void h.error("Config",'Unable to find plugin "{0}"',a)},g.prototype.init=function(a){this.trigger("afterInit"),a?(this.setRules(a),delete this.settings.rules):this.setRoot(!0)},g.prototype.checkFilters=function(a){var b=[];if(a&&0!==a.length||h.error("Config","Missing filters list"),a.forEach(function(a,c){switch(a.id||h.error("Config","Missing filter {0} id",c),b.indexOf(a.id)!=-1&&h.error("Config",'Filter "{0}" already defined',a.id),b.push(a.id),a.type?g.types[a.type]||h.error("Config",'Invalid type "{0}"',a.type):a.type="string",a.input?"function"!=typeof a.input&&g.inputs.indexOf(a.input)==-1&&h.error("Config",'Invalid input "{0}"',a.input):a.input="number"===g.types[a.type]?"number":"text",a.operators&&a.operators.forEach(function(a){"string"!=typeof a&&h.error("Config","Filter operators must be global operators types (string)")}),a.field||(a.field=a.id),a.label||(a.label=a.field),a.optgroup?(this.status.has_optgroup=!0,this.settings.optgroups[a.optgroup]||(this.settings.optgroups[a.optgroup]=a.optgroup)):a.optgroup=null,a.input){case"radio":case"checkbox":(!a.values||a.values.length<1)&&h.error("Config",'Missing filter "{0}" values',a.id);break;case"select":a.placeholder&&(void 0===a.placeholder_value&&(a.placeholder_value=-1),h.iterateOptions(a.values,function(b){b==a.placeholder_value&&h.error("Config",'Placeholder of filter "{0}" overlaps with one of its values',a.id)}))}},this),this.settings.sort_filters)if("function"==typeof this.settings.sort_filters)a.sort(this.settings.sort_filters);else{var c=this;a.sort(function(a,b){return c.translate(a.label).localeCompare(c.translate(b.label))})}return this.status.has_optgroup&&(a=h.groupSort(a,"optgroup")),a},g.prototype.checkOperators=function(a){var b=[];return a.forEach(function(c,d){"string"==typeof c?(g.OPERATORS[c]||h.error("Config",'Unknown operator "{0}"',c),a[d]=c=$.extendext(!0,"replace",{},g.OPERATORS[c])):(c.type||h.error("Config",'Missing "type" for operator {0}',d),g.OPERATORS[c.type]&&(a[d]=c=$.extendext(!0,"replace",{},g.OPERATORS[c.type],c)),void 0!==c.nb_inputs&&void 0!==c.apply_to||h.error("Config",'Missing "nb_inputs" and/or "apply_to" for operator "{0}"',c.type)),b.indexOf(c.type)!=-1&&h.error("Config",'Operator "{0}" already defined',c.type),b.push(c.type),c.optgroup?(this.status.has_operator_optgroup=!0,this.settings.optgroups[c.optgroup]||(this.settings.optgroups[c.optgroup]=c.optgroup)):c.optgroup=null},this),this.status.has_operator_optgroup&&(a=h.groupSort(a,"optgroup")),a},g.prototype.bindEvents=function(){var a=this,b=g.selectors;this.$el.on("change.queryBuilder",b.group_condition,function(){if($(this).is(":checked")){var c=$(this).closest(b.group_container);a.getModel(c).condition=$(this).val()}}),this.$el.on("change.queryBuilder",b.rule_filter,function(){var c=$(this).closest(b.rule_container);a.getModel(c).filter=a.getFilterById($(this).val())}),this.$el.on("change.queryBuilder",b.rule_operator,function(){var c=$(this).closest(b.rule_container);a.getModel(c).operator=a.getOperatorByType($(this).val())}),this.$el.on("click.queryBuilder",b.add_rule,function(){var c=$(this).closest(b.group_container);a.addRule(a.getModel(c))}),this.$el.on("click.queryBuilder",b.delete_rule,function(){var c=$(this).closest(b.rule_container);a.deleteRule(a.getModel(c))}),0!==this.settings.allow_groups&&(this.$el.on("click.queryBuilder",b.add_group,function(){var c=$(this).closest(b.group_container);a.addGroup(a.getModel(c))}),this.$el.on("click.queryBuilder",b.delete_group,function(){var c=$(this).closest(b.group_container);a.deleteGroup(a.getModel(c))})),this.model.on({drop:function(b,c){c.$el.remove(),a.refreshGroupsConditions()},add:function(b,c,d,e){0===e?d.$el.prependTo(c.$el.find(">"+g.selectors.rules_list)):d.$el.insertAfter(c.rules[e-1].$el),a.refreshGroupsConditions()},move:function(b,c,d,e){c.$el.detach(),0===e?c.$el.prependTo(d.$el.find(">"+g.selectors.rules_list)):c.$el.insertAfter(d.rules[e-1].$el),a.refreshGroupsConditions()},update:function(b,c,d,e,f){if(c instanceof k)switch(d){case"error":a.updateError(c);break;case"flags":a.applyRuleFlags(c);break;case"filter":a.updateRuleFilter(c,f);break;case"operator":a.updateRuleOperator(c,f);break;case"value":a.updateRuleValue(c,f)}else switch(d){case"error":a.updateError(c);break;case"flags":a.applyGroupFlags(c);break;case"condition":a.updateGroupCondition(c,f)}}})},g.prototype.setRoot=function(a,b,c){a=void 0===a||a===!0;var d=this.nextGroupId(),e=$(this.getGroupTemplate(d,1));return this.$el.append(e),this.model.root=new j(null,e),this.model.root.model=this.model,this.model.root.data=b,this.model.root.__.flags=$.extend({},this.settings.default_group_flags,c),this.trigger("afterAddGroup",this.model.root),this.model.root.condition=this.settings.default_condition,a&&this.addRule(this.model.root),this.model.root},g.prototype.addGroup=function(a,b,c,d){b=void 0===b||b===!0;var e=a.level+1,f=this.trigger("beforeAddGroup",a,b,e);if(f.isDefaultPrevented())return null;var g=this.nextGroupId(),h=$(this.getGroupTemplate(g,e)),i=a.addGroup(h);return i.data=c,i.__.flags=$.extend({},this.settings.default_group_flags,d),this.trigger("afterAddGroup",i),this.trigger("rulesChanged"),i.condition=this.settings.default_condition,b&&this.addRule(i),i},g.prototype.deleteGroup=function(a){if(a.isRoot())return!1;var b=this.trigger("beforeDeleteGroup",a);if(b.isDefaultPrevented())return!1;var c=!0;return a.each("reverse",function(a){c&=this.deleteRule(a)},function(a){c&=this.deleteGroup(a)},this),c&&(a.drop(),this.trigger("afterDeleteGroup"),this.trigger("rulesChanged")),c},g.prototype.updateGroupCondition=function(a,b){a.$el.find(">"+g.selectors.group_condition).each(function(){var b=$(this);b.prop("checked",b.val()===a.condition),b.parent().toggleClass("active",b.val()===a.condition)}),this.trigger("afterUpdateGroupCondition",a,b),this.trigger("rulesChanged")},g.prototype.refreshGroupsConditions=function(){!function a(b){(!b.flags||b.flags&&!b.flags.condition_readonly)&&b.$el.find(">"+g.selectors.group_condition).prop("disabled",b.rules.length<=1).parent().toggleClass("disabled",b.rules.length<=1),b.each(null,function(b){a(b)},this)}(this.model.root)},g.prototype.addRule=function(a,b,c){var d=this.trigger("beforeAddRule",a);if(d.isDefaultPrevented())return null;var e=this.nextRuleId(),f=$(this.getRuleTemplate(e)),g=a.addRule(f);return void 0!==b&&(g.data=b),g.__.flags=$.extend({},this.settings.default_rule_flags,c),this.trigger("afterAddRule",g),this.trigger("rulesChanged"),this.createRuleFilters(g),!this.settings.default_filter&&this.settings.display_empty_filter||(g.filter=this.change("getDefaultFilter",this.getFilterById(this.settings.default_filter||this.filters[0].id),g)),g},g.prototype.deleteRule=function(a){if(a.flags.no_delete)return!1;var b=this.trigger("beforeDeleteRule",a);return!b.isDefaultPrevented()&&(a.drop(),this.trigger("afterDeleteRule"),this.trigger("rulesChanged"),!0)},g.prototype.createRuleFilters=function(a){var b=this.change("getRuleFilters",this.filters,a),c=$(this.getRuleFilterSelect(a,b));a.$el.find(g.selectors.filter_container).html(c),this.trigger("afterCreateRuleFilters",a)},g.prototype.createRuleOperators=function(a){var b=a.$el.find(g.selectors.operator_container).empty();if(a.filter){var c=this.getOperators(a.filter),d=$(this.getRuleOperatorSelect(a,c));b.html(d),a.filter.default_operator?a.__.operator=this.getOperatorByType(a.filter.default_operator):a.__.operator=c[0],a.$el.find(g.selectors.rule_operator).val(a.operator.type),this.trigger("afterCreateRuleOperators",a,c)}},g.prototype.createRuleInput=function(a){var b=a.$el.find(g.selectors.value_container).empty();if(a.__.value=void 0,a.filter&&a.operator&&0!==a.operator.nb_inputs){for(var c=this,d=$(),e=a.filter,f=0;f0&&b.append(this.settings.inputs_separator),b.append(h),d=d.add(h)}b.show(),d.on("change "+(e.input_event||""),function(){this._updating_input||(a._updating_value=!0,a.value=c.getRuleInputValue(a),a._updating_value=!1)}),e.plugin&&d[e.plugin](e.plugin_config||{}),this.trigger("afterCreateRuleInput",a),void 0!==e.default_value?a.value=e.default_value:(a._updating_value=!0,a.value=c.getRuleInputValue(a),a._updating_value=!1)}},g.prototype.updateRuleFilter=function(a,b){this.createRuleOperators(a),this.createRuleInput(a),a.$el.find(g.selectors.rule_filter).val(a.filter?a.filter.id:"-1"),b&&a.filter&&b.id!==a.filter.id&&(a.data=void 0),this.trigger("afterUpdateRuleFilter",a,b),this.trigger("rulesChanged")},g.prototype.updateRuleOperator=function(a,b){var c=a.$el.find(g.selectors.value_container),d=a.value;a.operator&&0!==a.operator.nb_inputs?(c.show(),!c.is(":empty")&&b&&a.operator.nb_inputs===b.nb_inputs&&a.operator.optgroup===b.optgroup||this.createRuleInput(a)):(c.hide(),a.__.value=void 0),a.operator&&a.$el.find(g.selectors.rule_operator).val(a.operator.type),this.trigger("afterUpdateRuleOperator",a,b),this.trigger("rulesChanged"),this.updateRuleValue(a,d)},g.prototype.updateRuleValue=function(a,b){a._updating_value||this.setRuleInputValue(a,a.value),this.trigger("afterUpdateRuleValue",a,b),this.trigger("rulesChanged")},g.prototype.applyRuleFlags=function(a){var b=a.flags,c=g.selectors;b.filter_readonly&&a.$el.find(c.rule_filter).prop("disabled",!0),b.operator_readonly&&a.$el.find(c.rule_operator).prop("disabled",!0),b.value_readonly&&a.$el.find(c.rule_value).prop("disabled",!0),b.no_delete&&a.$el.find(c.delete_rule).remove(),this.trigger("afterApplyRuleFlags",a)},g.prototype.applyGroupFlags=function(a){var b=a.flags,c=g.selectors;b.condition_readonly&&a.$el.find(">"+c.group_condition).prop("disabled",!0).parent().addClass("readonly"),b.no_add_rule&&a.$el.find(c.add_rule).remove(),b.no_add_group&&a.$el.find(c.add_group).remove(),b.no_delete&&a.$el.find(c.delete_group).remove(),this.trigger("afterApplyGroupFlags",a)},g.prototype.clearErrors=function(a){a=a||this.model.root,a&&(a.error=null,a instanceof j&&a.each(function(a){a.error=null},function(a){this.clearErrors(a)},this))},g.prototype.updateError=function(a){if(this.settings.display_errors)if(null===a.error)a.$el.removeClass("has-error");else{var b=this.translate("errors",a.error[0]);b=h.fmt(b,a.error.slice(1)),b=this.change("displayError",b,a.error,a),a.$el.addClass("has-error").find(g.selectors.error_container).eq(0).attr("title",b)}},g.prototype.triggerValidationError=function(a,b,c){$.isArray(b)||(b=[b]);var d=this.trigger("validationError",a,b,c);d.isDefaultPrevented()||(a.error=b)},g.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},g.prototype.reset=function(){var a=this.trigger("beforeReset");a.isDefaultPrevented()||(this.status.group_id=1,this.status.rule_id=0,this.model.root.empty(),this.addRule(this.model.root),this.trigger("afterReset"),this.trigger("rulesChanged"))},g.prototype.clear=function(){var a=this.trigger("beforeClear");a.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"))},g.prototype.setOptions=function(a){$.each(a,function(a,b){g.modifiable_options.indexOf(a)!==-1&&(this.settings[a]=b)}.bind(this))},g.prototype.getModel=function(a){return a?a instanceof i?a:$(a).data("queryBuilderModel"):this.model.root},g.prototype.validate=function(a){a=$.extend({skip_empty:!1},a),this.clearErrors();var b=this,c=function d(c){var e=0,f=0;return c.each(function(c){if(c.filter||!a.skip_empty){if(!c.filter)return b.triggerValidationError(c,"no_filter",null),void f++;if(!c.operator)return b.triggerValidationError(c,"no_operator",null),void f++;if(0!==c.operator.nb_inputs){var d=b.validateValue(c,c.value);if(d!==!0)return b.triggerValidationError(c,d,c.value),void f++}e++}},function(a){var b=d(a);b===!0?e++:b===!1&&f++}),!(f>0)&&(0===e&&!c.isRoot()&&a.skip_empty?null:!!(0!==e||b.settings.allow_empty&&c.isRoot())||(b.triggerValidationError(c,"empty_group",null),!1))}(this.model.root);return this.change("validate",c)},g.prototype.getRules=function(a){a=$.extend({get_flags:!1,allow_invalid:!1,skip_empty:!1},a);var b=this.validate(a);if(!b&&!a.allow_invalid)return null;var c=this,d=function e(b){var d={condition:b.condition,rules:[]};if(b.data&&(d.data=$.extendext(!0,"replace",{},b.data)),a.get_flags){var f=c.getGroupFlags(b.flags,"all"===a.get_flags);$.isEmptyObject(f)||(d.flags=f)}return b.each(function(b){if(b.filter||!a.skip_empty){var e=null;b.operator&&0===b.operator.nb_inputs||(e=b.value);var f={id:b.filter?b.filter.id:null,field:b.filter?b.filter.field:null,type:b.filter?b.filter.type:null,input:b.filter?b.filter.input:null,operator:b.operator?b.operator.type:null,value:e};if((b.filter&&b.filter.data||b.data)&&(f.data=$.extendext(!0,"replace",{},b.filter.data,b.data)),a.get_flags){var g=c.getRuleFlags(b.flags,"all"===a.get_flags);$.isEmptyObject(g)||(f.flags=g)}d.rules.push(c.change("ruleToJson",f,b))}},function(b){var c=e(b);0===c.rules.length&&a.skip_empty||d.rules.push(c)},this),c.change("groupToJson",d,b)}(this.model.root);return d.valid=b,this.change("getRules",d)},g.prototype.setRules=function(a,b){b=$.extend({allow_invalid:!1},b),$.isArray(a)&&(a={condition:this.settings.default_condition,rules:a}),a&&a.rules&&(0!==a.rules.length||this.settings.allow_empty)||h.error("RulesParse","Incorrect data object passed"),this.clear(),this.setRoot(!1,a.data,this.parseGroupFlags(a)),this.applyGroupFlags(this.model.root),a=this.change("setRules",a,b);var c=this;!function d(a,e){null!==e&&(void 0===a.condition?a.condition=c.settings.default_condition:c.settings.conditions.indexOf(a.condition)==-1&&(h.error(!b.allow_invalid,"UndefinedCondition",'Invalid condition "{0}"',a.condition),a.condition=c.settings.default_condition),e.condition=a.condition,a.rules.forEach(function(a){var f;if(void 0!==a.rules)if(c.settings.allow_groups!==-1&&c.settings.allow_groups1){j=["operator_not_multiple",f.type,this.translate("operators",f.type)];break}switch(e.input){case"radio":if(void 0===b[k]||0===b[k].length){i.allow_empty_value||(j=["radio_empty"]);break}break;case"checkbox":if(void 0===b[k]||0===b[k].length){i.allow_empty_value||(j=["checkbox_empty"]);break}break;case"select":if(void 0===b[k]||0===b[k].length||e.placeholder&&b[k]==e.placeholder_value){i.allow_empty_value||(j=["select_empty"]);break}break;default:d=$.isArray(b[k])?b[k]:[b[k]];for(var l=0;lparseInt(i.max)){j=[this.getValidationMessage(i,"max","string_exceed_max_length"),i.max];break}if(i.format&&("string"==typeof i.format&&(i.format=new RegExp(i.format)),!i.format.test(d[l]))){j=[this.getValidationMessage(i,"format","string_invalid_format"),i.format];break}break;case"number":if(void 0===d[l]||0===d[l].length){i.allow_empty_value||(j=["number_nan"]);break}if(isNaN(d[l])){j=["number_nan"];break}if("integer"==e.type){if(parseInt(d[l])!=d[l]){j=["number_not_integer"];break}}else if(parseFloat(d[l])!=d[l]){j=["number_not_double"];break}if(void 0!==i.min&&d[l]parseFloat(i.max)){j=[this.getValidationMessage(i,"max","number_exceed_max"),i.max];break}if(void 0!==i.step&&"any"!==i.step){var m=(d[l]/i.step).toPrecision(14);if(parseInt(m)!=m){j=[this.getValidationMessage(i,"step","number_wrong_step"),i.step];break}}break;case"datetime":if(void 0===d[l]||0===d[l].length){i.allow_empty_value||(j=["datetime_empty"]);break}if(i.format){"moment"in window||h.error("MissingLibrary","MomentJS is required for Date/Time validation. Get it here http://momentjs.com");var n=moment(d[l],i.format);if(!n.isValid()){j=[this.getValidationMessage(i,"format","datetime_invalid"),i.format];break}if(i.min&&nmoment(i.max,i.format)){j=[this.getValidationMessage(i,"max","datetime_exceed_max"),i.max];break}}break;case"boolean":if(void 0===d[l]||0===d[l].length){i.allow_empty_value||(j=["boolean_not_valid"]);break}if(c=(""+d[l]).trim().toLowerCase(),"true"!==c&&"false"!==c&&"1"!==c&&"0"!==c&&1!==d[l]&&0!==d[l]){j=["boolean_not_valid"];break}}if(j!==!0)break}}if(j!==!0)break}if(("between"===a.operator.type||"not_between"===a.operator.type)&&2===b.length)switch(g.types[e.type]){case"number":b[0]>b[1]&&(j=["number_between_invalid",b[0],b[1]]);break;case"datetime":i.format&&("moment"in window||h.error("MissingLibrary","MomentJS is required for Date/Time validation. Get it here http://momentjs.com"),moment(b[0],i.format).isAfter(moment(b[1],i.format))&&(j=["datetime_between_invalid",b[0],b[1]]))}return j},g.prototype.nextGroupId=function(){return this.status.id+"_group_"+this.status.group_id++},g.prototype.nextRuleId=function(){return this.status.id+"_rule_"+this.status.rule_id++},g.prototype.getOperators=function(a){"string"==typeof a&&(a=this.getFilterById(a));for(var b=[],c=0,d=this.operators.length;c '+b+" "});break;case"select":g+='";break;case"textarea":g+='";break;case"number":l+=' "})}})},{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-xs",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){t.$el.find(i.rule_operator).removeClass("form-control").chosen(r)}),this.on("afterUpdateRuleFilter",function(e,t){t.$el.find(i.rule_filter).trigger("chosen:updated")}),this.on("afterUpdateRuleOperator",function(e,t){t.$el.find(i.rule_operator).trigger("chosen:updated")}),this.on("beforeDeleteRule",function(e,t){t.$el.find(i.rule_filter).chosen("destroy"),t.$el.find(i.rule_operator).chosen("destroy")})}),c.define("filter-description",function(n){"inline"===n.mode?this.on("afterUpdateRuleFilter afterUpdateRuleOperator",function(e,t){var r=t.$el.find("p.filter-description"),i=e.builder.getFilterDescription(t.filter,t);i?(0===r.length?(r=$('

      ')).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('"),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('"),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={left:e.value,operation:i.settings.default_condition,right:null}),e.value.not=!0)}),this.on("sqlGroupsDistinct.filter",function(e,t,r){r.not&&(e.value=!0)}),this.on("sqlToGroup.filter",function(e,t){e.value.not=!!t.not}),this.on("groupToMongo.filter",function(e,t){var r="$"+t.condition.toLowerCase();t.not&&e.value[r]&&(e.value={$nor:[e.value]})}),this.on("parseMongoNode.filter",function(e){var t=Object.keys(e.value);"$nor"==t[0]&&(e.value=e.value[t[0]][0],e.value.not=!0)}),this.on("mongoToGroup.filter",function(e,t){e.value.not=!!t.not})},{icon_unchecked:"glyphicon glyphicon-unchecked",icon_checked:"glyphicon glyphicon-check",disable_template:!1}),h.defineModelProperties(a,["not"]),c.selectors.group_not=c.selectors.group_header+" [data-not=group]",c.extend({updateGroupNot:function(e){var t=this.plugins["not-group"];e.$el.find(">"+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({allowForm: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)||0jQuery QueryBuilder Example - - - - - + + + + + + - +