diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..7715ae28
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,18 @@
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 4
+trim_trailing_whitespace = true
+
+[*.json]
+indent_size = 2
+insert_final_newline = false
+
+[*.scss]
+indent_size = 2
+
+[*.html]
+indent_size = 2
diff --git a/CONTRIBUTING.md b/.github/CONTRIBUTING.md
similarity index 57%
rename from CONTRIBUTING.md
rename to .github/CONTRIBUTING.md
index 94bbd395..be3320fd 100644
--- a/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -1,24 +1,21 @@
-# Asking for help and features
-Though I am really happy to provide help, I am not your mom nor your instructor. Any request without enough detail and any bug report without a code example (live example is preferred) won't get any answer.
+# Guidelines for contributing
-Be exhaustive, describe your needs, show what you tried, it's the best way to get a rapid answer/bug fix.
+## Work on `dev`
+Any merge request should be created from and issued to the `dev` branch.
-# How to contribute
+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.
-Check the doc about [creating plugins](http://mistic100.github.io/jQuery-QueryBuilder/dev/plugins.html).
+Check the doc about [creating plugins](http://querybuilder.js.org/dev/plugins.html) and [use events](http://querybuilder.js.org/dev/events.html).
I reserve the right to refuse any plugin I think is not useful for many people. Particularly, only import/export plugins for mainstream data storages will be integrated in the main repository. Others should be in a separated repository. But it's totally possible to add a link to your repository in the documentation.
## Unit tests
Any big feature must have it's own QUnit tests suite. Of course existing tests must still pass after changes.
-I won't merge any branch not passing the TravisCI build (this include JShint compliance).
-
-## dist files
-Keep it simple, don't commit any files in the `dist` directory, I build these files only before a release.
+I won't merge any branch not passing the TravisCI build, including JShint/JSCS/SCSSlint compliance.
## Translations
Source language files are plain JSON files which will be converted to executable JS files by the build task. The `__locale` key must be filled with the international name of the language + 2-chars code and the `__author` key can be used to give information about the translator.
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 00000000..7a8c011b
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,6 @@
+**Issues guidelines**
+
+- Please search in the [documentation](http://querybuilder.js.org) before asking.
+- Any issue without enough details won't get any answer and will be closed.
+- Help requests must be exhaustive, precise and come with some code explaining the need (use Markdown code highlight).
+- Bug reports must come with a simple test case, preferably on jsFiddle, Plunker, etc. (QueryBuilder is available on [jsDelivr](https://cdn.jsdelivr.net/npm/jQuery-QueryBuilder/dist/) and [unpkg](https://unpkg.com/jQuery-QueryBuilder/dist/) to be used on such platforms).
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 00000000..1131297f
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,7 @@
+**Merge request checklist**
+
+- [ ] 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
+- [ ] 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/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 00000000..0648b398
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,21 @@
+name: CI
+
+on: [push, pull_request]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: actions/setup-node@v3
+ with:
+ node-version: '16'
+ cache: 'yarn'
+
+ - name: build
+ run: |
+ yarn install
+ yarn build
diff --git a/.gitignore b/.gitignore
index 2116521c..a952958a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
-bower_components
node_modules
+doc
.sass-cache
-.coverage-results
.idea
+*.iml
+package-lock.json
diff --git a/.jsdoc.json b/.jsdoc.json
new file mode 100644
index 00000000..d8a3fd67
--- /dev/null
+++ b/.jsdoc.json
@@ -0,0 +1,39 @@
+{
+ "opts": {
+ "private": false,
+ "template": "node_modules/foodoc/template",
+ "readme": "build/jsdoc.md"
+ },
+ "plugins": [
+ "plugins/markdown"
+ ],
+ "templates": {
+ "systemName": "jQuery QueryBuilder API",
+ "systemSummary": "jQuery plugin for user friendly query/filter creator",
+ "systemColor": "#004482",
+ "copyright": "Licensed under MIT License, documentation under CC BY 3.0.",
+ "includeDate": false,
+ "inverseNav": false,
+ "cleverLinks": true,
+ "sort": "longname, version, since",
+ "analytics": {
+ "ua": "UA-28192323-3",
+ "domain": "auto"
+ },
+ "navMembers": [
+ {"kind": "class", "title": "Classes", "summary": "All documented classes."},
+ {"kind": "external", "title": "Externals", "summary": "All documented external members."},
+ {"kind": "global", "title": "Globals", "summary": "All documented globals."},
+ {"kind": "mixin", "title": "Mixins", "summary": "All documented mixins."},
+ {"kind": "interface", "title": "Interfaces", "summary": "All documented interfaces."},
+ {"kind": "module", "title": "Modules", "summary": "All documented modules."},
+ {"kind": "event", "title": "Events", "summary": "All documented events."},
+ {"kind": "namespace", "title": "Namespaces", "summary": "All documented namespaces."},
+ {"kind": "tutorial", "title": "Tutorials", "summary": "All available tutorials."}
+ ],
+ "scripts": [
+ "https://cdnjs.cloudflare.com/ajax/libs/trianglify/1.0.1/trianglify.min.js",
+ "js/custom.js"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 7ea5c9e8..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-language: node_js
-node_js:
- - "0.12"
-before_install:
- - gem install sass
- - npm install -g grunt-cli
- - npm install -g bower
-before_script:
- - bower install
-install: npm install
-after_success: grunt coveralls
\ No newline at end of file
diff --git a/Gruntfile.js b/Gruntfile.js
deleted file mode 100644
index 8ae8a5d6..00000000
--- a/Gruntfile.js
+++ /dev/null
@@ -1,578 +0,0 @@
-var deepmerge = require('deepmerge');
-
-module.exports = function(grunt) {
- require('time-grunt')(grunt);
- require('jit-grunt')(grunt);
-
- grunt.util.linefeed = '\n';
-
- function removeJshint(src) {
- return src
- .replace(/\/\*jshint [a-z:]+ \*\/\r?\n\r?\n?/g, '')
- .replace(/\/\*jshint -[EWI]{1}[0-9]{3} \*\/\r?\n\r?\n?/g, '');
- }
-
- function process_lang(file, src, wrapper) {
- var lang = file.split(/[\/\.]/)[2];
- var content = JSON.parse(src);
- wrapper = wrapper || ['',''];
-
- grunt.config.set('lang_locale', content.__locale || lang);
- grunt.config.set('lang_author', content.__author);
- var header = grunt.template.process('<%= langBanner %>');
-
- loaded_plugins.forEach(function(p) {
- var plugin_file = 'src/plugins/'+ p +'/i18n/'+ lang +'.json';
-
- if (grunt.file.exists(plugin_file)) {
- content = deepmerge(content, grunt.file.readJSON(plugin_file));
- }
- });
-
- return header
- + '\n\n'
- + wrapper[0]
- + 'QueryBuilder.regional[\'' + lang + '\'] = '
- + JSON.stringify(content, null, 2)
- + ';\n\n'
- + 'QueryBuilder.defaults({ lang_code: \'' + lang + '\' });'
- + wrapper[1];
- }
-
-
- var all_plugins = {},
- all_langs = {},
- loaded_plugins = [],
- loaded_langs = [],
- js_core_files = [
- 'src/main.js',
- 'src/defaults.js',
- 'src/core.js',
- 'src/public.js',
- 'src/data.js',
- 'src/template.js',
- 'src/model.js',
- 'src/utils.js',
- 'src/jquery.js'
- ],
- js_files_to_load = js_core_files.slice(),
- all_js_files = js_core_files.slice(),
- js_files_for_standalone = [
- 'bower_components/jquery-extendext/jQuery.extendext.js',
- 'bower_components/doT/doT.js',
- 'dist/js/query-builder.js'
- ];
-
-
- (function(){
- // list available plugins and languages
- grunt.file.expand('src/plugins/**/plugin.js')
- .forEach(function(f) {
- var n = f.split('/')[2];
- all_plugins[n] = f;
- });
-
- grunt.file.expand('src/i18n/*.json')
- .forEach(function(f) {
- var n = f.split(/[\/\.]/)[2];
- all_langs[n] = f;
- });
-
- // fill all js files
- for (var p in all_plugins) {
- all_js_files.push(all_plugins[p]);
- }
-
- // parse 'plugins' parameter
- var arg_plugins = grunt.option('plugins');
- if (typeof arg_plugins === 'string') {
- arg_plugins.replace(/ /g, '').split(',').forEach(function(p) {
- if (all_plugins[p]) {
- js_files_to_load.push(all_plugins[p]);
- loaded_plugins.push(p);
- }
- else {
- grunt.fail.warn('Plugin '+ p +' unknown');
- }
- });
- }
- else if (arg_plugins === undefined) {
- for (var p in all_plugins) {
- js_files_to_load.push(all_plugins[p]);
- loaded_plugins.push(p);
- }
- }
-
- // default language
- js_files_to_load.push('.temp/i18n/en.js');
- loaded_langs.push('en');
-
- // parse 'lang' parameter
- var arg_langs = grunt.option('languages');
- if (typeof arg_langs === 'string') {
- arg_langs.replace(/ /g, '').split(',').forEach(function(l) {
- if (all_langs[l]) {
- if (l !== 'en') {
- js_files_to_load.push(all_langs[l].replace(/^src/, '.temp').replace(/json$/, 'js'));
- loaded_langs.push(l);
- }
- }
- else {
- grunt.fail.warn('Language '+ l +' unknown');
- }
- });
- }
- }());
-
-
- grunt.initConfig({
- pkg: grunt.file.readJSON('package.json'),
-
- banner:
- '/*!\n'+
- ' * jQuery QueryBuilder <%= pkg.version %>\n'+
- ' * Copyright 2014-<%= grunt.template.today("yyyy") %> Damien "Mistic" Sorel (http://www.strangeplanet.fr)\n'+
- ' * Licensed under MIT (http://opensource.org/licenses/MIT)\n'+
- ' */',
-
- langBanner:
- '/*!\n'+
- ' * jQuery QueryBuilder <%= pkg.version %>\n'+
- ' * Locale: <%= lang_locale %>\n'+
- '<% if (lang_author) { %> * Author: <%= lang_author %>\n<% } %>'+
- ' * Licensed under MIT (http://opensource.org/licenses/MIT)\n'+
- ' */',
-
- // bump version
- bump: {
- options: {
- files: ['package.json', 'bower.json', 'composer.json'],
- createTag: false,
- commit: false,
- push: false
- }
- },
-
- // watchers
- watch: {
- js: {
- files: ['src/*.js', 'src/plugins/**/plugin.js'],
- tasks: ['build_js']
- },
- css: {
- files: ['src/scss/*.scss', 'src/plugins/**/plugin.scss'],
- tasks: ['build_css']
- },
- lang: {
- files: ['src/i18n/*.json', 'src/plugins/**/i18n/*.json'],
- tasks: ['build_lang']
- }
- },
-
- // copy SASS files
- copy: {
- sass_core: {
- files: [{
- expand: true,
- flatten: true,
- src: ['src/scss/*.scss'],
- dest: 'dist/scss'
- }]
- },
- sass_plugins: {
- files: loaded_plugins.map(function(name) {
- return {
- src: 'src/plugins/'+ name +'/plugin.scss',
- dest: 'dist/scss/plugins/' + name + '.scss'
- };
- })
- }
- },
-
- concat: {
- // concat all JS
- js: {
- src: js_files_to_load,
- dest: 'dist/js/query-builder.js',
- options: {
- stripBanners: false,
- separator: '\n\n',
- process: function(src) {
- return removeJshint(src).replace(/\r\n/g, '\n');
- }
- }
- },
- // create standalone version
- js_standalone: {
- src: js_files_for_standalone,
- dest: 'dist/js/query-builder.standalone.js',
- options: {
- stripBanners: false,
- separator: '\n\n',
- process: function(src, file) {
- var name = file.match(/([^\/]+?).js$/)[1];
-
- return removeJshint(src)
- .replace(/\r\n/g, '\n')
- .replace(/define\((.*?)\);/, 'define(\'' + name + '\', $1);');
- }
- }
- },
- // compile language files with AMD wrapper
- lang: {
- files: Object.keys(all_langs).map(function(name) {
- return {
- src: 'src/i18n/'+ name +'.json',
- dest: 'dist/i18n/query-builder.' + name + '.js'
- };
- }),
- options: {
- process: function(src, file) {
- var wrapper = grunt.file.read('src/i18n/.wrapper.js').replace(/\r\n/g, '\n').split(/@@js\n/);
- return process_lang(file, src, wrapper);
- }
- }
- },
- // comple language files without wrapper
- lang_temp: {
- files: Object.keys(all_langs).map(function(name) {
- return {
- src: 'src/i18n/'+ name +'.json',
- dest: '.temp/i18n/' + name + '.js'
- };
- }),
- options: {
- process: function(src, file) {
- return process_lang(file, src);
- }
- }
- },
- // add banner to CSS files
- css: {
- options: {
- banner: '<%= banner %>\n\n',
- },
- files: [{
- expand: true,
- src: ['dist/css/*.css', 'dist/scss/*.scss'],
- dest: ''
- }]
- }
- },
-
- wrap: {
- // add AMD wrapper and banner
- js: {
- src: ['dist/js/query-builder.js'],
- dest: '',
- options: {
- separator: '',
- wrapper: function() {
- var wrapper = grunt.file.read('src/.wrapper.js').replace(/\r\n/g, '\n').split(/@@js\n/);
-
- if (loaded_plugins.length) {
- wrapper[0] = '// Plugins: ' + loaded_plugins.join(', ') + '\n' + wrapper[0];
- }
- if (loaded_langs.length) {
- wrapper[0] = '// Languages: ' + loaded_langs.join(', ') + '\n' + wrapper[0];
- }
- wrapper[0] = grunt.template.process('<%= banner %>\n\n') + wrapper[0];
-
- return wrapper;
- }
- }
- },
- // add plugins SASS imports
- sass: {
- src: ['dist/scss/default.scss'],
- dest: '',
- options: {
- separator: '',
- wrapper: function() {
- return ['', loaded_plugins.reduce(function(wrapper, name) {
- if (grunt.file.exists('dist/scss/plugins/' + name + '.scss')) {
- wrapper+= '\n@import \'plugins/' + name + '\';';
- }
- return wrapper;
- }, '\n')];
- }
- }
- }
- },
-
- // parse scss
- sass: {
- options: {
- sourcemap: 'none',
- style: 'expanded'
- },
- dist: {
- files: [{
- expand: true,
- flatten: true,
- src: ['dist/scss/*.scss'],
- dest: 'dist/css',
- ext: '.css',
- rename: function(dest, src) {
- return dest + '/query-builder.' + src;
- }
- }]
- }
- },
-
- // compress js
- uglify: {
- options: {
- banner: '<%= banner %>\n\n',
- mangle: { except: ['$'] }
- },
- dist: {
- files: [{
- expand: true,
- flatten: true,
- src: ['dist/js/*.js', '!dist/js/*.min.js'],
- dest: 'dist/js',
- ext: '.min.js',
- extDot: 'last'
- }]
- }
- },
-
- // compress css
- cssmin: {
- dist: {
- files: [{
- expand: true,
- flatten: true,
- src: ['dist/css/*.css', '!dist/css/*.min.css'],
- dest: 'dist/css',
- ext: '.min.css',
- extDot: 'last'
- }]
- }
- },
-
- // clean build dir
- clean: {
- temp: ['.temp']
- },
-
- // jshint tests
- jshint: {
- lib: {
- options: {
- '-W069': true // accesses to "regional" in language files
- },
- src: js_files_to_load
- }
- },
-
- // inject all source files and test modules in the test file
- 'string-replace': {
- test: {
- src: 'tests/index.html',
- dest: 'tests/index.html',
- options: {
- replacements: [{
- pattern: /()(?:[\s\S]*)()/m,
- replacement: function(match, m1, m2) {
- var scripts = '\n';
-
- js_core_files.forEach(function(file) {
- scripts+= '\n';
- });
-
- scripts+= '\n';
-
- for (var p in all_plugins) {
- scripts+= '\n';
- }
-
- return m1 + scripts + m2;
- }
- }, {
- pattern: /()(?:[\s\S]*)()/m,
- replacement: function(match, m1, m2) {
- var scripts = '\n';
-
- grunt.file.expand('tests/*.module.js').forEach(function(file) {
- scripts+= '\n';
- });
-
- return m1 + scripts + m2;
- }
- }]
- }
- }
- },
-
- // qunit test suite
- qunit: {
- all: {
- options: {
- urls: ['tests/index.html?coverage=true'],
- noGlobals: true
- }
- }
- },
-
- // save LCOV files
- qunit_blanket_lcov: {
- all: {
- files: [{
- expand: true,
- src: ['src/*.js', 'src/plugins/**/plugin.js']
- }],
- options: {
- dest: '.coverage-results/all.lcov'
- }
- }
- },
-
- // coveralls data
- coveralls: {
- options: {
- force: true
- },
- all: {
- src: '.coverage-results/all.lcov',
- }
- }
- });
-
-
- // list the triggers and changes
- grunt.registerTask('describe_triggers', 'List QueryBuilder triggers.', function() {
- var triggers = {};
- var total = 0;
-
- for (var f in all_js_files) {
- grunt.file.read(all_js_files[f]).split(/\r?\n/).forEach(function(line, i) {
- var matches = /(e = )?(?:this|that)\.(trigger|change)\('(\w+)'([^)]*)\);/.exec(line);
- if (matches !== null) {
- triggers[matches[3]] = {
- name: matches[3],
- type: matches[2],
- file: all_js_files[f],
- line: i,
- args: matches[4].slice(2),
- prevent: !!matches[1]
- };
-
- total++;
- }
- });
- }
-
- grunt.log.write('\n');
-
- for (var t in triggers) {
- grunt.log.write(t['cyan'] + ' ' + triggers[t].type['magenta']);
- if (triggers[t].prevent) grunt.log.write(' (*)'['yellow']);
- grunt.log.write('\n');
- grunt.log.writeln(' ' + (triggers[t].file +':'+ triggers[t].line)['red'] + ' ' + triggers[t].args);
- grunt.log.write('\n');
- }
-
- grunt.log.writeln((total + ' Triggers in QueryBuilder.')['cyan']['bold']);
- });
-
- // list all possible thrown errors
- grunt.registerTask('describe_errors', 'List QueryBuilder errors.', function() {
- var errors = {};
- var total = 0;
-
- for (var f in all_js_files) {
- grunt.file.read(all_js_files[f]).split(/\r?\n/).forEach(function(line, i) {
- var matches = /Utils\.error\('(\w+)', '([^)]+)'([^)]*)\);/.exec(line);
- if (matches !== null) {
- (errors[matches[1]] = errors[matches[1]] || []).push({
- type: matches[1],
- message: matches[2],
- file: all_js_files[f],
- line: i,
- args: matches[3].slice(2).split(', ')
- });
-
- total++;
- }
- });
- }
-
- grunt.log.write('\n');
-
- for (var e in errors) {
- grunt.log.writeln((e+'Error')['cyan']);
- errors[e].forEach(function(error) {
- var message = error.message.replace(/{([0-9]+)}/g, function(m, i) {
- return error.args[parseInt(i)]['yellow'];
- });
- grunt.log.writeln(' ' + (error.file +':'+ error.line)['red']);
- grunt.log.writeln(' ' + message);
- });
- grunt.log.write('\n');
- }
-
- grunt.log.writeln((total + ' Errors in QueryBuilder.')['cyan']['bold']);
- });
-
- // display available modules
- grunt.registerTask('list_modules', 'List QueryBuilder plugins and languages.', function() {
- grunt.log.writeln('\nAvailable QueryBuilder plugins:\n');
-
- for (var p in all_plugins) {
- grunt.log.write(p['cyan']);
-
- if (grunt.file.exists(all_plugins[p].replace(/js$/, 'scss'))) {
- grunt.log.write(' + CSS');
- }
-
- grunt.log.write('\n');
- }
-
- grunt.log.writeln('\nAvailable QueryBuilder languages:\n');
-
- for (var l in all_langs) {
- if (l !== 'en') {
- grunt.log.writeln(l['cyan']);
- }
- }
- });
-
-
- grunt.registerTask('build_js', [
- 'concat:lang_temp',
- 'concat:js',
- 'wrap:js',
- 'concat:js_standalone',
- 'uglify',
- 'clean:temp'
- ]);
-
- grunt.registerTask('build_css', [
- 'copy:sass_core',
- 'copy:sass_plugins',
- 'wrap:sass',
- 'sass',
- 'cssmin',
- 'concat:css'
- ]);
-
- grunt.registerTask('build_lang', [
- 'concat:lang'
- ]);
-
- grunt.registerTask('default', [
- 'build_lang',
- 'build_js',
- 'build_css'
- ]);
-
- grunt.registerTask('test', [
- 'default',
- 'jshint',
- 'string-replace:test',
- 'qunit_blanket_lcov',
- 'qunit'
- ]);
-};
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index 99070e3d..2558fa6a 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2014-2015 Damien Sorel
+Copyright (c) 2014-2018 Damien Sorel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
\ No newline at end of file
+SOFTWARE.
diff --git a/README.md b/README.md
index ed0792b0..f0fd8ab7 100644
--- a/README.md
+++ b/README.md
@@ -1,70 +1,61 @@
# jQuery QueryBuilder
-[](http://querybuilder.js.org)
-[](https://travis-ci.org/mistic100/jQuery-QueryBuilder)
-[](https://coveralls.io/r/mistic100/jQuery-QueryBuilder)
-[](http://www.jsdelivr.com/projects/jquery.query-builder)
+[](https://www.npmjs.com/package/jQuery-QueryBuilder)
+[](https://www.jsdelivr.com/package/npm/jQuery-QueryBuilder)
+[](https://github.com/mistic100/jQuery-QueryBuilder/actions)
+[](https://gitlocalize.com/repo/5259/whole_project?utm_source=badge)
jQuery plugin offering an simple interface to create complex queries.
-[](http://querybuilder.js.org)
+[](https://querybuilder.js.org)
+
+
## Documentation
-http://querybuilder.js.org
+[querybuilder.js.org](https://querybuilder.js.org)
-### Dependencies
- * jQuery >= 1.9
- * Bootstrap >= 3.1 (CSS only)
- * [jQuery.extendext](https://github.com/mistic100/jQuery.extendext)
- * [doT.js](http://olado.github.io/doT)
- * [MomentJS](http://momentjs.com) (optional, for Date/Time validation)
- * 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)
-### Browser support
- * Internet Explorer >= 9
- * All other recent browsers
+## Install
-### Build
+#### Manually
-#### Prerequisites
+[Download the latest release](https://github.com/mistic100/jQuery-QueryBuilder/releases)
- * NodeJS + NPM: `apt-get install nodejs-legacy npm`
- * Ruby Dev: `apt-get install ruby-dev`
- * Grunt CLI: `npm install -g grunt-cli`
- * Bower: `npm install -g bower`
- * SASS: `gem install sass`
+#### With npm
-#### Run
+```bash
+$ npm install jQuery-QueryBuilder
+```
-Install Node and Bower dependencies `npm install & bower install` then run `grunt` in the root directory to generate production files inside `dist`.
+#### Via CDN
-#### Options
+jQuery-QueryBuilder is available on [jsDelivr](https://www.jsdelivr.com/package/npm/jQuery-QueryBuilder).
+### Dependencies
+ * [jQuery 3](https://jquery.com)
+ * [Bootstrap 5](https://getbootstrap.com/docs/5.3/) CSS and bundle.js which includes `Popper` for tooltips and popovers
+ * [Bootstrap Icons](https://icons.getbootstrap.com/)
+ * [jQuery.extendext](https://github.com/mistic100/jQuery.extendext)
+ * [MomentJS](https://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
-You can choose which plugins to include with `--plugins` :
-```bash
-# include "sql-support" and "mongodb-support" plugins
-grunt --plugins=sql-support,mongodb-support
+($.extendext is directly included in the [standalone](https://github.com/mistic100/jQuery-QueryBuilder/blob/master/dist/js/query-builder.standalone.js) file)
-# disable all plugins
-grunt --plugins=false
-```
-All plugins are included by default.
-You can also include language files with `--languages` :
-```bash
-# include French & Italian translation
-grunt --languages=fr,it
-```
-#### Other commands
+## Developement
+
+Install Node dependencies with `npm install`.
+
+#### Build
+
+Run `npm run build` in the root directory to generate production files inside `dist`.
+
+#### Serve
+
+Run `npm run serve` to open the example page with automatic build and livereload.
- * `grunt test` to run JSHint and the QUnit test suite.
- * `grunt list_modules` to get the list of available plugins and languages.
- * `grunt describe_triggers` to get the list of all triggers.
- * `grunt watch` to automatically build the library when modifying the source files.
-### Inspiration
- * [Knockout Query Builder](http://kindohm.github.io/knockout-query-builder/)
- * [jui_filter_rules](http://www.pontikis.net/labs/jui_filter_rules/)
+## License
+This library is available under the MIT license.
diff --git a/bower.json b/bower.json
deleted file mode 100644
index 7013d5c4..00000000
--- a/bower.json
+++ /dev/null
@@ -1,52 +0,0 @@
-{
- "name": "jQuery-QueryBuilder",
- "version": "2.3.0",
- "authors": [{
- "name": "Damien \"Mistic\" Sorel",
- "email": "contact@git.strangeplanet.fr",
- "homepage": "http://www.strangeplanet.fr"
- }],
- "description": "jQuery plugin for user friendly query/filter creator",
- "main": [
- "dist/js/query-builder.js",
- "dist/css/query-builder.default.css"
- ],
- "dependencies": {
- "jquery": ">= 1.9.0",
- "bootstrap": "^3.1.0",
- "moment": "^2.6.0",
- "jquery-extendext": "^0.1.1",
- "doT": "master"
- },
- "devDependencies": {
- "blanket": "^1.1.0",
- "qunit": "^1.17.0",
- "bootstrap-select": "^1.6.0",
- "bootbox": "^4.3.0",
- "awesome-bootstrap-checkbox": "^0.3.0",
- "sql-parser": "^1.0.0"
- },
- "keywords": [
- "jquery",
- "query",
- "builder",
- "filter"
- ],
- "license": "MIT",
- "homepage": "https://github.com/mistic100/jQuery-QueryBuilder",
- "repository": {
- "type": "git",
- "url": "git://github.com/mistic100/jQuery-QueryBuilder.git"
- },
- "ignore": [
- "**/.*",
- "node_modules",
- "bower_components",
- "src",
- "tests",
- "composer.json",
- "package.json",
- "Gruntfile.js",
- "CONTRIBUTING.md"
- ]
-}
diff --git a/build/dist.mjs b/build/dist.mjs
new file mode 100644
index 00000000..e413853b
--- /dev/null
+++ b/build/dist.mjs
@@ -0,0 +1,210 @@
+import fs from 'fs';
+import path from 'path';
+import { globSync } from 'glob';
+import * as sass from 'sass';
+import pkg from '../package.json' assert { type: 'json' };
+
+const DEV = process.argv[2] === '--dev';
+
+const DIST = 'dist/';
+
+const CORE_JS = [
+ 'src/main.js',
+ 'src/defaults.js',
+ 'src/plugins.js',
+ 'src/core.js',
+ 'src/public.js',
+ 'src/data.js',
+ 'src/template.js',
+ 'src/utils.js',
+ 'src/model.js',
+ 'src/jquery.js',
+];
+
+const CORE_SASS = [
+ 'src/scss/dark.scss',
+ 'src/scss/default.scss',
+];
+
+const STANDALONE_JS = {
+ 'jquery-extendext': 'node_modules/jquery-extendext/jquery-extendext.js',
+ 'query-builder': `${DIST}js/query-builder.js`,
+};
+
+const BANNER = () => `/*!
+ * jQuery QueryBuilder ${pkg.version}
+ * Copyright 2014-${new Date().getFullYear()} Damien "Mistic" Sorel (http://www.strangeplanet.fr)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */`;
+
+const LANG_BANNER = (locale, author) => `/*!
+ * jQuery QueryBuilder ${pkg.version}
+ * Locale: ${locale}
+ * Author: ${author}
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */`;
+
+const ALL_PLUGINS_JS = glob('src/plugins/*/plugin.js')
+ .sort()
+ .reduce((all, p) => {
+ const n = p.split('/')[2];
+ all[n] = p;
+ return all;
+ }, {});
+
+const ALL_PLUGINS_SASS = glob('src/plugins/*/plugin.scss')
+ .sort()
+ .reduce((all, p) => {
+ const n = p.split('/')[2];
+ all[n] = p;
+ return all;
+ }, {});
+
+const ALL_LANGS = glob('src/i18n/*.json')
+ .map(p => p.split(/[\/\.]/)[2])
+ .sort();
+
+function glob(pattern) {
+ return globSync(pattern)
+ .map(p => p.split(path.sep).join('/'));
+}
+
+/**
+ * Build lang files
+ */
+function buildLangs() {
+ const wrapper = fs.readFileSync('src/i18n/.wrapper.js', { encoding: 'utf8' })
+ .split('@@js\n');
+
+ ALL_LANGS.forEach(lang => {
+ const outpath = `${DIST}i18n/query-builder.${lang}.js`;
+ console.log(`LANG ${lang} (${outpath})`);
+ fs.writeFileSync(outpath, getLang(lang, wrapper));
+ });
+}
+
+/**
+ * Get the content of a single lang
+ */
+function getLang(lang, wrapper = ['', '']) {
+ const corepath = `src/i18n/${lang}.json`;
+ const content = JSON.parse(fs.readFileSync(corepath, { encoding: 'utf8' }));
+
+ Object.keys(ALL_PLUGINS_JS).forEach(plugin => {
+ const pluginpath = `src/plugins/${plugin}/i18n/${lang}.json`;
+ try {
+ const plugincontent = JSON.parse(fs.readFileSync(pluginpath, { encoding: 'utf8' }));
+ Object.assign(content, plugincontent);
+ } catch { }
+ });
+
+ return LANG_BANNER(content.__locale || lang, content.__author || '')
+ + '\n\n'
+ + wrapper[0]
+ + `QueryBuilder.regional['${lang}'] = `
+ + JSON.stringify(content, null, 2)
+ + ';\n\n'
+ + `QueryBuilder.defaults({ lang_code: '${lang}' });`
+ + wrapper[1];
+}
+
+/**
+ * Build main JS file
+ */
+function buildMain() {
+ const wrapper = fs.readFileSync('src/.wrapper.js', { encoding: 'utf8' })
+ .split('@@js\n');
+
+ const files_to_load = [
+ ...CORE_JS,
+ ...Object.values(ALL_PLUGINS_JS),
+ ];
+
+ const output = BANNER()
+ + '\n\n'
+ + wrapper[0]
+ + files_to_load.map(f => fs.readFileSync(f, { encoding: 'utf8' })).join('\n\n')
+ + '\n\n'
+ + getLang('en')
+ + wrapper[1];
+
+ const outpath = `${DIST}js/query-builder.js`;
+ console.log(`MAIN (${outpath})`);
+ fs.writeFileSync(outpath, output);
+}
+
+/**
+ * Build standalone JS file
+ */
+function buildStandalone() {
+ const output = Object.entries(STANDALONE_JS)
+ .map(([name, file]) => {
+ return fs.readFileSync(file, { encoding: 'utf8' })
+ .replace(/define\((.*?)\);/, `define('${name}', $1);`);
+ })
+ .join('\n\n');
+
+ const outpath = `${DIST}js/query-builder.standalone.js`;
+ console.log(`STANDALONE (${outpath})`);
+ fs.writeFileSync(outpath, output);
+}
+
+/**
+ * Copy SASS files
+ */
+function copySass() {
+ Object.entries(ALL_PLUGINS_SASS).forEach(([plugin, path]) => {
+ const outpath = `${DIST}scss/plugins/${plugin}.scss`;
+ console.log(`SASS ${plugin} (${path})`);
+ fs.copyFileSync(path, outpath);
+ });
+
+ CORE_SASS.forEach(path => {
+ const name = path.split('/').pop();
+
+ const content = fs.readFileSync(path, { encoding: 'utf8' });
+
+ let output = BANNER()
+ + '\n'
+ + content;
+ if (name === 'default.scss') {
+ output += '\n'
+ + Object.keys(ALL_PLUGINS_SASS).map(p => `@import "plugins/${p}";`).join('\n');
+ }
+
+ const outpath = `${DIST}scss/${name}`;
+ console.log(`SASS (${path})`);
+ fs.writeFileSync(outpath, output);
+ });
+}
+
+/**
+ * Build CSS files
+ */
+function buildCss() {
+ CORE_SASS.forEach(p => {
+ const path = p.replace('src/', DIST);
+ const name = path.split('/').pop();
+
+ const output = sass.compile(path);
+
+ const outpath = `${DIST}css/query-builder.${name.split('.').shift()}.css`;
+ console.log(`CSS (${path})`);
+ fs.writeFileSync(outpath, output.css);
+ });
+}
+
+if (!DEV) {
+ fs.rmSync(DIST, { recursive: true, force: true });
+}
+fs.mkdirSync(DIST + 'css', { recursive: true });
+fs.mkdirSync(DIST + 'i18n', { recursive: true });
+fs.mkdirSync(DIST + 'js', { recursive: true });
+fs.mkdirSync(DIST + 'scss', { recursive: true });
+fs.mkdirSync(DIST + 'scss/plugins', { recursive: true });
+
+buildLangs();
+buildMain();
+buildStandalone();
+copySass();
+buildCss();
diff --git a/build/jsdoc.js b/build/jsdoc.js
new file mode 100644
index 00000000..edbad8d4
--- /dev/null
+++ b/build/jsdoc.js
@@ -0,0 +1,12 @@
+(function() {
+ var header = $('.page-header');
+ var pattern = Trianglify({
+ width: window.screen.width | header.outerWidth(),
+ height: header.outerHeight(),
+ cell_size: 90,
+ seed: 'jQuery QueryBuilder',
+ x_colors: ['#0074d9', '#001224']
+ });
+
+ header.css('background-image', 'url(' + pattern.png() + ')');
+}());
diff --git a/build/jsdoc.md b/build/jsdoc.md
new file mode 100644
index 00000000..e329af92
--- /dev/null
+++ b/build/jsdoc.md
@@ -0,0 +1,11 @@
+# [Main documentation](..)
+
+# Entry point: [$.fn.QueryBuilder](external-_jQuery.fn_.html)
+
+# [QueryBuilder](QueryBuilder.html)
+
+# [Rule](Rule.html) & [Group](Group.html)
+
+# [Events](list_event.html)
+
+# [Plugins](module-plugins.html)
diff --git a/build/liveserver.mjs b/build/liveserver.mjs
new file mode 100644
index 00000000..3d60e23c
--- /dev/null
+++ b/build/liveserver.mjs
@@ -0,0 +1,20 @@
+import liveServer from 'alive-server';
+import path from 'path';
+
+const rootDir = process.cwd();
+
+const EXAMPLES_DIR = 'examples';
+const DIST_DIR = 'dist';
+
+liveServer.start({
+ open: true,
+ root: path.join(rootDir, EXAMPLES_DIR),
+ watch: [
+ path.join(rootDir, EXAMPLES_DIR),
+ path.join(rootDir, DIST_DIR),
+ ],
+ mount: [
+ ['/node_modules', path.join(rootDir, 'node_modules')],
+ ['/dist', path.join(rootDir, DIST_DIR)],
+ ],
+});
diff --git a/composer.json b/composer.json
deleted file mode 100644
index 7e9b8133..00000000
--- a/composer.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "name": "mistic100/jquery-querybuilder",
- "version": "2.3.0",
- "authors": [{
- "name": "Damien \"Mistic\" Sorel",
- "email": "contact@git.strangeplanet.fr",
- "homepage": "http://www.strangeplanet.fr"
- }],
- "description": "jQuery plugin for user friendly query/filter creator",
- "require": {
- "components/jquery": ">=1.9.0",
- "moment/moment": ">=2.6.0",
- "twbs/bootstrap": ">=3.1.0"
- },
- "keywords": [
- "jquery",
- "query",
- "builder",
- "filter"
- ],
- "license": "MIT",
- "homepage": "https://github.com/mistic100/jQuery-QueryBuilder",
- "support": {
- "issues": "https://github.com/mistic100/jQuery-QueryBuilder/issues"
- }
-}
diff --git a/dist/css/query-builder.dark.css b/dist/css/query-builder.dark.css
index ff7c5e1c..90b5fbaa 100644
--- a/dist/css/query-builder.dark.css
+++ b/dist/css/query-builder.dark.css
@@ -1,10 +1,14 @@
/*!
- * jQuery QueryBuilder 2.3.0
- * Copyright 2014-2015 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * jQuery QueryBuilder 3.0.0
+ * Copyright 2014-2024 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
-
-.query-builder .rules-group-container, .query-builder .rule-container, .query-builder .rule-placeholder {
+/*!
+ * jQuery QueryBuilder 3.0.0
+ * Copyright 2014-2024 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+.query-builder .rule-placeholder, .query-builder .rule-container, .query-builder .rules-group-container {
position: relative;
margin: 4px 0;
border-radius: 5px;
@@ -13,9 +17,9 @@
background: rgba(40, 40, 40, 0.9);
}
-.query-builder .rule-container .rule-filter-container,
+.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, .query-builder .error-container, .query-builder .drag-handle {
+.query-builder .rule-container .rule-value-container {
display: inline-block;
margin: 0 5px 0 0;
vertical-align: middle;
@@ -27,31 +31,40 @@
border: 1px solid #00164A;
background: rgba(50, 70, 80, 0.5);
}
-.query-builder .rules-group-container .rules-group-header {
+.query-builder .rules-group-header {
margin-bottom: 10px;
}
-.query-builder .rules-group-container .rules-group-header input[name$=_cond] {
- display: none;
+.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-container .rules-list {
+.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-container .rule-value-container {
- border-left: 1px solid #ddd;
+.query-builder .rule-value-container {
+ border-left: 1px solid #DDD;
padding-left: 5px;
}
-.query-builder .rule-container .rule-value-container label {
+.query-builder .rule-value-container label {
margin-bottom: 0;
font-weight: normal;
}
-.query-builder .rule-container .rule-value-container label.block {
+.query-builder .rule-value-container label.block {
display: block;
}
-.query-builder .rule-container select, .query-builder .rule-container input[type=text], .query-builder .rule-container input[type=number] {
- padding: 1px;
-}
.query-builder .error-container {
display: none;
cursor: help;
@@ -64,8 +77,8 @@
.query-builder .has-error .error-container {
display: inline-block !important;
}
-.query-builder .rules-list > *:before, .query-builder .rules-list > *:after {
- content: '';
+.query-builder .rules-list > *::before, .query-builder .rules-list > *::after {
+ content: "";
position: absolute;
left: -10px;
width: 10px;
@@ -73,25 +86,33 @@
border-color: #222;
border-style: solid;
}
-.query-builder .rules-list > *:before {
+.query-builder .rules-list > *::before {
top: -4px;
border-width: 0 0 2px 2px;
}
-.query-builder .rules-list > *:after {
+.query-builder .rules-list > *::after {
top: 50%;
border-width: 0 0 0 2px;
}
-.query-builder .rules-list > *:first-child:before {
+.query-builder .rules-list > *:first-child::before {
top: -12px;
height: calc(50% + 14px);
}
-.query-builder .rules-list > *:last-child:before {
+.query-builder .rules-list > *:last-child::before {
border-radius: 0 0 0 4px;
}
-.query-builder .rules-list > *:last-child:after {
+.query-builder .rules-list > *:last-child::after {
display: none;
}
+.query-builder.bt-checkbox-bootstrap-icons .checkbox input[type=checkbox] + label::before {
+ outline: 0;
+}
+.query-builder.bt-checkbox-bootstrap-icons .checkbox input[type=checkbox]:checked + label::after {
+ font-family: "bootstrap-icons";
+ content: "\f633";
+}
+
.query-builder .error-container + .tooltip .tooltip-inner {
color: #F22 !important;
}
@@ -115,10 +136,15 @@
vertical-align: middle;
margin-left: 5px;
}
-.query-builder .dragged {
+.query-builder .dragging {
+ position: fixed;
opacity: 0.5;
+ z-index: 100;
+}
+.query-builder .dragging::before, .query-builder .dragging::after {
+ display: none;
}
.query-builder .rule-placeholder {
border: 1px dashed #BBB;
opacity: 0.7;
-}
+}
\ No newline at end of file
diff --git a/dist/css/query-builder.dark.min.css b/dist/css/query-builder.dark.min.css
deleted file mode 100644
index 5062ba74..00000000
--- a/dist/css/query-builder.dark.min.css
+++ /dev/null
@@ -1,7 +0,0 @@
-/*!
- * jQuery QueryBuilder 2.3.0
- * Copyright 2014-2015 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-container .rules-group-header{margin-bottom:10px}.query-builder .rules-group-container .rules-group-header input[name$=_cond]{display:none}.query-builder .rules-group-container .rules-list{list-style:none;padding:0 0 0 15px;margin:0}.query-builder .rule-container .rule-value-container{border-left:1px solid #ddd;padding-left:5px}.query-builder .rule-container .rule-value-container label{margin-bottom:0;font-weight:400}.query-builder .rule-container .rule-value-container label.block{display:block}.query-builder .rule-container input[type=number],.query-builder .rule-container input[type=text],.query-builder .rule-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 .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 .dragged{opacity:.5}.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 d333a840..b5edf68e 100644
--- a/dist/css/query-builder.default.css
+++ b/dist/css/query-builder.default.css
@@ -1,10 +1,9 @@
/*!
- * jQuery QueryBuilder 2.3.0
- * Copyright 2014-2015 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * jQuery QueryBuilder 3.0.0
+ * Copyright 2014-2024 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
-
-.query-builder .rules-group-container, .query-builder .rule-container, .query-builder .rule-placeholder {
+.query-builder .rule-placeholder, .query-builder .rule-container, .query-builder .rules-group-container {
position: relative;
margin: 4px 0;
border-radius: 5px;
@@ -13,9 +12,9 @@
background: rgba(255, 255, 255, 0.9);
}
-.query-builder .rule-container .rule-filter-container,
+.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, .query-builder .error-container, .query-builder .drag-handle {
+.query-builder .rule-container .rule-value-container {
display: inline-block;
margin: 0 5px 0 0;
vertical-align: middle;
@@ -27,31 +26,40 @@
border: 1px solid #DCC896;
background: rgba(250, 240, 210, 0.5);
}
-.query-builder .rules-group-container .rules-group-header {
+.query-builder .rules-group-header {
margin-bottom: 10px;
}
-.query-builder .rules-group-container .rules-group-header input[name$=_cond] {
- display: none;
+.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-container .rules-list {
+.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-container .rule-value-container {
- border-left: 1px solid #ddd;
+.query-builder .rule-value-container {
+ border-left: 1px solid #DDD;
padding-left: 5px;
}
-.query-builder .rule-container .rule-value-container label {
+.query-builder .rule-value-container label {
margin-bottom: 0;
font-weight: normal;
}
-.query-builder .rule-container .rule-value-container label.block {
+.query-builder .rule-value-container label.block {
display: block;
}
-.query-builder .rule-container select, .query-builder .rule-container input[type=text], .query-builder .rule-container input[type=number] {
- padding: 1px;
-}
.query-builder .error-container {
display: none;
cursor: help;
@@ -64,8 +72,8 @@
.query-builder .has-error .error-container {
display: inline-block !important;
}
-.query-builder .rules-list > *:before, .query-builder .rules-list > *:after {
- content: '';
+.query-builder .rules-list > *::before, .query-builder .rules-list > *::after {
+ content: "";
position: absolute;
left: -10px;
width: 10px;
@@ -73,25 +81,33 @@
border-color: #CCC;
border-style: solid;
}
-.query-builder .rules-list > *:before {
+.query-builder .rules-list > *::before {
top: -4px;
border-width: 0 0 2px 2px;
}
-.query-builder .rules-list > *:after {
+.query-builder .rules-list > *::after {
top: 50%;
border-width: 0 0 0 2px;
}
-.query-builder .rules-list > *:first-child:before {
+.query-builder .rules-list > *:first-child::before {
top: -12px;
height: calc(50% + 14px);
}
-.query-builder .rules-list > *:last-child:before {
+.query-builder .rules-list > *:last-child::before {
border-radius: 0 0 0 4px;
}
-.query-builder .rules-list > *:last-child:after {
+.query-builder .rules-list > *:last-child::after {
display: none;
}
+.query-builder.bt-checkbox-bootstrap-icons .checkbox input[type=checkbox] + label::before {
+ outline: 0;
+}
+.query-builder.bt-checkbox-bootstrap-icons .checkbox input[type=checkbox]:checked + label::after {
+ font-family: "bootstrap-icons";
+ content: "\f633";
+}
+
.query-builder .error-container + .tooltip .tooltip-inner {
color: #F99 !important;
}
@@ -115,10 +131,15 @@
vertical-align: middle;
margin-left: 5px;
}
-.query-builder .dragged {
+.query-builder .dragging {
+ position: fixed;
opacity: 0.5;
+ z-index: 100;
+}
+.query-builder .dragging::before, .query-builder .dragging::after {
+ display: none;
}
.query-builder .rule-placeholder {
border: 1px dashed #BBB;
opacity: 0.7;
-}
+}
\ No newline at end of file
diff --git a/dist/css/query-builder.default.min.css b/dist/css/query-builder.default.min.css
deleted file mode 100644
index 0e95d802..00000000
--- a/dist/css/query-builder.default.min.css
+++ /dev/null
@@ -1,7 +0,0 @@
-/*!
- * jQuery QueryBuilder 2.3.0
- * Copyright 2014-2015 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-container .rules-group-header{margin-bottom:10px}.query-builder .rules-group-container .rules-group-header input[name$=_cond]{display:none}.query-builder .rules-group-container .rules-list{list-style:none;padding:0 0 0 15px;margin:0}.query-builder .rule-container .rule-value-container{border-left:1px solid #ddd;padding-left:5px}.query-builder .rule-container .rule-value-container label{margin-bottom:0;font-weight:400}.query-builder .rule-container .rule-value-container label.block{display:block}.query-builder .rule-container input[type=number],.query-builder .rule-container input[type=text],.query-builder .rule-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 .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 .dragged{opacity:.5}.query-builder .rule-placeholder{border:1px dashed #BBB;opacity:.7}
\ No newline at end of file
diff --git a/dist/i18n/query-builder.ar.js b/dist/i18n/query-builder.ar.js
new file mode 100644
index 00000000..edb2917e
--- /dev/null
+++ b/dist/i18n/query-builder.ar.js
@@ -0,0 +1,80 @@
+/*!
+ * jQuery QueryBuilder 3.0.0
+ * Locale: Arabic (ar)
+ * Author: Mohamed YOUNES, https://github.com/MedYOUNES
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['ar'] = {
+ "__locale": "Arabic (ar)",
+ "__author": "Mohamed YOUNES, https://github.com/MedYOUNES",
+ "add_rule": "إضافة حُكم",
+ "add_group": "إضافة زُمْرَة",
+ "delete_rule": "حذف",
+ "delete_group": "حذف",
+ "conditions": {
+ "AND": "و",
+ "OR": "أو"
+ },
+ "operators": {
+ "equal": "يساوي",
+ "not_equal": "غير مساوٍ",
+ "in": "في",
+ "not_in": "ليس في",
+ "less": "أقل من",
+ "less_or_equal": "أصغر أو مساو",
+ "greater": "أكبر",
+ "greater_or_equal": "أكبر أو مساو",
+ "between": "محصور بين",
+ "not_between": "غير محصور بين",
+ "begins_with": "يبدأ بـ",
+ "not_begins_with": "لا يبدأ بـ",
+ "contains": "يحتوي على",
+ "not_contains": "لا يحتوي على",
+ "ends_with": "ينتهي بـ",
+ "not_ends_with": "لا ينتهي بـ",
+ "is_empty": "فارغ",
+ "is_not_empty": "غير فارغ",
+ "is_null": "صفر",
+ "is_not_null": "ليس صفرا"
+ },
+ "errors": {
+ "no_filter": "لم تحدد أي مرشح",
+ "empty_group": "الزمرة فارغة",
+ "radio_empty": "لم تحدد أي قيمة",
+ "checkbox_empty": "لم تحدد أي قيمة",
+ "select_empty": "لم تحدد أي قيمة",
+ "string_empty": "النص فارغ",
+ "string_exceed_min_length": "النص دون الأدنى المسموح به",
+ "string_exceed_max_length": "النص فوق الأقصى المسموح به",
+ "string_invalid_format": "تركيبة غير صحيحة",
+ "number_nan": "ليس عددا",
+ "number_not_integer": "ليس عددا صحيحا",
+ "number_not_double": "ليس عددا كسريا",
+ "number_exceed_min": "العدد أصغر من الأدنى المسموح به",
+ "number_exceed_max": "العدد أكبر من الأقصى المسموح به",
+ "number_wrong_step": "أخطأت في حساب مضاعفات العدد",
+ "datetime_empty": "لم تحدد التاريخ",
+ "datetime_invalid": "صيغة التاريخ غير صحيحة",
+ "datetime_exceed_min": "التاريخ دون الأدنى المسموح به",
+ "datetime_exceed_max": "التاريخ أكبر من الأقصى المسموح به",
+ "boolean_not_valid": "ليست قيمة منطقية ثنائية",
+ "operator_not_multiple": "العامل ليس متعدد القيَم"
+ },
+ "invert": "قَلْبُ"
+};
+
+QueryBuilder.defaults({ lang_code: 'ar' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.az.js b/dist/i18n/query-builder.az.js
new file mode 100644
index 00000000..3820f42e
--- /dev/null
+++ b/dist/i18n/query-builder.az.js
@@ -0,0 +1,79 @@
+/*!
+ * jQuery QueryBuilder 3.0.0
+ * Locale: Azerbaijan (az)
+ * Author: Megaplan, mborisv
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['az'] = {
+ "__locale": "Azerbaijan (az)",
+ "__author": "Megaplan, mborisv ",
+ "add_rule": "Əlavə etmək",
+ "add_group": "Qrup əlavə etmək",
+ "delete_rule": "Silmək",
+ "delete_group": "Silmək",
+ "conditions": {
+ "AND": "VƏ",
+ "OR": "VƏ YA"
+ },
+ "operators": {
+ "equal": "bərabərdir",
+ "not_equal": "bərabər deyil",
+ "in": "qeyd edilmişlərdən",
+ "not_in": "qeyd olunmamışlardan",
+ "less": "daha az",
+ "less_or_equal": "daha az və ya bərabər",
+ "greater": "daha çox",
+ "greater_or_equal": "daha çox və ya bərabər",
+ "between": "arasında",
+ "begins_with": "başlayır",
+ "not_begins_with": "başlamır",
+ "contains": "ibarətdir",
+ "not_contains": "yoxdur",
+ "ends_with": "başa çatır",
+ "not_ends_with": "başa çatmır",
+ "is_empty": "boş sətir",
+ "is_not_empty": "boş olmayan sətir",
+ "is_null": "boşdur",
+ "is_not_null": "boş deyil"
+ },
+ "errors": {
+ "no_filter": "Filterlər seçilməyib",
+ "empty_group": "Qrup boşdur",
+ "radio_empty": "Məna seçilməyib",
+ "checkbox_empty": "Məna seçilməyib",
+ "select_empty": "Məna seçilməyib",
+ "string_empty": "Doldurulmayıb",
+ "string_exceed_min_length": "{0} daha çox simvol olmalıdır",
+ "string_exceed_max_length": "{0} daha az simvol olmalıdır",
+ "string_invalid_format": "Yanlış format ({0})",
+ "number_nan": "Rəqəm deyil",
+ "number_not_integer": "Rəqəm deyil",
+ "number_not_double": "Rəqəm deyil",
+ "number_exceed_min": "{0} daha çox olmalıdır",
+ "number_exceed_max": "{0} daha az olmalıdır",
+ "number_wrong_step": "{0} bölünən olmalıdır",
+ "datetime_empty": "Doldurulmayıb",
+ "datetime_invalid": "Yanlış tarix formatı ({0})",
+ "datetime_exceed_min": "{0} sonra olmalıdır",
+ "datetime_exceed_max": "{0} əvvəl olmalıdır",
+ "boolean_not_valid": "Loqik olmayan",
+ "operator_not_multiple": "\"{1}\" operatoru çoxlu məna daşımır"
+ },
+ "invert": "invert"
+};
+
+QueryBuilder.defaults({ lang_code: 'az' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.bg.js b/dist/i18n/query-builder.bg.js
new file mode 100644
index 00000000..3fa9dc74
--- /dev/null
+++ b/dist/i18n/query-builder.bg.js
@@ -0,0 +1,79 @@
+/*!
+ * jQuery QueryBuilder 3.0.0
+ * Locale: Bulgarian (bg)
+ * Author: Valentin Hristov
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['bg'] = {
+ "__locale": "Bulgarian (bg)",
+ "__author": "Valentin Hristov",
+ "add_rule": "Добави правило",
+ "add_group": "Добави група",
+ "delete_rule": "Изтрий",
+ "delete_group": "Изтрий",
+ "conditions": {
+ "AND": "И",
+ "OR": "ИЛИ"
+ },
+ "operators": {
+ "equal": "равно",
+ "not_equal": "различно",
+ "in": "в",
+ "not_in": "не е в",
+ "less": "по-малко",
+ "less_or_equal": "по-малко или равно",
+ "greater": "по-голям",
+ "greater_or_equal": "по-голям или равно",
+ "between": "между",
+ "not_between": "не е между",
+ "begins_with": "започва с",
+ "not_begins_with": "не започва с",
+ "contains": "съдържа",
+ "not_contains": "не съдържа",
+ "ends_with": "завършва с",
+ "not_ends_with": "не завършва с",
+ "is_empty": "е празно",
+ "is_not_empty": "не е празно",
+ "is_null": "е нищо",
+ "is_not_null": "различно от нищо"
+ },
+ "errors": {
+ "no_filter": "Не е избран филтър",
+ "empty_group": "Групата е празна",
+ "radio_empty": "Не е селектирана стойност",
+ "checkbox_empty": "Не е селектирана стойност",
+ "select_empty": "Не е селектирана стойност",
+ "string_empty": "Празна стойност",
+ "string_exceed_min_length": "Необходимо е да съдържа поне {0} символа",
+ "string_exceed_max_length": "Необходимо е да съдържа повече от {0} символа",
+ "string_invalid_format": "Невалиден формат ({0})",
+ "number_nan": "Не е число",
+ "number_not_integer": "Не е цяло число",
+ "number_not_double": "Не е реално число",
+ "number_exceed_min": "Трябва да е по-голямо от {0}",
+ "number_exceed_max": "Трябва да е по-малко от {0}",
+ "number_wrong_step": "Трябва да е кратно на {0}",
+ "datetime_empty": "Празна стойност",
+ "datetime_invalid": "Невалиден формат на дата ({0})",
+ "datetime_exceed_min": "Трябва да е след {0}",
+ "datetime_exceed_max": "Трябва да е преди {0}",
+ "boolean_not_valid": "Не е булева",
+ "operator_not_multiple": "Оператора \"{1}\" не може да приеме множество стойности"
+ }
+};
+
+QueryBuilder.defaults({ lang_code: 'bg' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.cs.js b/dist/i18n/query-builder.cs.js
new file mode 100644
index 00000000..551bee28
--- /dev/null
+++ b/dist/i18n/query-builder.cs.js
@@ -0,0 +1,79 @@
+/*!
+ * jQuery QueryBuilder 3.0.0
+ * Locale: Čeština (cs)
+ * Author: Megaplan, mborisv
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['cs'] = {
+ "__locale": "Čeština (cs)",
+ "__author": "Megaplan, mborisv ",
+ "add_rule": "Přidat",
+ "add_group": "Přidat skupinu",
+ "delete_rule": "Odstranit",
+ "delete_group": "Odstranit skupinu",
+ "conditions": {
+ "AND": "I",
+ "OR": "NEBO"
+ },
+ "operators": {
+ "equal": "stejně",
+ "not_equal": "liší se",
+ "in": "z uvedených",
+ "not_in": "ne z uvedených",
+ "less": "méně",
+ "less_or_equal": "méně nebo stejně",
+ "greater": "více",
+ "greater_or_equal": "více nebo stejně",
+ "between": "mezi",
+ "begins_with": "začíná z",
+ "not_begins_with": "nezačíná z",
+ "contains": "obsahuje",
+ "not_contains": "neobsahuje",
+ "ends_with": "končí na",
+ "not_ends_with": "nekončí na",
+ "is_empty": "prázdný řádek",
+ "is_not_empty": "neprázdný řádek",
+ "is_null": "prázdno",
+ "is_not_null": "plno"
+ },
+ "errors": {
+ "no_filter": "není vybraný filtr",
+ "empty_group": "prázdná skupina",
+ "radio_empty": "Není udaná hodnota",
+ "checkbox_empty": "Není udaná hodnota",
+ "select_empty": "Není udaná hodnota",
+ "string_empty": "Nevyplněno",
+ "string_exceed_min_length": "Musí obsahovat více {0} symbolů",
+ "string_exceed_max_length": "Musí obsahovat méně {0} symbolů",
+ "string_invalid_format": "Nesprávný formát ({0})",
+ "number_nan": "Žádné číslo",
+ "number_not_integer": "Žádné číslo",
+ "number_not_double": "Žádné číslo",
+ "number_exceed_min": "Musí být více {0}",
+ "number_exceed_max": "Musí být méně {0}",
+ "number_wrong_step": "Musí být násobkem {0}",
+ "datetime_empty": "Nevyplněno",
+ "datetime_invalid": "Nesprávný formát datumu ({0})",
+ "datetime_exceed_min": "Musí být po {0}",
+ "datetime_exceed_max": "Musí být do {0}",
+ "boolean_not_valid": "Nelogické",
+ "operator_not_multiple": "Operátor \"{1}\" nepodporuje mnoho hodnot"
+ },
+ "invert": "invertní"
+};
+
+QueryBuilder.defaults({ lang_code: 'cs' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.da.js b/dist/i18n/query-builder.da.js
index 0baff65d..ff6d3f77 100644
--- a/dist/i18n/query-builder.da.js
+++ b/dist/i18n/query-builder.da.js
@@ -1,12 +1,12 @@
/*!
- * jQuery QueryBuilder 2.3.0
+ * jQuery QueryBuilder 3.0.0
* Locale: Danish (da)
* Author: Jna Borup Coyle, github@coyle.dk
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
(function(root, factory) {
- if (typeof define === 'function' && define.amd) {
+ if (typeof define == 'function' && define.amd) {
define(['jquery', 'query-builder'], factory);
}
else {
diff --git a/dist/i18n/query-builder.de.js b/dist/i18n/query-builder.de.js
index d930f8e0..d92c6679 100644
--- a/dist/i18n/query-builder.de.js
+++ b/dist/i18n/query-builder.de.js
@@ -1,12 +1,12 @@
/*!
- * jQuery QueryBuilder 2.3.0
+ * jQuery QueryBuilder 3.0.0
* Locale: German (de)
* Author: "raimu"
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
(function(root, factory) {
- if (typeof define === 'function' && define.amd) {
+ if (typeof define == 'function' && define.amd) {
define(['jquery', 'query-builder'], factory);
}
else {
@@ -37,6 +37,8 @@ QueryBuilder.regional['de'] = {
"less_or_equal": "kleiner gleich",
"greater": "größer",
"greater_or_equal": "größer gleich",
+ "between": "zwischen",
+ "not_between": "nicht zwischen",
"begins_with": "beginnt mit",
"not_begins_with": "beginnt nicht mit",
"contains": "enthält",
diff --git a/dist/i18n/query-builder.el.js b/dist/i18n/query-builder.el.js
new file mode 100644
index 00000000..701d2045
--- /dev/null
+++ b/dist/i18n/query-builder.el.js
@@ -0,0 +1,80 @@
+/*!
+ * jQuery QueryBuilder 3.0.0
+ * Locale: Greek (el)
+ * Author: Stelios Patsatzis, https://www.linkedin.com/in/stelios-patsatzis-89841561
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['el'] = {
+ "__locale": "Greek (el)",
+ "__author": "Stelios Patsatzis, https://www.linkedin.com/in/stelios-patsatzis-89841561",
+ "add_rule": "Προσθήκη Συνθήκης",
+ "add_group": "Προσθήκη Ομάδας",
+ "delete_rule": "Διαγραφή",
+ "delete_group": "Διαγραφή",
+ "conditions": {
+ "AND": "Λογικό ΚΑΙ",
+ "OR": "Λογικό Η"
+ },
+ "operators": {
+ "equal": "Ισούται με",
+ "not_equal": "Διάφορο από ",
+ "in": "Περιέχει",
+ "not_in": "Δεν Περιέχει",
+ "less": "Λιγότερο από",
+ "less_or_equal": "Λιγότερο ή Ίσο",
+ "greater": "Μεγαλύτερο από",
+ "greater_or_equal": "Μεγαλύτερο ή Ίσο",
+ "between": "Μεταξύ",
+ "not_between": "Εκτός",
+ "begins_with": "Αρχίζει με",
+ "not_begins_with": "Δεν αρχίζει με",
+ "contains": "Περιέχει",
+ "not_contains": "Δεν περιέχει",
+ "ends_with": "Τελειώνει σε",
+ "not_ends_with": "Δεν τελειώνει σε",
+ "is_empty": "Είναι άδειο",
+ "is_not_empty": "Δεν είναι άδειο",
+ "is_null": "Είναι NULL",
+ "is_not_null": "Δεν είναι NULL"
+ },
+ "errors": {
+ "no_filter": "Χωρίς φίλτρα",
+ "empty_group": "Άδεια ομάδα",
+ "radio_empty": "Χωρίς τιμή",
+ "checkbox_empty": "Χωρίς τιμή",
+ "select_empty": "Χωρίς τιμή",
+ "string_empty": "Χωρίς τιμή",
+ "string_exceed_min_length": "Ελάχιστο όριο {0} χαρακτήρων",
+ "string_exceed_max_length": "Μέγιστο όριο {0} χαρακτήρων",
+ "string_invalid_format": "Λανθασμένη μορφή ({0})",
+ "number_nan": "Δεν είναι αριθμός",
+ "number_not_integer": "Δεν είναι ακέραιος αριθμός",
+ "number_not_double": "Δεν είναι πραγματικός αριθμός",
+ "number_exceed_min": "Πρέπει να είναι μεγαλύτερο απο {0}",
+ "number_exceed_max": "Πρέπει να είναι μικρότερο απο {0}",
+ "number_wrong_step": "Πρέπει να είναι πολλαπλάσιο του {0}",
+ "datetime_empty": "Χωρίς τιμή",
+ "datetime_invalid": "Λανθασμένη μορφή ημερομηνίας ({0})",
+ "datetime_exceed_min": "Νεότερο από {0}",
+ "datetime_exceed_max": "Παλαιότερο από {0}",
+ "boolean_not_valid": "Δεν είναι BOOLEAN",
+ "operator_not_multiple": "Η συνθήκη \"{1}\" δεν μπορεί να δεχθεί πολλαπλές τιμές"
+ },
+ "invert": "Εναλλαγή"
+};
+
+QueryBuilder.defaults({ lang_code: 'el' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.en.js b/dist/i18n/query-builder.en.js
index b460d520..a6ce0f66 100644
--- a/dist/i18n/query-builder.en.js
+++ b/dist/i18n/query-builder.en.js
@@ -1,12 +1,12 @@
/*!
- * jQuery QueryBuilder 2.3.0
+ * jQuery QueryBuilder 3.0.0
* Locale: English (en)
* Author: Damien "Mistic" Sorel, http://www.strangeplanet.fr
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
(function(root, factory) {
- if (typeof define === 'function' && define.amd) {
+ if (typeof define == 'function' && define.amd) {
define(['jquery', 'query-builder'], factory);
}
else {
@@ -66,14 +66,17 @@ QueryBuilder.regional['en'] = {
"number_exceed_min": "Must be greater than {0}",
"number_exceed_max": "Must be lower than {0}",
"number_wrong_step": "Must be a multiple of {0}",
+ "number_between_invalid": "Invalid values, {0} is greater than {1}",
"datetime_empty": "Empty value",
"datetime_invalid": "Invalid date format ({0})",
"datetime_exceed_min": "Must be after {0}",
"datetime_exceed_max": "Must be before {0}",
+ "datetime_between_invalid": "Invalid values, {0} is greater than {1}",
"boolean_not_valid": "Not a boolean",
- "operator_not_multiple": "Operator {0} cannot accept multiple values"
+ "operator_not_multiple": "Operator \"{1}\" cannot accept multiple values"
},
- "invert": "Invert"
+ "invert": "Invert",
+ "NOT": "NOT"
};
QueryBuilder.defaults({ lang_code: 'en' });
diff --git a/dist/i18n/query-builder.eo.js b/dist/i18n/query-builder.eo.js
new file mode 100644
index 00000000..6e66521d
--- /dev/null
+++ b/dist/i18n/query-builder.eo.js
@@ -0,0 +1,83 @@
+/*!
+ * jQuery QueryBuilder 3.0.0
+ * Locale: Esperanto (eo)
+ * Author: Robin van der Vliet, https://robinvandervliet.com/
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['eo'] = {
+ "__locale": "Esperanto (eo)",
+ "__author": "Robin van der Vliet, https://robinvandervliet.com/",
+ "add_rule": "Aldoni regulon",
+ "add_group": "Aldoni grupon",
+ "delete_rule": "Forigi",
+ "delete_group": "Forigi",
+ "conditions": {
+ "AND": "KAJ",
+ "OR": "AŬ"
+ },
+ "operators": {
+ "equal": "estas egala al",
+ "not_equal": "ne estas egala al",
+ "in": "estas en",
+ "not_in": "ne estas en",
+ "less": "estas malpli ol",
+ "less_or_equal": "estas malpli ol aŭ egala al",
+ "greater": "estas pli ol",
+ "greater_or_equal": "estas pli ol aŭ egala al",
+ "between": "estas inter",
+ "not_between": "ne estas inter",
+ "begins_with": "komenciĝas per",
+ "not_begins_with": "ne komenciĝas per",
+ "contains": "enhavas",
+ "not_contains": "ne enhavas",
+ "ends_with": "finiĝas per",
+ "not_ends_with": "ne finiĝas per",
+ "is_empty": "estas malplena",
+ "is_not_empty": "ne estas malplena",
+ "is_null": "estas senvalora",
+ "is_not_null": "ne estas senvalora"
+ },
+ "errors": {
+ "no_filter": "Neniu filtrilo elektita",
+ "empty_group": "La grupo estas malplena",
+ "radio_empty": "Neniu valoro elektita",
+ "checkbox_empty": "Neniu valoro elektita",
+ "select_empty": "Neniu valoro elektita",
+ "string_empty": "Malplena valoro",
+ "string_exceed_min_length": "Devas enhavi pli ol {0} signojn",
+ "string_exceed_max_length": "Devas ne enhavi pli ol {0} signojn",
+ "string_invalid_format": "Nevalida strukturo ({0})",
+ "number_nan": "Ne estas nombro",
+ "number_not_integer": "Ne estas entjera nombro",
+ "number_not_double": "Ne estas reela nombro",
+ "number_exceed_min": "Devas esti pli ol {0}",
+ "number_exceed_max": "Devas esti malpli ol {0}",
+ "number_wrong_step": "Devas esti oblo de {0}",
+ "number_between_invalid": "Nevalidaj valoroj, {0} estas pli ol {1}",
+ "datetime_empty": "Malplena valoro",
+ "datetime_invalid": "Nevalida dato ({0})",
+ "datetime_exceed_min": "Devas esti post {0}",
+ "datetime_exceed_max": "Devas esti antaŭ {0}",
+ "datetime_between_invalid": "Nevalidaj valoroj, {0} estas post {1}",
+ "boolean_not_valid": "Ne estas bulea valoro",
+ "operator_not_multiple": "La operacio \"{1}\" ne akceptas plurajn valorojn"
+ },
+ "invert": "Inversigi",
+ "NOT": "NE"
+};
+
+QueryBuilder.defaults({ lang_code: 'eo' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.es.js b/dist/i18n/query-builder.es.js
index f50b90a4..ea94a3fd 100644
--- a/dist/i18n/query-builder.es.js
+++ b/dist/i18n/query-builder.es.js
@@ -1,12 +1,12 @@
/*!
- * jQuery QueryBuilder 2.3.0
+ * jQuery QueryBuilder 3.0.0
* Locale: Spanish (es)
* Author: "pyarza", "kddlb"
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
(function(root, factory) {
- if (typeof define === 'function' && define.amd) {
+ if (typeof define == 'function' && define.amd) {
define(['jquery', 'query-builder'], factory);
}
else {
@@ -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 0665c699..011758fd 100644
--- a/dist/i18n/query-builder.fa-IR.js
+++ b/dist/i18n/query-builder.fa-IR.js
@@ -1,12 +1,12 @@
/*!
- * jQuery QueryBuilder 2.3.0
+ * jQuery QueryBuilder 3.0.0
* Locale: Farsi (fa-ir)
* Author: Behzad Sedighzade, behzad.sedighzade@gmail.com
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
(function(root, factory) {
- if (typeof define === 'function' && define.amd) {
+ if (typeof define == 'function' && define.amd) {
define(['jquery', 'query-builder'], factory);
}
else {
@@ -17,7 +17,7 @@
var QueryBuilder = $.fn.queryBuilder;
-QueryBuilder.regional['fa-ir'] = {
+QueryBuilder.regional['fa-IR'] = {
"__locale": "Farsi (fa-ir)",
"__author": "Behzad Sedighzade, behzad.sedighzade@gmail.com",
"add_rule": "افزودن قاعده",
@@ -38,6 +38,7 @@ QueryBuilder.regional['fa-ir'] = {
"greater": "بزرگتر از",
"greater_or_equal": "بزرگتر یا مساوی با",
"between": "مابین",
+ "not_between": "مابین نباشد",
"begins_with": "شروع شود با",
"not_begins_with": "شروع نشود با",
"contains": "شامل شود",
@@ -70,9 +71,9 @@ QueryBuilder.regional['fa-ir'] = {
"datetime_exceed_min": "باید بعد از {0} باشد",
"datetime_exceed_max": "باید قبل از {0} باشد",
"boolean_not_valid": "مقدار دودویی وارد کنید",
- "operator_not_multiple": "اپراتور {0} نمی تواند چند مقدار قبول کند"
+ "operator_not_multiple": "اپراتور \"{1}\" نمی تواند چند مقدار قبول کند"
}
};
-QueryBuilder.defaults({ lang_code: 'fa-ir' });
+QueryBuilder.defaults({ lang_code: 'fa-IR' });
}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.fr.js b/dist/i18n/query-builder.fr.js
index 781947aa..39dc7303 100644
--- a/dist/i18n/query-builder.fr.js
+++ b/dist/i18n/query-builder.fr.js
@@ -1,12 +1,12 @@
/*!
- * jQuery QueryBuilder 2.3.0
+ * jQuery QueryBuilder 3.0.0
* Locale: French (fr)
* Author: Damien "Mistic" Sorel, http://www.strangeplanet.fr
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
(function(root, factory) {
- if (typeof define === 'function' && define.amd) {
+ if (typeof define == 'function' && define.amd) {
define(['jquery', 'query-builder'], factory);
}
else {
@@ -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",
@@ -66,14 +66,17 @@ QueryBuilder.regional['fr'] = {
"number_exceed_min": "Doit être plus grand que {0}",
"number_exceed_max": "Doit être plus petit que {0}",
"number_wrong_step": "Doit être un multiple de {0}",
+ "number_between_invalid": "Valeurs invalides, {0} est plus grand que {1}",
"datetime_empty": "Valeur vide",
"datetime_invalid": "Fomat de date invalide ({0})",
"datetime_exceed_min": "Doit être après {0}",
"datetime_exceed_max": "Doit être avant {0}",
+ "datetime_between_invalid": "Valeurs invalides, {0} est plus grand que {1}",
"boolean_not_valid": "N'est pas un booléen",
- "operator_not_multiple": "L'opérateur {0} ne peut utiliser plusieurs valeurs"
+ "operator_not_multiple": "L'opérateur \"{1}\" ne peut utiliser plusieurs valeurs"
},
- "invert": "Inverser"
+ "invert": "Inverser",
+ "NOT": "NON"
};
QueryBuilder.defaults({ lang_code: 'fr' });
diff --git a/dist/i18n/query-builder.he.js b/dist/i18n/query-builder.he.js
new file mode 100644
index 00000000..2e453775
--- /dev/null
+++ b/dist/i18n/query-builder.he.js
@@ -0,0 +1,81 @@
+/*!
+ * jQuery QueryBuilder 3.0.0
+ * Locale: Hebrew (he)
+ * Author: Kfir Stri https://github.com/kfirstri
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['he'] = {
+ "__locale": "Hebrew (he)",
+ "__author": "Kfir Stri https://github.com/kfirstri",
+ "add_rule": "הוסף כלל",
+ "add_group": "הוסף קבוצה",
+ "delete_rule": "מחק",
+ "delete_group": "מחק",
+ "conditions": {
+ "AND": "וגם",
+ "OR": "או"
+ },
+ "operators": {
+ "equal": "שווה ל",
+ "not_equal": "שונה מ",
+ "in": "חלק מ",
+ "not_in": "לא חלק מ",
+ "less": "פחות מ",
+ "less_or_equal": "פחות או שווה ל",
+ "greater": "גדול מ",
+ "greater_or_equal": "גדול או שווה ל",
+ "between": "בין",
+ "not_between": "לא בין",
+ "begins_with": "מתחיל ב",
+ "not_begins_with": "לא מתחיל ב",
+ "contains": "מכיל",
+ "not_contains": "לא מכיל",
+ "ends_with": "מסתיים ב",
+ "not_ends_with": "לא מסתיים ב",
+ "is_empty": "ריק",
+ "is_not_empty": "לא ריק",
+ "is_null": "חסר ערך",
+ "is_not_null": "לא חסר ערך"
+ },
+ "errors": {
+ "no_filter": "לא נבחרו מסננים",
+ "empty_group": "הקבוצה רירקה",
+ "radio_empty": "לא נבחר אף ערך",
+ "checkbox_empty": "לא נבחר אף ערך",
+ "select_empty": "לא נבחר אף ערך",
+ "string_empty": "חסר ערך",
+ "string_exceed_min_length": "המחרוזת חייבת להכיל לפחות {0} תווים",
+ "string_exceed_max_length": "המחרוזת לא יכולה להכיל יותר מ{0} תווים",
+ "string_invalid_format": "המחרוזת בפורמט שגוי ({0})",
+ "number_nan": "זהו לא מספר",
+ "number_not_integer": "המספר אינו מספר שלם",
+ "number_not_double": "המספר אינו מספר עשרוני",
+ "number_exceed_min": "המספר צריך להיות גדול מ {0}",
+ "number_exceed_max": "המספר צריך להיות קטן מ{0}",
+ "number_wrong_step": "המספר צריך להיות כפולה של {0}",
+ "datetime_empty": "תאריך ריק",
+ "datetime_invalid": "פורמט תאריך שגוי ({0})",
+ "datetime_exceed_min": "התאריך חייב להיות אחרי {0}",
+ "datetime_exceed_max": "התאריך חייב להיות לפני {0}",
+ "boolean_not_valid": "זהו לא בוליאני",
+ "operator_not_multiple": "האופרטור \"{1}\" לא יכול לקבל ערכים מרובים"
+ },
+ "invert": "הפוך שאילתא",
+ "NOT": "לא"
+};
+
+QueryBuilder.defaults({ lang_code: 'he' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.hu.js b/dist/i18n/query-builder.hu.js
new file mode 100644
index 00000000..323a9adc
--- /dev/null
+++ b/dist/i18n/query-builder.hu.js
@@ -0,0 +1,83 @@
+/*!
+ * jQuery QueryBuilder 3.0.0
+ * Locale: Hungarian - Magyar (hu)
+ * Author: Szabó Attila "Tailor993", https://www.tailor993.hu
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['hu'] = {
+ "__locale": "Hungarian - Magyar (hu)",
+ "__author": "Szabó Attila \"Tailor993\", https://www.tailor993.hu",
+ "add_rule": "Feltétel hozzáadása",
+ "add_group": "Csoport hozzáadása",
+ "delete_rule": "Feltétel törlése",
+ "delete_group": "Csoport törlése",
+ "conditions": {
+ "AND": "ÉS",
+ "OR": "VAGY"
+ },
+ "operators": {
+ "equal": "egyenlő",
+ "not_equal": "nem egyenlő",
+ "in": "bennevan",
+ "not_in": "nincs benne",
+ "less": "kisebb",
+ "less_or_equal": "kisebb vagy egyenlő",
+ "greater": "nagyobb",
+ "greater_or_equal": "nagyobb vagy egyenlő",
+ "between": "közötte",
+ "not_between": "nincs közötte",
+ "begins_with": "ezzel kezdődik",
+ "not_begins_with": "ezzel nem kezdődik",
+ "contains": "tartalmazza",
+ "not_contains": "nem tartalmazza",
+ "ends_with": "erre végződik",
+ "not_ends_with": "errre nem végződik",
+ "is_empty": "üres",
+ "is_not_empty": "nem üres",
+ "is_null": "null",
+ "is_not_null": "nem null"
+ },
+ "errors": {
+ "no_filter": "Nincs kiválasztott feltétel",
+ "empty_group": "A csoport üres",
+ "radio_empty": "Nincs kiválasztott érték",
+ "checkbox_empty": "Nincs kiválasztott érték",
+ "select_empty": "Nincs kiválasztott érték",
+ "string_empty": "Üres érték",
+ "string_exceed_min_length": "A megadott szöveg rövidebb a várt {0} karakternél",
+ "string_exceed_max_length": "A megadott szöveg nem tartalmazhat többet, mint {0} karaktert",
+ "string_invalid_format": "Nem megfelelő formátum ({0})",
+ "number_nan": "Nem szám",
+ "number_not_integer": "Nem egész szám (integer)",
+ "number_not_double": "Nem valós szám",
+ "number_exceed_min": "Nagyobbnak kell lennie, mint {0}",
+ "number_exceed_max": "Kisebbnek kell lennie, mint {0}",
+ "number_wrong_step": "{0} többszörösének kell lennie.",
+ "number_between_invalid": "INem megfelelő érték, {0} nagyobb, mint {1}",
+ "datetime_empty": "Üres érték",
+ "datetime_invalid": "nem megfelelő dátum formátum ({0})",
+ "datetime_exceed_min": "A dátumnak későbbinek kell lennie, mint{0}",
+ "datetime_exceed_max": "A dátumnak korábbinak kell lennie, mint {0}",
+ "datetime_between_invalid": "Nem megfelelő értékek, {0} nagyobb, mint {1}",
+ "boolean_not_valid": "Nem igaz/hamis (boolean)",
+ "operator_not_multiple": "Ez a művelet: \"{1}\" nem fogadhat el több értéket"
+ },
+ "invert": "Megfordítás (Invertálás)",
+ "NOT": "NEM"
+};
+
+QueryBuilder.defaults({ lang_code: 'hu' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.it.js b/dist/i18n/query-builder.it.js
index 3fa33305..c4565e96 100644
--- a/dist/i18n/query-builder.it.js
+++ b/dist/i18n/query-builder.it.js
@@ -1,11 +1,12 @@
/*!
- * jQuery QueryBuilder 2.3.0
+ * jQuery QueryBuilder 3.0.0
* Locale: Italian (it)
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * Author: davegraziosi, Giuseppe Lodi Rizzini
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
(function(root, factory) {
- if (typeof define === 'function' && define.amd) {
+ if (typeof define == 'function' && define.amd) {
define(['jquery', 'query-builder'], factory);
}
else {
@@ -18,6 +19,7 @@ var QueryBuilder = $.fn.queryBuilder;
QueryBuilder.regional['it'] = {
"__locale": "Italian (it)",
+ "__author": "davegraziosi, Giuseppe Lodi Rizzini",
"add_rule": "Aggiungi regola",
"add_group": "Aggiungi gruppo",
"delete_rule": "Elimina",
@@ -35,6 +37,8 @@ QueryBuilder.regional['it'] = {
"less_or_equal": "minore o uguale",
"greater": "maggiore",
"greater_or_equal": "maggiore o uguale",
+ "between": "compreso tra",
+ "not_between": "non compreso tra",
"begins_with": "inizia con",
"not_begins_with": "non inizia con",
"contains": "contiene",
@@ -45,6 +49,31 @@ QueryBuilder.regional['it'] = {
"is_not_empty": "non è vuoto",
"is_null": "è nullo",
"is_not_null": "non è nullo"
+ },
+ "errors": {
+ "no_filter": "Nessun filtro selezionato",
+ "empty_group": "Il gruppo è vuoto",
+ "radio_empty": "No value selected",
+ "checkbox_empty": "Nessun valore selezionato",
+ "select_empty": "Nessun valore selezionato",
+ "string_empty": "Valore vuoto",
+ "string_exceed_min_length": "Deve contenere almeno {0} caratteri",
+ "string_exceed_max_length": "Non deve contenere più di {0} caratteri",
+ "string_invalid_format": "Formato non valido ({0})",
+ "number_nan": "Non è un numero",
+ "number_not_integer": "Non è un intero",
+ "number_not_double": "Non è un numero con la virgola",
+ "number_exceed_min": "Deve essere maggiore di {0}",
+ "number_exceed_max": "Deve essere minore di {0}",
+ "number_wrong_step": "Deve essere multiplo di {0}",
+ "number_between_invalid": "Valori non validi, {0} è maggiore di {1}",
+ "datetime_empty": "Valore vuoto",
+ "datetime_invalid": "Formato data non valido ({0})",
+ "datetime_exceed_min": "Deve essere successivo a {0}",
+ "datetime_exceed_max": "Deve essere precedente a {0}",
+ "datetime_between_invalid": "Valori non validi, {0} è maggiore di {1}",
+ "boolean_not_valid": "Non è un booleano",
+ "operator_not_multiple": "L'Operatore {0} non può accettare valori multipli"
}
};
diff --git a/dist/i18n/query-builder.lt.js b/dist/i18n/query-builder.lt.js
new file mode 100644
index 00000000..5d0324ab
--- /dev/null
+++ b/dist/i18n/query-builder.lt.js
@@ -0,0 +1,83 @@
+/*!
+ * jQuery QueryBuilder 3.0.0
+ * Locale: Lithuanian (lt)
+ * Author: Dalius Guzauskas (aka Tichij), https://lt.linkedin.com/in/daliusg
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['lt'] = {
+ "__locale": "Lithuanian (lt)",
+ "__author": "Dalius Guzauskas (aka Tichij), https://lt.linkedin.com/in/daliusg",
+ "add_rule": "Pridėti taisyklę",
+ "add_group": "Pridėti grupę",
+ "delete_rule": "Ištrinti",
+ "delete_group": "Ištrinti",
+ "conditions": {
+ "AND": "IR",
+ "OR": "ARBA"
+ },
+ "operators": {
+ "equal": "lygu",
+ "not_equal": "nėra lygu",
+ "in": "iš nurodytų",
+ "not_in": "ne iš nurodytų",
+ "less": "mažiau",
+ "less_or_equal": "mažiau arba lygu",
+ "greater": "daugiau",
+ "greater_or_equal": "daugiau arba lygu",
+ "between": "tarp",
+ "not_between": "nėra tarp",
+ "begins_with": "prasideda",
+ "not_begins_with": "neprasideda",
+ "contains": "turi",
+ "not_contains": "neturi",
+ "ends_with": "baigiasi",
+ "not_ends_with": "nesibaigia",
+ "is_empty": "tuščia",
+ "is_not_empty": "ne tuščia",
+ "is_null": "neapibrėžta",
+ "is_not_null": "nėra neapibrėžta"
+ },
+ "errors": {
+ "no_filter": "Nepasirinktas filtras",
+ "empty_group": "Grupė tuščia",
+ "radio_empty": "Nepasirinkta reikšmė",
+ "checkbox_empty": "Nepasirinkta reikšmė",
+ "select_empty": "Nepasirinkta reikšmė",
+ "string_empty": "Tuščia reikšmė",
+ "string_exceed_min_length": "Turi būti bent {0} simbolių",
+ "string_exceed_max_length": "Turi būti ne daugiau kaip {0} simbolių",
+ "string_invalid_format": "Klaidingas formatas ({0})",
+ "number_nan": "Nėra skaičius",
+ "number_not_integer": "Ne sveikasis skaičius",
+ "number_not_double": "Ne realusis skaičius",
+ "number_exceed_min": "Turi būti daugiau už {0}",
+ "number_exceed_max": "Turi būti mažiau už {0}",
+ "number_wrong_step": "Turi būti {0} kartotinis",
+ "number_between_invalid": "Klaidingos reikšmės, {0} yra daugiau už {1}",
+ "datetime_empty": "Tuščia reikšmė",
+ "datetime_invalid": "Klaidingas datos formatas ({0})",
+ "datetime_exceed_min": "Turi būti po {0}",
+ "datetime_exceed_max": "Turi būti prieš {0}",
+ "datetime_between_invalid": "Klaidingos reikšmės, {0} yra daugiau už {1}",
+ "boolean_not_valid": "Nėra loginis tipas",
+ "operator_not_multiple": "Operatorius \"{1}\" negali priimti kelių reikšmių"
+ },
+ "invert": "Invertuoti",
+ "NOT": "NE"
+};
+
+QueryBuilder.defaults({ lang_code: 'lt' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.nl.js b/dist/i18n/query-builder.nl.js
index 5ccbc0a2..8e88ac56 100644
--- a/dist/i18n/query-builder.nl.js
+++ b/dist/i18n/query-builder.nl.js
@@ -1,12 +1,12 @@
/*!
- * jQuery QueryBuilder 2.3.0
+ * jQuery QueryBuilder 3.0.0
* Locale: Dutch (nl)
* Author: "Roywcm"
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
(function(root, factory) {
- if (typeof define === 'function' && define.amd) {
+ if (typeof define == 'function' && define.amd) {
define(['jquery', 'query-builder'], factory);
}
else {
@@ -38,6 +38,7 @@ QueryBuilder.regional['nl'] = {
"greater": "groter",
"greater_or_equal": "groter of gelijk",
"between": "tussen",
+ "not_between": "niet tussen",
"begins_with": "begint met",
"not_begins_with": "begint niet met",
"contains": "bevat",
diff --git a/dist/i18n/query-builder.no.js b/dist/i18n/query-builder.no.js
index a5f9e5d3..1ec2d013 100644
--- a/dist/i18n/query-builder.no.js
+++ b/dist/i18n/query-builder.no.js
@@ -1,12 +1,12 @@
/*!
- * jQuery QueryBuilder 2.3.0
+ * jQuery QueryBuilder 3.0.0
* Locale: Norwegian (no)
* Author: Jna Borup Coyle, github@coyle.dk
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
(function(root, factory) {
- if (typeof define === 'function' && define.amd) {
+ if (typeof define == 'function' && define.amd) {
define(['jquery', 'query-builder'], factory);
}
else {
diff --git a/dist/i18n/query-builder.pl.js b/dist/i18n/query-builder.pl.js
index a31b3c5d..c89d0316 100644
--- a/dist/i18n/query-builder.pl.js
+++ b/dist/i18n/query-builder.pl.js
@@ -1,12 +1,12 @@
/*!
- * jQuery QueryBuilder 2.3.0
+ * jQuery QueryBuilder 3.0.0
* Locale: Polish (pl)
* Author: Artur Smolarek
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
(function(root, factory) {
- if (typeof define === 'function' && define.amd) {
+ if (typeof define == 'function' && define.amd) {
define(['jquery', 'query-builder'], factory);
}
else {
@@ -25,8 +25,8 @@ QueryBuilder.regional['pl'] = {
"delete_rule": "Usuń",
"delete_group": "Usuń",
"conditions": {
- "AND": "AND",
- "OR": "OR"
+ "AND": "ORAZ",
+ "OR": "LUB"
},
"operators": {
"equal": "równa się",
@@ -71,7 +71,7 @@ QueryBuilder.regional['pl'] = {
"datetime_exceed_min": "Musi być po {0}",
"datetime_exceed_max": "Musi być przed {0}",
"boolean_not_valid": "Niepoprawna wartość logiczna",
- "operator_not_multiple": "Operator {0} nie przyjmuje wielu wartości"
+ "operator_not_multiple": "Operator \"{1}\" nie przyjmuje wielu wartości"
},
"invert": "Odwróć"
};
diff --git a/dist/i18n/query-builder.pt-BR.js b/dist/i18n/query-builder.pt-BR.js
index e1de3b57..a9b4fe59 100644
--- a/dist/i18n/query-builder.pt-BR.js
+++ b/dist/i18n/query-builder.pt-BR.js
@@ -1,12 +1,12 @@
/*!
- * jQuery QueryBuilder 2.3.0
+ * jQuery QueryBuilder 3.0.0
* Locale: Brazilian Portuguese (pr-BR)
- * Author: Leandro Gehlen, leandrogehlen@gmail.com
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * Author: Leandro Gehlen, leandrogehlen@gmail.com; Marcos Ferretti, marcosvferretti@gmail.com
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
(function(root, factory) {
- if (typeof define === 'function' && define.amd) {
+ if (typeof define == 'function' && define.amd) {
define(['jquery', 'query-builder'], factory);
}
else {
@@ -19,9 +19,9 @@ var QueryBuilder = $.fn.queryBuilder;
QueryBuilder.regional['pt-BR'] = {
"__locale": "Brazilian Portuguese (pr-BR)",
- "__author": "Leandro Gehlen, leandrogehlen@gmail.com",
+ "__author": "Leandro Gehlen, leandrogehlen@gmail.com; Marcos Ferretti, marcosvferretti@gmail.com",
"add_rule": "Nova Regra",
- "add_group": "Novo Gruop",
+ "add_group": "Novo Grupo",
"delete_rule": "Excluir",
"delete_group": "Excluir",
"conditions": {
@@ -37,7 +37,8 @@ QueryBuilder.regional['pt-BR'] = {
"less_or_equal": "Menor ou igual",
"greater": "Maior",
"greater_or_equal": "Maior ou igual",
- "between": "entre",
+ "between": "Entre",
+ "not_between": "Não entre",
"begins_with": "Iniciando com",
"not_begins_with": "Não iniciando com",
"contains": "Contém",
@@ -57,7 +58,7 @@ QueryBuilder.regional['pt-BR'] = {
"select_empty": "Nenhum valor selecionado",
"string_empty": "Valor vazio",
"string_exceed_min_length": "É necessário conter pelo menos {0} caracteres",
- "string_exceed_max_length": "É necessário conterm mais de {0} caracteres",
+ "string_exceed_max_length": "É necessário conter mais de {0} caracteres",
"string_invalid_format": "Formato inválido ({0})",
"number_nan": "Não é um número",
"number_not_integer": "Não é um número inteiro",
@@ -67,8 +68,12 @@ QueryBuilder.regional['pt-BR'] = {
"number_wrong_step": "É necessário ser múltiplo de {0}",
"datetime_invalid": "Formato de data inválido ({0})",
"datetime_exceed_min": "É necessário ser superior a {0}",
- "datetime_exceed_max": "É necessário ser inferior a {0}"
- }
+ "datetime_exceed_max": "É necessário ser inferior a {0}",
+ "datetime_empty": "Nenhuma data selecionada",
+ "boolean_not_valid": "Não é um valor booleano",
+ "operator_not_multiple": "O operador \"{1}\" não aceita valores múltiplos"
+ },
+ "invert": "Inverter"
};
QueryBuilder.defaults({ lang_code: 'pt-BR' });
diff --git a/dist/i18n/query-builder.pt-PT.js b/dist/i18n/query-builder.pt-PT.js
index 012b0d2e..1e0aa77f 100644
--- a/dist/i18n/query-builder.pt-PT.js
+++ b/dist/i18n/query-builder.pt-PT.js
@@ -1,12 +1,12 @@
/*!
- * jQuery QueryBuilder 2.3.0
+ * jQuery QueryBuilder 3.0.0
* Locale: Portuguese (pt-PT)
* Author: Miguel Guerreiro, migas.csi@gmail.com
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
(function(root, factory) {
- if (typeof define === 'function' && define.amd) {
+ if (typeof define == 'function' && define.amd) {
define(['jquery', 'query-builder'], factory);
}
else {
diff --git a/dist/i18n/query-builder.ro.js b/dist/i18n/query-builder.ro.js
index 1aec5644..a1ba7eda 100644
--- a/dist/i18n/query-builder.ro.js
+++ b/dist/i18n/query-builder.ro.js
@@ -1,12 +1,12 @@
/*!
- * jQuery QueryBuilder 2.3.0
+ * jQuery QueryBuilder 3.0.0
* Locale: Romanian (ro)
- * Author: ArianServ
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * Author: ArianServ, totpero
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
(function(root, factory) {
- if (typeof define === 'function' && define.amd) {
+ if (typeof define == 'function' && define.amd) {
define(['jquery', 'query-builder'], factory);
}
else {
@@ -19,7 +19,7 @@ var QueryBuilder = $.fn.queryBuilder;
QueryBuilder.regional['ro'] = {
"__locale": "Romanian (ro)",
- "__author": "ArianServ",
+ "__author": "ArianServ, totpero",
"add_rule": "Adaugă regulă",
"add_group": "Adaugă grup",
"delete_rule": "Şterge",
@@ -33,10 +33,12 @@ QueryBuilder.regional['ro'] = {
"not_equal": "diferit",
"in": "în",
"not_in": "nu în",
- "less": "mai puţin",
- "less_or_equal": "mai puţin sau egal",
+ "less": "mai mic",
+ "less_or_equal": "mai mic sau egal",
"greater": "mai mare",
"greater_or_equal": "mai mare sau egal",
+ "between": "între",
+ "not_between": "nu între",
"begins_with": "începe cu",
"not_begins_with": "nu începe cu",
"contains": "conţine",
@@ -47,6 +49,31 @@ QueryBuilder.regional['ro'] = {
"is_not_empty": "nu este gol",
"is_null": "e nul",
"is_not_null": "nu e nul"
+ },
+ "errors": {
+ "no_filter": "Nici un filtru selectat",
+ "empty_group": "Grupul este gol",
+ "radio_empty": "Nici o valoare nu este selectată",
+ "checkbox_empty": "Nici o valoare nu este selectată",
+ "select_empty": "Nici o valoare nu este selectată",
+ "string_empty": "Valoare goală",
+ "string_exceed_min_length": "Trebuie să conţină mai puţin de {0} caractere",
+ "string_exceed_max_length": "Trebuie să conţină mai mult de {0} caractere",
+ "string_invalid_format": "Format invalid ({0})",
+ "number_nan": "Nu este număr",
+ "number_not_integer": "Nu este număr întreg",
+ "number_not_double": "Nu este număr real",
+ "number_exceed_min": "Trebuie să fie mai mare decât {0}",
+ "number_exceed_max": "Trebuie să fie mai mic decât {0}",
+ "number_wrong_step": "Trebuie să fie multiplu de {0}",
+ "number_between_invalid": "Valori invalide, {0} este mai mare decât {1}",
+ "datetime_empty": "Valoare goală",
+ "datetime_invalid": "Format dată invalid ({0})",
+ "datetime_exceed_min": "Trebuie să fie după {0}",
+ "datetime_exceed_max": "Trebuie să fie înainte {0}",
+ "datetime_between_invalid": "Valori invalide, {0} este mai mare decât {1}",
+ "boolean_not_valid": "Nu este boolean",
+ "operator_not_multiple": "Operatorul \"{1}\" nu poate accepta mai multe valori"
}
};
diff --git a/dist/i18n/query-builder.ru.js b/dist/i18n/query-builder.ru.js
index 8e338007..03cc3b7c 100644
--- a/dist/i18n/query-builder.ru.js
+++ b/dist/i18n/query-builder.ru.js
@@ -1,11 +1,12 @@
/*!
- * jQuery QueryBuilder 2.3.0
+ * jQuery QueryBuilder 3.0.0
* Locale: Russian (ru)
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * Author:
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
(function(root, factory) {
- if (typeof define === 'function' && define.amd) {
+ if (typeof define == 'function' && define.amd) {
define(['jquery', 'query-builder'], factory);
}
else {
@@ -36,6 +37,7 @@ QueryBuilder.regional['ru'] = {
"greater": "больше",
"greater_or_equal": "больше или равно",
"between": "между",
+ "not_between": "не между",
"begins_with": "начинается с",
"not_begins_with": "не начинается с",
"contains": "содержит",
@@ -50,10 +52,10 @@ QueryBuilder.regional['ru'] = {
"errors": {
"no_filter": "Фильтр не выбран",
"empty_group": "Группа пуста",
- "radio_empty": "Не выбранно значение",
- "checkbox_empty": "Не выбранно значение",
- "select_empty": "Не выбранно значение",
- "string_empty": "Не заполненно",
+ "radio_empty": "Не выбрано значение",
+ "checkbox_empty": "Не выбрано значение",
+ "select_empty": "Не выбрано значение",
+ "string_empty": "Не заполнено",
"string_exceed_min_length": "Должен содержать больше {0} символов",
"string_exceed_max_length": "Должен содержать меньше {0} символов",
"string_invalid_format": "Неверный формат ({0})",
@@ -63,13 +65,17 @@ QueryBuilder.regional['ru'] = {
"number_exceed_min": "Должно быть больше {0}",
"number_exceed_max": "Должно быть меньше, чем {0}",
"number_wrong_step": "Должно быть кратно {0}",
- "datetime_empty": "Не заполненно",
+ "number_between_invalid": "Недопустимые значения, {0} больше {1}",
+ "datetime_empty": "Не заполнено",
"datetime_invalid": "Неверный формат даты ({0})",
"datetime_exceed_min": "Должно быть, после {0}",
"datetime_exceed_max": "Должно быть, до {0}",
+ "datetime_between_invalid": "Недопустимые значения, {0} больше {1}",
"boolean_not_valid": "Не логическое",
- "operator_not_multiple": "Оператор {0} не поддерживает много значений"
- }
+ "operator_not_multiple": "Оператор \"{1}\" не поддерживает много значений"
+ },
+ "invert": "Инвертировать",
+ "NOT": "НЕ"
};
QueryBuilder.defaults({ lang_code: 'ru' });
diff --git a/dist/i18n/query-builder.sk.js b/dist/i18n/query-builder.sk.js
new file mode 100644
index 00000000..d8ca2623
--- /dev/null
+++ b/dist/i18n/query-builder.sk.js
@@ -0,0 +1,83 @@
+/*!
+ * jQuery QueryBuilder 3.0.0
+ * Locale: Slovensky (sk)
+ * Author: k2s
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['sk'] = {
+ "__locale": "Slovensky (sk)",
+ "__author": "k2s",
+ "add_rule": "Pridať podmienku",
+ "add_group": "Pridať skupinu",
+ "delete_rule": "Zmazať",
+ "delete_group": "Zmazať",
+ "conditions": {
+ "AND": "A",
+ "OR": "ALEBO"
+ },
+ "operators": {
+ "equal": "rovné",
+ "not_equal": "nerovné",
+ "in": "v",
+ "not_in": "nie v",
+ "less": "menej",
+ "less_or_equal": "menej alebo rovné",
+ "greater": "väčšie",
+ "greater_or_equal": "väčšie alebo rovné",
+ "between": "medzi",
+ "not_between": "nie medzi",
+ "begins_with": "začína na",
+ "not_begins_with": "nezačína na",
+ "contains": "obsahuje",
+ "not_contains": "neobsahuje",
+ "ends_with": "končí na",
+ "not_ends_with": "nekončí na",
+ "is_empty": "je prázdne",
+ "is_not_empty": "nie je prázdne",
+ "is_null": "je null",
+ "is_not_null": "nie je null"
+ },
+ "errors": {
+ "no_filter": "Nie je zvolený filter",
+ "empty_group": "Skupina je prázdna",
+ "radio_empty": "Nie je označená hodnota",
+ "checkbox_empty": "Nie je označená hodnota",
+ "select_empty": "Nie je označená hodnota",
+ "string_empty": "Prázdna hodnota",
+ "string_exceed_min_length": "Musí obsahovať aspon {0} znakov",
+ "string_exceed_max_length": "Nesmie obsahovať viac ako {0} znakov",
+ "string_invalid_format": "Chybný formát ({0})",
+ "number_nan": "Nie je číslo",
+ "number_not_integer": "Nie je celé číslo",
+ "number_not_double": "Nie je desatinné číslo",
+ "number_exceed_min": "Musí byť väčšie ako {0}",
+ "number_exceed_max": "Musí byť menšie ako {0}",
+ "number_wrong_step": "Musí byť násobkom čísla {0}",
+ "number_between_invalid": "Chybné hodnoty, {0} je väčšie ako {1}",
+ "datetime_empty": "Prázdna hodnota",
+ "datetime_invalid": "Chybný formát dátumu ({0})",
+ "datetime_exceed_min": "Musí byť neskôr ako {0}",
+ "datetime_exceed_max": "Musí byť skôr ako {0}",
+ "datetime_between_invalid": "Chybné hodnoty, {0} je neskôr ako {1}",
+ "boolean_not_valid": "Neplatné áno/nie",
+ "operator_not_multiple": "Operátor '{1}' nepodporuje viacero hodnôt"
+ },
+ "invert": "Invertný",
+ "NOT": "NIE"
+};
+
+QueryBuilder.defaults({ lang_code: 'sk' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.sq.js b/dist/i18n/query-builder.sq.js
index bc96281f..f991b12a 100644
--- a/dist/i18n/query-builder.sq.js
+++ b/dist/i18n/query-builder.sq.js
@@ -1,12 +1,12 @@
/*!
- * jQuery QueryBuilder 2.3.0
+ * jQuery QueryBuilder 3.0.0
* Locale: Albanian (sq)
* Author: Tomor Pupovci
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
(function(root, factory) {
- if (typeof define === 'function' && define.amd) {
+ if (typeof define == 'function' && define.amd) {
define(['jquery', 'query-builder'], factory);
}
else {
@@ -70,7 +70,7 @@ QueryBuilder.regional['sq'] = {
"datetime_exceed_min": "Duhet të jetë pas {0}",
"datetime_exceed_max": "Duhet të jetë para {0}",
"boolean_not_valid": "Nuk është boolean",
- "operator_not_multiple": "Operatori {0} nuk mund të pranojë vlera të shumëfishta"
+ "operator_not_multiple": "Operatori \"{1}\" nuk mund të pranojë vlera të shumëfishta"
}
};
diff --git a/dist/i18n/query-builder.sv.js b/dist/i18n/query-builder.sv.js
new file mode 100644
index 00000000..715cebb5
--- /dev/null
+++ b/dist/i18n/query-builder.sv.js
@@ -0,0 +1,83 @@
+/*!
+ * jQuery QueryBuilder 3.0.0
+ * Locale: Svenska (sv)
+ * Author: hekin1
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['sv'] = {
+ "__locale": "Svenska (sv)",
+ "__author": "hekin1",
+ "add_rule": "Lägg till regel",
+ "add_group": "Lägg till grupp",
+ "delete_rule": "Ta bort",
+ "delete_group": "Ta bort",
+ "conditions": {
+ "AND": "OCH",
+ "OR": "ELLER"
+ },
+ "operators": {
+ "equal": "lika med",
+ "not_equal": "ej lika med",
+ "in": "en av",
+ "not_in": "ej en av",
+ "less": "mindre",
+ "less_or_equal": "mindre eller lika med",
+ "greater": "större",
+ "greater_or_equal": "större eller lika med",
+ "between": "mellan",
+ "not_between": "ej mellan",
+ "begins_with": "börjar med",
+ "not_begins_with": "börjar inte med",
+ "contains": "innehåller",
+ "not_contains": "innehåller inte",
+ "ends_with": "slutar med",
+ "not_ends_with": "slutar inte med",
+ "is_empty": "är tom",
+ "is_not_empty": "är inte tom",
+ "is_null": "är null",
+ "is_not_null": "är inte null"
+ },
+ "errors": {
+ "no_filter": "Inget filter valt",
+ "empty_group": "Gruppen är tom",
+ "radio_empty": "Inget värde valt",
+ "checkbox_empty": "Inget värde valt",
+ "select_empty": "Inget värde valt",
+ "string_empty": "Tomt värde",
+ "string_exceed_min_length": "Måste innehålla minst {0} tecken",
+ "string_exceed_max_length": "Får ej innehålla fler än {0} tecken",
+ "string_invalid_format": "Felaktigt format ({0})",
+ "number_nan": "Inte numeriskt",
+ "number_not_integer": "Inte en siffra",
+ "number_not_double": "Inte ett decimaltal",
+ "number_exceed_min": "Måste vara större än {0}",
+ "number_exceed_max": "Måste vara lägre än {0}",
+ "number_wrong_step": "Måste vara en mutipel av {0}",
+ "number_between_invalid": "Felaktiga värden, {0} är större än {1}",
+ "datetime_empty": "Tomt värde",
+ "datetime_invalid": "Felaktigt datumformat ({0})",
+ "datetime_exceed_min": "Måste vara efter {0}",
+ "datetime_exceed_max": "Måste vara före {0}",
+ "datetime_between_invalid": "Felaktiga värden, {0} är större än {1}",
+ "boolean_not_valid": "Inte en boolean",
+ "operator_not_multiple": "Operatorn \"{1}\" accepterar inte flera värden"
+ },
+ "invert": "Invertera",
+ "NOT": "INTE"
+};
+
+QueryBuilder.defaults({ lang_code: 'sv' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.sw.js b/dist/i18n/query-builder.sw.js
new file mode 100644
index 00000000..8829fc60
--- /dev/null
+++ b/dist/i18n/query-builder.sw.js
@@ -0,0 +1,83 @@
+/*!
+ * jQuery QueryBuilder 3.0.0
+ * Locale: Swahili (sw)
+ * Author: Timothy Anyona
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['sw'] = {
+ "__locale": "Swahili (sw)",
+ "__author": "Timothy Anyona",
+ "add_rule": "Ongeza kanuni",
+ "add_group": "Ongeza kikundi",
+ "delete_rule": "Futa",
+ "delete_group": "Futa",
+ "conditions": {
+ "AND": "NA",
+ "OR": "AU"
+ },
+ "operators": {
+ "equal": "ni",
+ "not_equal": "sio",
+ "in": "mojawapo ya",
+ "not_in": "sio mojawapo ya",
+ "less": "isiyozidi",
+ "less_or_equal": "isiyozidi au ni sawa na",
+ "greater": "inayozidi",
+ "greater_or_equal": "inayozidi au ni sawa na",
+ "between": "kati ya",
+ "not_between": "isiyo kati ya",
+ "begins_with": "inaanza na",
+ "not_begins_with": "isiyoanza na",
+ "contains": "ina",
+ "not_contains": "haina",
+ "ends_with": "inaisha na",
+ "not_ends_with": "isiyoisha na",
+ "is_empty": "ni tupu",
+ "is_not_empty": "sio tupu",
+ "is_null": "ni batili",
+ "is_not_null": "sio batili"
+ },
+ "errors": {
+ "no_filter": "Chujio halijachaguliwa",
+ "empty_group": "Kikundi ki tupu",
+ "radio_empty": "Thamani haijachaguliwa",
+ "checkbox_empty": "Thamani haijachaguliwa",
+ "select_empty": "Thamani haijachaguliwa",
+ "string_empty": "Thamani tupu",
+ "string_exceed_min_length": "Lazima iwe na vibambo visiopungua {0}",
+ "string_exceed_max_length": "Haifai kuwa na vibambo zaidi ya {0}",
+ "string_invalid_format": "Fomati batili ({0})",
+ "number_nan": "Sio nambari",
+ "number_not_integer": "Sio namba kamili",
+ "number_not_double": "Sio namba desimali",
+ "number_exceed_min": "Lazima iwe zaidi ya {0}",
+ "number_exceed_max": "Lazima iwe chini ya {0}",
+ "number_wrong_step": "Lazima iwe kigawe cha {0}",
+ "number_between_invalid": "Thamani batili, {0} ni kubwa kuliko {1}",
+ "datetime_empty": "Thamani tupu",
+ "datetime_invalid": "Fomati tarehe batili ({0})",
+ "datetime_exceed_min": "Lazima iwe baada ya {0}",
+ "datetime_exceed_max": "Lazima iwe kabla ya {0}",
+ "datetime_between_invalid": "Thamani batili, {0} ni baada ya {1}",
+ "boolean_not_valid": "Sio buleani",
+ "operator_not_multiple": "Opereta \"{1}\" haikubali thamani nyingi"
+ },
+ "invert": "Pindua",
+ "NOT": "SIO"
+};
+
+QueryBuilder.defaults({ lang_code: 'sw' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.tr.js b/dist/i18n/query-builder.tr.js
new file mode 100644
index 00000000..7751e423
--- /dev/null
+++ b/dist/i18n/query-builder.tr.js
@@ -0,0 +1,82 @@
+/*!
+ * jQuery QueryBuilder 3.0.0
+ * Locale: Turkish (tr)
+ * Author: Aykut Alpgiray Ateş
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['tr'] = {
+ "__locale": "Turkish (tr)",
+ "__author": "Aykut Alpgiray Ateş",
+ "add_rule": "Kural Ekle",
+ "add_group": "Grup Ekle",
+ "delete_rule": "Sil",
+ "delete_group": "Sil",
+ "conditions": {
+ "AND": "Ve",
+ "OR": "Veya"
+ },
+ "operators": {
+ "equal": "eşit",
+ "not_equal": "eşit değil",
+ "in": "içinde",
+ "not_in": "içinde değil",
+ "less": "küçük",
+ "less_or_equal": "küçük veya eşit",
+ "greater": "büyük",
+ "greater_or_equal": "büyük veya eşit",
+ "between": "arasında",
+ "not_between": "arasında değil",
+ "begins_with": "ile başlayan",
+ "not_begins_with": "ile başlamayan",
+ "contains": "içeren",
+ "not_contains": "içermeyen",
+ "ends_with": "ile biten",
+ "not_ends_with": "ile bitmeyen",
+ "is_empty": "boş ise",
+ "is_not_empty": "boş değil ise",
+ "is_null": "var ise",
+ "is_not_null": "yok ise"
+ },
+ "errors": {
+ "no_filter": "Bir filtre seçili değil",
+ "empty_group": "Grup bir eleman içermiyor",
+ "radio_empty": "Seçim yapılmalı",
+ "checkbox_empty": "Seçim yapılmalı",
+ "select_empty": "Seçim yapılmalı",
+ "string_empty": "Bir metin girilmeli",
+ "string_exceed_min_length": "En az {0} karakter girilmeli",
+ "string_exceed_max_length": "En fazla {0} karakter girilebilir",
+ "string_invalid_format": "Uyumsuz format ({0})",
+ "number_nan": "Sayı değil",
+ "number_not_integer": "Tam sayı değil",
+ "number_not_double": "Ondalıklı sayı değil",
+ "number_exceed_min": "Sayı {0}'den/dan daha büyük olmalı",
+ "number_exceed_max": "Sayı {0}'den/dan daha küçük olmalı",
+ "number_wrong_step": "{0} veya katı olmalı",
+ "number_between_invalid": "Geçersiz değerler, {0} değeri {1} değerinden büyük",
+ "datetime_empty": "Tarih Seçilmemiş",
+ "datetime_invalid": "Uygun olmayan tarih formatı ({0})",
+ "datetime_exceed_min": "{0} Tarihinden daha sonrası olmalı.",
+ "datetime_exceed_max": "{0} Tarihinden daha öncesi olmalı.",
+ "datetime_between_invalid": "Geçersiz değerler, {0} değeri {1} değerinden büyük",
+ "boolean_not_valid": "Değer Doğru/Yanlış(bool) olmalı",
+ "operator_not_multiple": "Operatör \"{1}\" birden fazla değer kabul etmiyor"
+ },
+ "invert": "Ters Çevir"
+};
+
+QueryBuilder.defaults({ lang_code: 'tr' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.ua.js b/dist/i18n/query-builder.ua.js
new file mode 100644
index 00000000..1238b26e
--- /dev/null
+++ b/dist/i18n/query-builder.ua.js
@@ -0,0 +1,79 @@
+/*!
+ * jQuery QueryBuilder 3.0.0
+ * Locale: Ukrainian (ua)
+ * Author: Megaplan, mborisv
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['ua'] = {
+ "__locale": "Ukrainian (ua)",
+ "__author": "Megaplan, mborisv ",
+ "add_rule": "Додати",
+ "add_group": "Додати групу",
+ "delete_rule": "Видалити",
+ "delete_group": "Видалити",
+ "conditions": {
+ "AND": "І",
+ "OR": "АБО"
+ },
+ "operators": {
+ "equal": "дорівнює",
+ "not_equal": "не дорівнює",
+ "in": "з вказаних",
+ "not_in": "не з вказаних",
+ "less": "менше",
+ "less_or_equal": "менше або дорівнюж",
+ "greater": "більше",
+ "greater_or_equal": "більше або дорівнює",
+ "between": "між",
+ "begins_with": "починається з",
+ "not_begins_with": "не починається з",
+ "contains": "містить",
+ "not_contains": "не містить",
+ "ends_with": "закінчується на",
+ "not_ends_with": "не не закінчується на",
+ "is_empty": "порожній рядок",
+ "is_not_empty": "не порожній рядок",
+ "is_null": "порожньо",
+ "is_not_null": "не порожньо"
+ },
+ "errors": {
+ "no_filter": "Фільтр не вибраний",
+ "empty_group": "Група порожня",
+ "radio_empty": "Значення не вибрано",
+ "checkbox_empty": "Значення не вибрано",
+ "select_empty": "Значення не вибрано",
+ "string_empty": "Не заповнено",
+ "string_exceed_min_length": "Повинен містити більше {0} символів",
+ "string_exceed_max_length": "Повинен містити менше {0} символів",
+ "string_invalid_format": "Невірний формат ({0})",
+ "number_nan": "Не число",
+ "number_not_integer": "Не число",
+ "number_not_double": "Не число",
+ "number_exceed_min": "Повинне бути більше {0}",
+ "number_exceed_max": "Повинне бути менше, ніж {0}",
+ "number_wrong_step": "Повинне бути кратне {0}",
+ "datetime_empty": "Не заповнено",
+ "datetime_invalid": "Невірний формат дати ({0})",
+ "datetime_exceed_min": "Повинне бути, після {0}",
+ "datetime_exceed_max": "Повинне бути, до {0}",
+ "boolean_not_valid": "Не логічне",
+ "operator_not_multiple": "Оператор \"{1}\" не підтримує багато значень"
+ },
+ "invert": "інвертувати"
+};
+
+QueryBuilder.defaults({ lang_code: 'ua' });
+}));
\ No newline at end of file
diff --git a/dist/i18n/query-builder.zh-CN.js b/dist/i18n/query-builder.zh-CN.js
new file mode 100644
index 00000000..d908f33a
--- /dev/null
+++ b/dist/i18n/query-builder.zh-CN.js
@@ -0,0 +1,80 @@
+/*!
+ * jQuery QueryBuilder 3.0.0
+ * Locale: Simplified Chinese (zh_CN)
+ * Author: shadowwind, shatteredwindgo@gmail.com
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
+ */
+
+(function(root, factory) {
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'query-builder'], factory);
+ }
+ else {
+ factory(root.jQuery);
+ }
+}(this, function($) {
+"use strict";
+
+var QueryBuilder = $.fn.queryBuilder;
+
+QueryBuilder.regional['zh-CN'] = {
+ "__locale": "Simplified Chinese (zh_CN)",
+ "__author": "shadowwind, shatteredwindgo@gmail.com",
+ "add_rule": "添加规则",
+ "add_group": "添加组",
+ "delete_rule": "删除",
+ "delete_group": "删除组",
+ "conditions": {
+ "AND": "和",
+ "OR": "或"
+ },
+ "operators": {
+ "equal": "等于",
+ "not_equal": "不等于",
+ "in": "在...之內",
+ "not_in": "不在...之內",
+ "less": "小于",
+ "less_or_equal": "小于或等于",
+ "greater": "大于",
+ "greater_or_equal": "大于或等于",
+ "between": "在...之间",
+ "not_between": "不在...之间",
+ "begins_with": "以...开始",
+ "not_begins_with": "不以...开始",
+ "contains": "包含以下内容",
+ "not_contains": "不包含以下内容",
+ "ends_with": "以...结束",
+ "not_ends_with": "不以...结束",
+ "is_empty": "为空",
+ "is_not_empty": "不为空",
+ "is_null": "为 null",
+ "is_not_null": "不为 null"
+ },
+ "errors": {
+ "no_filter": "没有选择过滤器",
+ "empty_group": "该组为空",
+ "radio_empty": "没有选中项",
+ "checkbox_empty": "没有选中项",
+ "select_empty": "没有选中项",
+ "string_empty": "没有输入值",
+ "string_exceed_min_length": "必须至少包含{0}个字符",
+ "string_exceed_max_length": "必须不超过{0}个字符",
+ "string_invalid_format": "无效格式({0})",
+ "number_nan": "值不是数字",
+ "number_not_integer": "不是整数",
+ "number_not_double": "不是浮点数",
+ "number_exceed_min": "必须大于{0}",
+ "number_exceed_max": "必须小于{0}",
+ "number_wrong_step": "必须是{0}的倍数",
+ "datetime_empty": "值为空",
+ "datetime_invalid": "不是有效日期({0})",
+ "datetime_exceed_min": "必须在{0}之后",
+ "datetime_exceed_max": "必须在{0}之前",
+ "boolean_not_valid": "不是布尔值",
+ "operator_not_multiple": "选项\"{1}\"无法接受多个值"
+ },
+ "invert": "倒置"
+};
+
+QueryBuilder.defaults({ lang_code: 'zh-CN' });
+}));
\ No newline at end of file
diff --git a/dist/js/query-builder.js b/dist/js/query-builder.js
index 00a8a34c..b5b30837 100644
--- a/dist/js/query-builder.js
+++ b/dist/js/query-builder.js
@@ -1,44 +1,174 @@
/*!
- * jQuery QueryBuilder 2.3.0
- * Copyright 2014-2015 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
- * Licensed under MIT (http://opensource.org/licenses/MIT)
+ * jQuery QueryBuilder 3.0.0
+ * Copyright 2014-2024 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
+ * Licensed under MIT (https://opensource.org/licenses/MIT)
*/
-// Languages: en
-// Plugins: bt-checkbox, bt-selectpicker, bt-tooltip-errors, change-filters, filter-description, invert, mongodb-support, sortable, sql-support, unique-filter
(function(root, factory) {
- if (typeof define === 'function' && define.amd) {
- define(['jquery', 'doT', 'jQuery.extendext'], factory);
+ if (typeof define == 'function' && define.amd) {
+ define(['jquery', 'jquery-extendext'], factory);
+ }
+ else if (typeof module === 'object' && module.exports) {
+ module.exports = factory(require('jquery'), require('jquery-extendext'));
}
else {
- factory(root.jQuery, root.doT);
+ factory(root.jQuery);
}
-}(this, function($, doT) {
+}(this, function($) {
"use strict";
-// CLASS DEFINITION
-// ===============================
+/**
+ * @typedef {object} Filter
+ * @memberof QueryBuilder
+ * @description See {@link http://querybuilder.js.org/index.html#filters}
+ */
+
+/**
+ * @typedef {object} Operator
+ * @memberof QueryBuilder
+ * @description See {@link http://querybuilder.js.org/index.html#operators}
+ */
+
+/**
+ * @param {jQuery} $el
+ * @param {object} options - see {@link http://querybuilder.js.org/#options}
+ * @constructor
+ */
var QueryBuilder = function($el, options) {
- this.init($el, options);
-};
+ $el[0].queryBuilder = this;
+ /**
+ * Element container
+ * @member {jQuery}
+ * @readonly
+ */
+ this.$el = $el;
-// EVENTS SYSTEM
-// ===============================
-$.extend(QueryBuilder.prototype, {
- change: function(type, value) {
- var event = new $.Event(type + '.queryBuilder.filter', {
- builder: this,
- value: value
- });
+ /**
+ * Configuration object
+ * @member {object}
+ * @readonly
+ */
+ this.settings = $.extendext(true, 'replace', {}, QueryBuilder.DEFAULTS, options);
- this.$el.triggerHandler(event, Array.prototype.slice.call(arguments, 2));
+ /**
+ * Internal model
+ * @member {Model}
+ * @readonly
+ */
+ this.model = new Model();
- return event.value;
- },
+ /**
+ * Internal status
+ * @member {object}
+ * @property {string} id - id of the container
+ * @property {boolean} generated_id - if the container id has been generated
+ * @property {int} group_id - current group id
+ * @property {int} rule_id - current rule id
+ * @property {boolean} has_optgroup - if filters have optgroups
+ * @property {boolean} has_operator_optgroup - if operators have optgroups
+ * @readonly
+ * @private
+ */
+ this.status = {
+ id: null,
+ generated_id: false,
+ group_id: 0,
+ rule_id: 0,
+ has_optgroup: false,
+ has_operator_optgroup: false
+ };
+
+ /**
+ * List of filters
+ * @member {QueryBuilder.Filter[]}
+ * @readonly
+ */
+ this.filters = this.settings.filters;
+
+ /**
+ * List of icons
+ * @member {object.}
+ * @readonly
+ */
+ this.icons = this.settings.icons;
+
+ /**
+ * List of operators
+ * @member {QueryBuilder.Operator[]}
+ * @readonly
+ */
+ this.operators = this.settings.operators;
+
+ /**
+ * List of templates
+ * @member {object.}
+ * @readonly
+ */
+ this.templates = this.settings.templates;
+
+ /**
+ * Plugins configuration
+ * @member {object.}
+ * @readonly
+ */
+ this.plugins = this.settings.plugins;
+
+ /**
+ * Translations object
+ * @member {object}
+ * @readonly
+ */
+ this.lang = null;
+
+ // translations : english << 'lang_code' << custom
+ if (QueryBuilder.regional['en'] === undefined) {
+ Utils.error('Config', '"i18n/en.js" not loaded.');
+ }
+ this.lang = $.extendext(true, 'replace', {}, QueryBuilder.regional['en'], QueryBuilder.regional[this.settings.lang_code], this.settings.lang);
+
+ // "allow_groups" can be boolean or int
+ if (this.settings.allow_groups === false) {
+ this.settings.allow_groups = 0;
+ }
+ else if (this.settings.allow_groups === true) {
+ this.settings.allow_groups = -1;
+ }
+
+ // init templates
+ Object.keys(this.templates).forEach(function(tpl) {
+ if (!this.templates[tpl]) {
+ this.templates[tpl] = QueryBuilder.templates[tpl];
+ }
+ if (typeof this.templates[tpl] !== 'function') {
+ throw new Error(`Template ${tpl} must be a function`);
+ }
+ }, this);
+ // ensure we have a container id
+ if (!this.$el.attr('id')) {
+ this.$el.attr('id', 'qb_' + Math.floor(Math.random() * 99999));
+ this.status.generated_id = true;
+ }
+ this.status.id = this.$el.attr('id');
+
+ // INIT
+ this.$el.addClass('query-builder');
+
+ this.filters = this.checkFilters(this.filters);
+ this.operators = this.checkOperators(this.operators);
+ this.bindEvents();
+ this.initPlugins();
+};
+
+$.extend(QueryBuilder.prototype, /** @lends QueryBuilder.prototype */ {
+ /**
+ * Triggers an event on the builder container
+ * @param {string} type
+ * @returns {$.Event}
+ */
trigger: function(type) {
- var event = new $.Event(type + '.queryBuilder', {
+ var event = new $.Event(this._tojQueryEvent(type), {
builder: this
});
@@ -47,103 +177,76 @@ $.extend(QueryBuilder.prototype, {
return event;
},
+ /**
+ * Triggers an event on the builder container and returns the modified value
+ * @param {string} type
+ * @param {*} value
+ * @returns {*}
+ */
+ change: function(type, value) {
+ var event = new $.Event(this._tojQueryEvent(type, true), {
+ builder: this,
+ value: value
+ });
+
+ this.$el.triggerHandler(event, Array.prototype.slice.call(arguments, 2));
+
+ return event.value;
+ },
+
+ /**
+ * Attaches an event listener on the builder container
+ * @param {string} type
+ * @param {function} cb
+ * @returns {QueryBuilder}
+ */
on: function(type, cb) {
- this.$el.on(type + '.queryBuilder', cb);
+ this.$el.on(this._tojQueryEvent(type), cb);
return this;
},
+ /**
+ * Removes an event listener from the builder container
+ * @param {string} type
+ * @param {function} [cb]
+ * @returns {QueryBuilder}
+ */
off: function(type, cb) {
- this.$el.off(type + '.queryBuilder', cb);
+ this.$el.off(this._tojQueryEvent(type), cb);
return this;
},
+ /**
+ * Attaches an event listener called once on the builder container
+ * @param {string} type
+ * @param {function} cb
+ * @returns {QueryBuilder}
+ */
once: function(type, cb) {
- this.$el.one(type + '.queryBuilder', cb);
+ this.$el.one(this._tojQueryEvent(type), cb);
return this;
- }
-});
-
-
-// PLUGINS SYSTEM
-// ===============================
-QueryBuilder.plugins = {};
-
-/**
- * Get or extend the default configuration
- * @param options {object,optional} new configuration, leave undefined to get the default config
- * @return {undefined|object} nothing or configuration object (copy)
- */
-QueryBuilder.defaults = function(options) {
- if (typeof options == 'object') {
- $.extendext(true, 'replace', QueryBuilder.DEFAULTS, options);
- }
- else if (typeof options == 'string') {
- if (typeof QueryBuilder.DEFAULTS[options] == 'object') {
- return $.extend(true, {}, QueryBuilder.DEFAULTS[options]);
- }
- else {
- return QueryBuilder.DEFAULTS[options];
- }
- }
- else {
- return $.extend(true, {}, QueryBuilder.DEFAULTS);
- }
-};
-
-/**
- * Define a new plugin
- * @param {string}
- * @param {function}
- * @param {object,optional} default configuration
- */
-QueryBuilder.define = function(name, fct, def) {
- QueryBuilder.plugins[name] = {
- fct: fct,
- def: def || {}
- };
-};
-
-/**
- * Add new methods
- * @param {object}
- */
-QueryBuilder.extend = function(methods) {
- $.extend(QueryBuilder.prototype, methods);
-};
-
-/**
- * Init plugins for an instance
- */
-QueryBuilder.prototype.initPlugins = function() {
- if (!this.plugins) {
- return;
- }
+ },
- if ($.isArray(this.plugins)) {
- var tmp = {};
- this.plugins.forEach(function(plugin) {
- tmp[plugin] = null;
- });
- this.plugins = tmp;
+ /**
+ * Appends `.queryBuilder` and optionally `.filter` to the events names
+ * @param {string} name
+ * @param {boolean} [filter=false]
+ * @returns {string}
+ * @private
+ */
+ _tojQueryEvent: function(name, filter) {
+ return name.split(' ').map(function(type) {
+ return type + '.queryBuilder' + (filter ? '.filter' : '');
+ }).join(' ');
}
+});
- Object.keys(this.plugins).forEach(function(plugin) {
- if (plugin in QueryBuilder.plugins) {
- this.plugins[plugin] = $.extend(true, {},
- QueryBuilder.plugins[plugin].def,
- this.plugins[plugin] || {}
- );
-
- QueryBuilder.plugins[plugin].fct.call(this, this.plugins[plugin]);
- }
- else {
- Utils.error('Unable to find plugin "{0}"', plugin);
- }
- }, this);
-};
/**
* Allowed types and their internal representation
+ * @type {object.}
+ * @readonly
+ * @private
*/
QueryBuilder.types = {
'string': 'string',
@@ -157,9 +260,13 @@ QueryBuilder.types = {
/**
* Allowed inputs
+ * @type {string[]}
+ * @readonly
+ * @private
*/
QueryBuilder.inputs = [
'text',
+ 'number',
'textarea',
'radio',
'checkbox',
@@ -168,24 +275,31 @@ QueryBuilder.inputs = [
/**
* Runtime modifiable options with `setOptions` method
+ * @type {string[]}
+ * @readonly
+ * @private
*/
QueryBuilder.modifiable_options = [
'display_errors',
'allow_groups',
- 'allow_empty'
+ 'allow_empty',
+ 'default_condition',
+ 'default_filter'
];
/**
* CSS selectors for common components
+ * @type {object.}
+ * @readonly
*/
-var Selectors = QueryBuilder.selectors = {
+QueryBuilder.selectors = {
group_container: '.rules-group-container',
rule_container: '.rule-container',
filter_container: '.rule-filter-container',
operator_container: '.rule-operator-container',
value_container: '.rule-value-container',
error_container: '.error-container',
- condition_container: '.group-conditions',
+ condition_container: '.rules-group-header .group-conditions',
rule_header: '.rule-header',
group_header: '.rules-group-header',
@@ -206,22 +320,57 @@ var Selectors = QueryBuilder.selectors = {
};
/**
- * Template strings (see `template.js`)
+ * Template strings (see template.js)
+ * @type {object.}
+ * @readonly
*/
QueryBuilder.templates = {};
/**
- * Localized strings (see `i18n/`)
+ * Localized strings (see i18n/)
+ * @type {object.}
+ * @readonly
*/
QueryBuilder.regional = {};
+/**
+ * Default operators
+ * @type {object.}
+ * @readonly
+ */
+QueryBuilder.OPERATORS = {
+ equal: { type: 'equal', nb_inputs: 1, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean'] },
+ not_equal: { type: 'not_equal', nb_inputs: 1, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean'] },
+ in: { type: 'in', nb_inputs: 1, multiple: true, apply_to: ['string', 'number', 'datetime'] },
+ not_in: { type: 'not_in', nb_inputs: 1, multiple: true, apply_to: ['string', 'number', 'datetime'] },
+ less: { type: 'less', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime'] },
+ less_or_equal: { type: 'less_or_equal', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime'] },
+ greater: { type: 'greater', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime'] },
+ greater_or_equal: { type: 'greater_or_equal', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime'] },
+ between: { type: 'between', nb_inputs: 2, multiple: false, apply_to: ['number', 'datetime'] },
+ not_between: { type: 'not_between', nb_inputs: 2, multiple: false, apply_to: ['number', 'datetime'] },
+ begins_with: { type: 'begins_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ not_begins_with: { type: 'not_begins_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ contains: { type: 'contains', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ not_contains: { type: 'not_contains', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ ends_with: { type: 'ends_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ not_ends_with: { type: 'not_ends_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
+ is_empty: { type: 'is_empty', nb_inputs: 0, multiple: false, apply_to: ['string'] },
+ is_not_empty: { type: 'is_not_empty', nb_inputs: 0, multiple: false, apply_to: ['string'] },
+ is_null: { type: 'is_null', nb_inputs: 0, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean'] },
+ is_not_null: { type: 'is_not_null', nb_inputs: 0, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean'] }
+};
+
/**
* Default configuration
+ * @type {object}
+ * @readonly
*/
QueryBuilder.DEFAULTS = {
filters: [],
plugins: [],
+ sort_filters: false,
display_errors: true,
allow_groups: -1,
allow_empty: false,
@@ -229,6 +378,8 @@ QueryBuilder.DEFAULTS = {
default_condition: 'AND',
inputs_separator: ' , ',
select_placeholder: '------',
+ display_empty_filter: true,
+ default_filter: null,
optgroups: {},
default_rule_flags: {
@@ -238,116 +389,189 @@ QueryBuilder.DEFAULTS = {
no_delete: false
},
+ default_group_flags: {
+ condition_readonly: false,
+ no_add_rule: false,
+ no_add_group: false,
+ no_delete: false
+ },
+
templates: {
group: null,
rule: null,
filterSelect: null,
- operatorSelect: null
+ operatorSelect: null,
+ ruleValueSelect: null
},
lang_code: 'en',
lang: {},
operators: [
- {type: 'equal', nb_inputs: 1, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean']},
- {type: 'not_equal', nb_inputs: 1, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean']},
- {type: 'in', nb_inputs: 1, multiple: true, apply_to: ['string', 'number', 'datetime']},
- {type: 'not_in', nb_inputs: 1, multiple: true, apply_to: ['string', 'number', 'datetime']},
- {type: 'less', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime']},
- {type: 'less_or_equal', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime']},
- {type: 'greater', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime']},
- {type: 'greater_or_equal', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime']},
- {type: 'between', nb_inputs: 2, multiple: false, apply_to: ['number', 'datetime']},
- {type: 'not_between', nb_inputs: 2, multiple: false, apply_to: ['number', 'datetime']},
- {type: 'begins_with', nb_inputs: 1, multiple: false, apply_to: ['string']},
- {type: 'not_begins_with', nb_inputs: 1, multiple: false, apply_to: ['string']},
- {type: 'contains', nb_inputs: 1, multiple: false, apply_to: ['string']},
- {type: 'not_contains', nb_inputs: 1, multiple: false, apply_to: ['string']},
- {type: 'ends_with', nb_inputs: 1, multiple: false, apply_to: ['string']},
- {type: 'not_ends_with', nb_inputs: 1, multiple: false, apply_to: ['string']},
- {type: 'is_empty', nb_inputs: 0, multiple: false, apply_to: ['string']},
- {type: 'is_not_empty', nb_inputs: 0, multiple: false, apply_to: ['string']},
- {type: 'is_null', nb_inputs: 0, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean']},
- {type: 'is_not_null', nb_inputs: 0, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean']}
+ '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'
+ add_group: 'bi-plus-circle-fill',
+ add_rule: 'bi-plus-lg',
+ remove_group: 'bi-x-lg',
+ remove_rule: 'bi-x-lg',
+ error: 'bi-exclamation-triangle'
}
};
+
/**
- * Init the builder
+ * @module plugins
*/
-QueryBuilder.prototype.init = function($el, options) {
- $el[0].queryBuilder = this;
- this.$el = $el;
- // PROPERTIES
- this.settings = $.extendext(true, 'replace', {}, QueryBuilder.DEFAULTS, options);
- this.model = new Model();
- this.status = {
- group_id: 0,
- rule_id: 0,
- generated_id: false,
- has_optgroup: false,
- id: null,
- updating_value: false
- };
+/**
+ * Definition of available plugins
+ * @type {object.}
+ */
+QueryBuilder.plugins = {};
- // "allow_groups" can be boolean or int
- if (this.settings.allow_groups === false) {
- this.settings.allow_groups = 0;
+/**
+ * Gets or extends the default configuration
+ * @param {object} [options] - new configuration
+ * @returns {undefined|object} nothing or configuration object (copy)
+ */
+QueryBuilder.defaults = function(options) {
+ if (typeof options == 'object') {
+ $.extendext(true, 'replace', QueryBuilder.DEFAULTS, options);
}
- else if (this.settings.allow_groups === true) {
- this.settings.allow_groups = -1;
+ else if (typeof options == 'string') {
+ if (typeof QueryBuilder.DEFAULTS[options] == 'object') {
+ return $.extend(true, {}, QueryBuilder.DEFAULTS[options]);
+ }
+ else {
+ return QueryBuilder.DEFAULTS[options];
+ }
}
+ else {
+ return $.extend(true, {}, QueryBuilder.DEFAULTS);
+ }
+};
- // SETTINGS SHORTCUTS
- this.filters = this.settings.filters;
- this.icons = this.settings.icons;
- this.operators = this.settings.operators;
- this.templates = this.settings.templates;
- this.plugins = this.settings.plugins;
-
- // translations : english << 'lang_code' << custom
- if (QueryBuilder.regional['en'] === undefined) {
- Utils.error('"i18n/en.js" not loaded.');
+/**
+ * Registers a new plugin
+ * @param {string} name
+ * @param {function} fct - init function
+ * @param {object} [def] - default options
+ */
+QueryBuilder.define = function(name, fct, def) {
+ QueryBuilder.plugins[name] = {
+ fct: fct,
+ def: def || {}
+ };
+};
+
+/**
+ * Adds new methods to QueryBuilder prototype
+ * @param {object.} methods
+ */
+QueryBuilder.extend = function(methods) {
+ $.extend(QueryBuilder.prototype, methods);
+};
+
+/**
+ * Initializes plugins for an instance
+ * @throws ConfigError
+ * @private
+ */
+QueryBuilder.prototype.initPlugins = function() {
+ if (!this.plugins) {
+ return;
}
- this.lang = $.extendext(true, 'replace', {}, QueryBuilder.regional['en'], QueryBuilder.regional[this.settings.lang_code], this.settings.lang);
-
- // init templates
- Object.keys(this.templates).forEach(function(tpl) {
- if (!this.templates[tpl]) {
- this.templates[tpl] = QueryBuilder.templates[tpl];
+
+ if ($.isArray(this.plugins)) {
+ var tmp = {};
+ this.plugins.forEach(function(plugin) {
+ tmp[plugin] = null;
+ });
+ this.plugins = tmp;
+ }
+
+ Object.keys(this.plugins).forEach(function(plugin) {
+ if (plugin in QueryBuilder.plugins) {
+ this.plugins[plugin] = $.extend(true, {},
+ QueryBuilder.plugins[plugin].def,
+ this.plugins[plugin] || {}
+ );
+
+ QueryBuilder.plugins[plugin].fct.call(this, this.plugins[plugin]);
}
- if (typeof this.templates[tpl] == 'string') {
- this.templates[tpl] = doT.template(this.templates[tpl]);
+ else {
+ Utils.error('Config', 'Unable to find plugin "{0}"', plugin);
}
}, this);
+};
- // ensure we have a container id
- if (!this.$el.attr('id')) {
- this.$el.attr('id', 'qb_'+Math.floor(Math.random()*99999));
- this.status.generated_id = true;
+/**
+ * Returns the config of a plugin, if the plugin is not loaded, returns the default config.
+ * @param {string} name
+ * @param {string} [property]
+ * @throws ConfigError
+ * @returns {*}
+ */
+QueryBuilder.prototype.getPluginOptions = function(name, property) {
+ var plugin;
+ if (this.plugins && this.plugins[name]) {
+ plugin = this.plugins[name];
+ }
+ else if (QueryBuilder.plugins[name]) {
+ plugin = QueryBuilder.plugins[name].def;
}
- this.status.id = this.$el.attr('id');
- // INIT
- this.$el.addClass('query-builder form-inline');
+ if (plugin) {
+ if (property) {
+ return plugin[property];
+ }
+ else {
+ return plugin;
+ }
+ }
+ else {
+ Utils.error('Config', 'Unable to find plugin "{0}"', name);
+ }
+};
- this.filters = this.checkFilters(this.filters);
- this.bindEvents();
- this.initPlugins();
+/**
+ * Final initialisation of the builder
+ * @param {object} [rules]
+ * @fires QueryBuilder.afterInit
+ * @private
+ */
+QueryBuilder.prototype.init = function(rules) {
+ /**
+ * When the initilization is done, just before creating the root group
+ * @event afterInit
+ * @memberof QueryBuilder
+ */
this.trigger('afterInit');
- if (options.rules) {
- this.setRules(options.rules);
+ if (rules) {
+ this.setRules(rules);
delete this.settings.rules;
}
else {
@@ -357,20 +581,23 @@ QueryBuilder.prototype.init = function($el, options) {
/**
* Checks the configuration of each filter
+ * @param {QueryBuilder.Filter[]} filters
+ * @returns {QueryBuilder.Filter[]}
+ * @throws ConfigError
*/
QueryBuilder.prototype.checkFilters = function(filters) {
var definedFilters = [];
if (!filters || filters.length === 0) {
- Utils.error('Missing filters list');
+ Utils.error('Config', 'Missing filters list');
}
filters.forEach(function(filter, i) {
if (!filter.id) {
- Utils.error('Missing filter {0} id', i);
+ Utils.error('Config', 'Missing filter {0} id', i);
}
if (definedFilters.indexOf(filter.id) != -1) {
- Utils.error('Filter "{0}" already defined', filter.id);
+ Utils.error('Config', 'Filter "{0}" already defined', filter.id);
}
definedFilters.push(filter.id);
@@ -378,14 +605,22 @@ QueryBuilder.prototype.checkFilters = function(filters) {
filter.type = 'string';
}
else if (!QueryBuilder.types[filter.type]) {
- Utils.error('Invalid type "{0}"', filter.type);
+ Utils.error('Config', 'Invalid type "{0}"', filter.type);
}
if (!filter.input) {
- filter.input = 'text';
+ filter.input = QueryBuilder.types[filter.type] === 'number' ? 'number' : 'text';
}
else if (typeof filter.input != 'function' && QueryBuilder.inputs.indexOf(filter.input) == -1) {
- Utils.error('Invalid input "{0}"', filter.input);
+ Utils.error('Config', 'Invalid input "{0}"', filter.input);
+ }
+
+ if (filter.operators) {
+ filter.operators.forEach(function(operator) {
+ if (typeof operator != 'string') {
+ Utils.error('Config', 'Filter operators must be global operators types (string)');
+ }
+ });
}
if (!filter.field) {
@@ -401,115 +636,189 @@ QueryBuilder.prototype.checkFilters = function(filters) {
else {
this.status.has_optgroup = true;
- // backward compatiblity, register optgroup if needed
+ // register optgroup if needed
if (!this.settings.optgroups[filter.optgroup]) {
this.settings.optgroups[filter.optgroup] = filter.optgroup;
}
}
switch (filter.input) {
- case 'radio': case 'checkbox':
+ case 'radio':
+ case 'checkbox':
if (!filter.values || filter.values.length < 1) {
- Utils.error('Missing filter "{0}" values', filter.id);
+ Utils.error('Config', 'Missing filter "{0}" values', filter.id);
}
break;
case 'select':
+ var cleanValues = [];
+ filter.has_optgroup = false;
+
+ Utils.iterateOptions(filter.values, function(value, label, optgroup) {
+ cleanValues.push({
+ value: value,
+ label: label,
+ optgroup: optgroup || null
+ });
+
+ if (optgroup) {
+ filter.has_optgroup = true;
+
+ // register optgroup if needed
+ if (!this.settings.optgroups[optgroup]) {
+ this.settings.optgroups[optgroup] = optgroup;
+ }
+ }
+ }.bind(this));
+
+ if (filter.has_optgroup) {
+ filter.values = Utils.groupSort(cleanValues, 'optgroup');
+ }
+ else {
+ filter.values = cleanValues;
+ }
+
if (filter.placeholder) {
if (filter.placeholder_value === undefined) {
filter.placeholder_value = -1;
}
- Utils.iterateOptions(filter.values, function(key, val) {
- if (key == filter.placeholder_value) {
- Utils.error('Placeholder of filter "{0}" overlaps with one of its values', filter.id);
+
+ filter.values.forEach(function(entry) {
+ if (entry.value == filter.placeholder_value) {
+ Utils.error('Config', 'Placeholder of filter "{0}" overlaps with one of its values', filter.id);
}
});
}
break;
}
- }, this);
+ }, this);
+
+ if (this.settings.sort_filters) {
+ if (typeof this.settings.sort_filters == 'function') {
+ filters.sort(this.settings.sort_filters);
+ }
+ else {
+ var self = this;
+ filters.sort(function(a, b) {
+ return self.translate(a.label).localeCompare(self.translate(b.label));
+ });
+ }
+ }
- // group filters with same optgroup, preserving declaration order when possible
if (this.status.has_optgroup) {
- var optgroups = [],
- newFilters = [];
+ filters = Utils.groupSort(filters, 'optgroup');
+ }
- filters.forEach(function(filter, i) {
- var idx;
+ return filters;
+};
- if (filter.optgroup) {
- idx = optgroups.lastIndexOf(filter.optgroup);
+/**
+ * Checks the configuration of each operator
+ * @param {QueryBuilder.Operator[]} operators
+ * @returns {QueryBuilder.Operator[]}
+ * @throws ConfigError
+ */
+QueryBuilder.prototype.checkOperators = function(operators) {
+ var definedOperators = [];
- if (idx == -1) {
- idx = optgroups.length;
- }
- else {
- idx++;
- }
+ operators.forEach(function(operator, i) {
+ if (typeof operator == 'string') {
+ if (!QueryBuilder.OPERATORS[operator]) {
+ Utils.error('Config', 'Unknown operator "{0}"', operator);
}
- else {
- idx = optgroups.length;
+
+ operators[i] = operator = $.extendext(true, 'replace', {}, QueryBuilder.OPERATORS[operator]);
+ }
+ else {
+ if (!operator.type) {
+ Utils.error('Config', 'Missing "type" for operator {0}', i);
}
- optgroups.splice(idx, 0, filter.optgroup);
- newFilters.splice(idx, 0, filter);
- });
+ if (QueryBuilder.OPERATORS[operator.type]) {
+ operators[i] = operator = $.extendext(true, 'replace', {}, QueryBuilder.OPERATORS[operator.type], operator);
+ }
+
+ if (operator.nb_inputs === undefined || operator.apply_to === undefined) {
+ Utils.error('Config', 'Missing "nb_inputs" and/or "apply_to" for operator "{0}"', operator.type);
+ }
+ }
+
+ if (definedOperators.indexOf(operator.type) != -1) {
+ Utils.error('Config', 'Operator "{0}" already defined', operator.type);
+ }
+ definedOperators.push(operator.type);
- filters = newFilters;
+ if (!operator.optgroup) {
+ operator.optgroup = null;
+ }
+ else {
+ this.status.has_operator_optgroup = true;
+
+ // register optgroup if needed
+ if (!this.settings.optgroups[operator.optgroup]) {
+ this.settings.optgroups[operator.optgroup] = operator.optgroup;
+ }
+ }
+ }, this);
+
+ if (this.status.has_operator_optgroup) {
+ operators = Utils.groupSort(operators, 'optgroup');
}
- return filters;
+ return operators;
};
/**
- * Add all events listeners
+ * Adds all events listeners to the builder
+ * @private
*/
QueryBuilder.prototype.bindEvents = function() {
- var that = this;
+ var self = this;
+ var Selectors = QueryBuilder.selectors;
// group condition change
this.$el.on('change.queryBuilder', Selectors.group_condition, function() {
if ($(this).is(':checked')) {
var $group = $(this).closest(Selectors.group_container);
- Model($group).condition = $(this).val();
+ self.getModel($group).condition = $(this).val();
}
});
// rule filter change
this.$el.on('change.queryBuilder', Selectors.rule_filter, function() {
var $rule = $(this).closest(Selectors.rule_container);
- Model($rule).filter = that.getFilterById($(this).val());
+ self.getModel($rule).filter = self.getFilterById($(this).val());
});
// rule operator change
this.$el.on('change.queryBuilder', Selectors.rule_operator, function() {
var $rule = $(this).closest(Selectors.rule_container);
- Model($rule).operator = that.getOperatorByType($(this).val());
+ self.getModel($rule).operator = self.getOperatorByType($(this).val());
});
// add rule button
this.$el.on('click.queryBuilder', Selectors.add_rule, function() {
var $group = $(this).closest(Selectors.group_container);
- that.addRule(Model($group));
+ self.addRule(self.getModel($group));
});
// delete rule button
this.$el.on('click.queryBuilder', Selectors.delete_rule, function() {
var $rule = $(this).closest(Selectors.rule_container);
- that.deleteRule(Model($rule));
+ self.deleteRule(self.getModel($rule));
});
if (this.settings.allow_groups !== 0) {
// add group button
this.$el.on('click.queryBuilder', Selectors.add_group, function() {
var $group = $(this).closest(Selectors.group_container);
- that.addGroup(Model($group));
+ self.addGroup(self.getModel($group));
});
// delete group button
this.$el.on('click.queryBuilder', Selectors.delete_group, function() {
var $group = $(this).closest(Selectors.group_container);
- that.deleteGroup(Model($group));
+ self.deleteGroup(self.getModel($group));
});
}
@@ -517,67 +826,94 @@ QueryBuilder.prototype.bindEvents = function() {
this.model.on({
'drop': function(e, node) {
node.$el.remove();
+ self.refreshGroupsConditions();
+ },
+ 'add': function(e, parent, node, index) {
+ if (index === 0) {
+ node.$el.prependTo(parent.$el.find('>' + QueryBuilder.selectors.rules_list));
+ }
+ else {
+ node.$el.insertAfter(parent.rules[index - 1].$el);
+ }
+ self.refreshGroupsConditions();
},
- 'add': function(e, node, index) {
+ 'move': function(e, node, group, index) {
node.$el.detach();
if (index === 0) {
- node.$el.prependTo(node.parent.$el.find('>' + Selectors.rules_list));
+ node.$el.prependTo(group.$el.find('>' + QueryBuilder.selectors.rules_list));
}
else {
- node.$el.insertAfter(node.parent.rules[index-1].$el);
+ node.$el.insertAfter(group.rules[index - 1].$el);
}
+ self.refreshGroupsConditions();
},
'update': function(e, node, field, value, oldValue) {
- switch (field) {
- case 'error':
- that.displayError(node);
- break;
+ if (node instanceof Rule) {
+ switch (field) {
+ case 'error':
+ self.updateError(node);
+ break;
- case 'condition':
- that.updateGroupCondition(node);
- break;
+ case 'flags':
+ self.applyRuleFlags(node);
+ break;
- case 'filter':
- that.updateRuleFilter(node);
- break;
+ case 'filter':
+ self.updateRuleFilter(node, oldValue);
+ break;
- case 'operator':
- that.updateRuleOperator(node, oldValue);
- break;
+ case 'operator':
+ self.updateRuleOperator(node, oldValue);
+ break;
- case 'flags':
- that.applyRuleFlags(node);
- break;
+ case 'value':
+ self.updateRuleValue(node, oldValue);
+ break;
+ }
+ }
+ else {
+ switch (field) {
+ case 'error':
+ self.updateError(node);
+ break;
- case 'value':
- that.updateRuleValue(node);
- break;
+ case 'flags':
+ self.applyGroupFlags(node);
+ break;
+
+ case 'condition':
+ self.updateGroupCondition(node, oldValue);
+ break;
+ }
}
}
});
};
/**
- * Create the root group
- * @param addRule {bool,optional} add a default empty rule
- * @param data {mixed,optional} group custom data
- * @return group {Root}
+ * Creates the root group
+ * @param {boolean} [addRule=true] - adds a default empty rule
+ * @param {object} [data] - group custom data
+ * @param {object} [flags] - flags to apply to the group
+ * @returns {Group} root group
+ * @fires QueryBuilder.afterAddGroup
*/
-QueryBuilder.prototype.setRoot = function(addRule, data) {
+QueryBuilder.prototype.setRoot = function(addRule, data, flags) {
addRule = (addRule === undefined || addRule === true);
- var group_id = this.nextGroupId(),
- $group = $(this.getGroupTemplate(group_id, 1));
+ var group_id = this.nextGroupId();
+ var $group = $($.parseHTML(this.getGroupTemplate(group_id, 1)));
this.$el.append($group);
this.model.root = new Group(null, $group);
this.model.root.model = this.model;
+
+ this.model.root.data = data;
+ this.model.root.flags = $.extend({}, this.settings.default_group_flags, flags);
this.model.root.condition = this.settings.default_condition;
- if (data !== undefined) {
- this.model.root.data = data;
- }
+ this.trigger('afterAddGroup', this.model.root);
if (addRule) {
this.addRule(this.model.root);
@@ -587,33 +923,55 @@ QueryBuilder.prototype.setRoot = function(addRule, data) {
};
/**
- * Add a new group
- * @param parent {Group}
- * @param addRule {bool,optional} add a default empty rule
- * @param data {mixed,optional} group custom data
- * @return group {Group}
+ * Adds a new group
+ * @param {Group} parent
+ * @param {boolean} [addRule=true] - adds a default empty rule
+ * @param {object} [data] - group custom data
+ * @param {object} [flags] - flags to apply to the group
+ * @returns {Group}
+ * @fires QueryBuilder.beforeAddGroup
+ * @fires QueryBuilder.afterAddGroup
*/
-QueryBuilder.prototype.addGroup = function(parent, addRule, data) {
+QueryBuilder.prototype.addGroup = function(parent, addRule, data, flags) {
addRule = (addRule === undefined || addRule === true);
var level = parent.level + 1;
+ /**
+ * Just before adding a group, can be prevented.
+ * @event beforeAddGroup
+ * @memberof QueryBuilder
+ * @param {Group} parent
+ * @param {boolean} addRule - if an empty rule will be added in the group
+ * @param {int} level - nesting level of the group, 1 is the root group
+ */
var e = this.trigger('beforeAddGroup', parent, addRule, level);
if (e.isDefaultPrevented()) {
return null;
}
- var group_id = this.nextGroupId(),
- $group = $(this.getGroupTemplate(group_id, level)),
- model = parent.addGroup($group);
+ var group_id = this.nextGroupId();
+ var $group = $(this.getGroupTemplate(group_id, level));
+ var model = parent.addGroup($group);
- if (data !== undefined) {
- model.data = data;
- }
+ model.data = data;
+ model.flags = $.extend({}, this.settings.default_group_flags, flags);
+ model.condition = this.settings.default_condition;
+ /**
+ * Just after adding a group
+ * @event afterAddGroup
+ * @memberof QueryBuilder
+ * @param {Group} group
+ */
this.trigger('afterAddGroup', model);
- model.condition = this.settings.default_condition;
+ /**
+ * After any change in the rules
+ * @event rulesChanged
+ * @memberof QueryBuilder
+ */
+ this.trigger('rulesChanged');
if (addRule) {
this.addRule(model);
@@ -623,15 +981,23 @@ QueryBuilder.prototype.addGroup = function(parent, addRule, data) {
};
/**
- * Tries to delete a group. The group is not deleted if at least one rule is no_delete.
- * @param group {Group}
- * @return {boolean} true if the group has been deleted
+ * Tries to delete a group. The group is not deleted if at least one rule is flagged `no_delete`.
+ * @param {Group} group
+ * @returns {boolean} if the group has been deleted
+ * @fires QueryBuilder.beforeDeleteGroup
+ * @fires QueryBuilder.afterDeleteGroup
*/
QueryBuilder.prototype.deleteGroup = function(group) {
if (group.isRoot()) {
return false;
}
+ /**
+ * Just before deleting a group, can be prevented
+ * @event beforeDeleteGroup
+ * @memberof QueryBuilder
+ * @param {Group} parent
+ */
var e = this.trigger('beforeDeleteGroup', group);
if (e.isDefaultPrevented()) {
return false;
@@ -640,70 +1006,147 @@ QueryBuilder.prototype.deleteGroup = function(group) {
var del = true;
group.each('reverse', function(rule) {
- del&= this.deleteRule(rule);
+ del &= this.deleteRule(rule);
}, function(group) {
- del&= this.deleteGroup(group);
+ del &= this.deleteGroup(group);
}, this);
if (del) {
group.drop();
+
+ /**
+ * Just after deleting a group
+ * @event afterDeleteGroup
+ * @memberof QueryBuilder
+ */
this.trigger('afterDeleteGroup');
+
+ this.trigger('rulesChanged');
}
return del;
};
/**
- * Changes the condition of a group
- * @param group {Group}
+ * Performs actions when a group's condition changes
+ * @param {Group} group
+ * @param {object} previousCondition
+ * @fires QueryBuilder.afterUpdateGroupCondition
+ * @private
*/
-QueryBuilder.prototype.updateGroupCondition = function(group) {
- group.$el.find('>' + Selectors.group_condition).each(function() {
+QueryBuilder.prototype.updateGroupCondition = function(group, previousCondition) {
+ group.$el.find('>' + QueryBuilder.selectors.group_condition).each(function() {
var $this = $(this);
$this.prop('checked', $this.val() === group.condition);
$this.parent().toggleClass('active', $this.val() === group.condition);
});
- this.trigger('afterUpdateGroupCondition', group);
+ /**
+ * After the group condition has been modified
+ * @event afterUpdateGroupCondition
+ * @memberof QueryBuilder
+ * @param {Group} group
+ * @param {object} previousCondition
+ */
+ this.trigger('afterUpdateGroupCondition', group, previousCondition);
+
+ this.trigger('rulesChanged');
+};
+
+/**
+ * Updates the visibility of conditions based on number of rules inside each group
+ * @private
+ */
+QueryBuilder.prototype.refreshGroupsConditions = function() {
+ (function walk(group) {
+ if (!group.flags || (group.flags && !group.flags.condition_readonly)) {
+ group.$el.find('>' + QueryBuilder.selectors.group_condition).prop('disabled', group.rules.length <= 1)
+ .parent().toggleClass('disabled', group.rules.length <= 1);
+ }
+
+ group.each(null, function(group) {
+ walk(group);
+ }, this);
+ }(this.model.root));
};
/**
- * Add a new rule
- * @param parent {Group}
- * @param data {mixed,optional} rule custom data
- * @return rule {Rule}
+ * Adds a new rule
+ * @param {Group} parent
+ * @param {object} [data] - rule custom data
+ * @param {object} [flags] - flags to apply to the rule
+ * @returns {Rule}
+ * @fires QueryBuilder.beforeAddRule
+ * @fires QueryBuilder.afterAddRule
+ * @fires QueryBuilder.changer:getDefaultFilter
*/
-QueryBuilder.prototype.addRule = function(parent, data) {
+QueryBuilder.prototype.addRule = function(parent, data, flags) {
+ /**
+ * Just before adding a rule, can be prevented
+ * @event beforeAddRule
+ * @memberof QueryBuilder
+ * @param {Group} parent
+ */
var e = this.trigger('beforeAddRule', parent);
if (e.isDefaultPrevented()) {
return null;
}
- var rule_id = this.nextRuleId(),
- $rule = $(this.getRuleTemplate(rule_id)),
- model = parent.addRule($rule);
+ var rule_id = this.nextRuleId();
+ var $rule = $($.parseHTML(this.getRuleTemplate(rule_id)));
+ var model = parent.addRule($rule);
- if (data !== undefined) {
- model.data = data;
- }
+ model.data = data;
+ model.flags = $.extend({}, this.settings.default_rule_flags, flags);
+ /**
+ * Just after adding a rule
+ * @event afterAddRule
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ */
this.trigger('afterAddRule', model);
+ this.trigger('rulesChanged');
+
this.createRuleFilters(model);
+ if (this.settings.default_filter || !this.settings.display_empty_filter) {
+ /**
+ * Modifies the default filter for a rule
+ * @event changer:getDefaultFilter
+ * @memberof QueryBuilder
+ * @param {QueryBuilder.Filter} filter
+ * @param {Rule} rule
+ * @returns {QueryBuilder.Filter}
+ */
+ model.filter = this.change('getDefaultFilter',
+ this.getFilterById(this.settings.default_filter || this.filters[0].id),
+ model
+ );
+ }
+
return model;
};
/**
- * Delete a rule.
- * @param rule {Rule}
- * @return {boolean} true if the rule has been deleted
+ * Tries to delete a rule
+ * @param {Rule} rule
+ * @returns {boolean} if the rule has been deleted
+ * @fires QueryBuilder.beforeDeleteRule
+ * @fires QueryBuilder.afterDeleteRule
*/
QueryBuilder.prototype.deleteRule = function(rule) {
if (rule.flags.no_delete) {
return false;
}
+ /**
+ * Just before deleting a rule, can be prevented
+ * @event beforeDeleteRule
+ * @memberof QueryBuilder
+ * @param {Rule} rule
+ */
var e = this.trigger('beforeDeleteRule', rule);
if (e.isDefaultPrevented()) {
return false;
@@ -711,53 +1154,98 @@ QueryBuilder.prototype.deleteRule = function(rule) {
rule.drop();
+ /**
+ * Just after deleting a rule
+ * @event afterDeleteRule
+ * @memberof QueryBuilder
+ */
this.trigger('afterDeleteRule');
+ this.trigger('rulesChanged');
+
return true;
};
/**
- * Create the filters