Introduction

QueryBuilder uses jQuery events and some piece of code from selectize.js to offer a plugins system.

Plugins can simply add public methods or make use of events to change the behavior of the builder.

Each plugin is a folder in the plugins directory, which contains at least a plugin.js file and optionally a plugin.scss file and a i18n folder. Everything needed for the plugin to operate must be contained in these two files (but third-party dependencies of course).

Plugins are included in the dist files by the Grunt task (depending on plugins build option) with everything needed for production (CommonJS factory, SCSS imports + CSS build), thus making plugin creation very easy.

plugin.js

API

QueryBuilder exposes some utilities to ease plugins creation, all available in the QueryBuilder variable.

defaults

Use QueryBuilder.defaults to extend the library configuration.

QueryBuilder.defaults({
  my_new_option: /* value */
});

QueryBuilder.defaults can also be used as a getter to return a copy of the default configuration.

var qb_defaults = QueryBuilder.defaults();

extend

QueryBuilder.extend is used to add new functions to the prototype of the library (eg: public methods).

QueryBuilder.extend({
  mySuperMethod: function() {
    /* do something */
  }
});

define

QueryBuilder.define is used to declare a plugin which will be initialized with the builder, optionally with a configuration object. It corresponds to plugins loaded with plugins option.

QueryBuilder.define('my_plugin', function(options) {
  /* "this" is the QueryBuilder instance */
}, {
  /* optional default plugin configuration */
});

"Standalone" plugin

The QueryBuilder variable is private to the CommonJS factory, thus you can't use it if you want to create a plugin which will not be included in the main build (separated JS/CSS files).
To solve this issue, use $.fn.queryBuilder instead.

Events system

What you will generally do in your plugin body is to bind callbacks to QueryBuilder events in order to modify default behavior. Callbacks are binded with the on method. Check this page for more information about the two types of events and a complete list of available events.

this.on('validationError', function(e, node, error, value) {
  /* do something when a validation error occurs */
});

this.on('getRuleTemplate.filter', function(e) {
  /* modify the rule HTML (e.value) */
});

Overwrite methods

If the events are not sufficient for you, you can still override existing QueryBuilder methods. You only need to access it from QueryBuilder.prototype ($.fn.queryBuilder.constructor.prototype for public access).

// keep a pointer to the original method
var originalInit = QueryBuilder.prototype.init;

// redefine the method
QueryBuilder.extend({
  init: function() {
    /* stuff */
    originalInit.call(this);
  }
});

plugin.scss

If your plugin needs additional CSS rules, you can add a .scss, file in the plugin directory, nor .css nor .sass files are allowed (of course you can use plain CSS in the SCSS file).

The plugins' SCSS files are imported at the end of the core SCSS, allowing you to use all defined variable. One interesting variable is $theme-name which contains... the theme name (currently "default" or "dark") you can use to make conditional formatting.

Basic SCSS from Filter Description plugin :
$description-text-color: #31708F;

@if $theme-name == 'dark' {
  $description-text-color: #AAD1E4;
}

.query-builder p.filter-description {
  color: $description-text-color;
}

Localization

If your plugin adds readable text you might want to enable translations for these text strings. This can be done by adding a i18n folder in your plugin directory, containing one .json file for each language. The translations you define here will be merged with the core translations at build time.

Example of plugin language file :
{
  "buttons": {
    "open": "Ouvrir",
    "close": "Fermer"
  }
}

Default translations

Don't forget to define the default translations (English) in the en.json file. It will be merged with the core translation by the Grunt task.

If your plugin is intended to be standalone, you can extend $.fn.queryBuilder.regional object instead, keys are language codes.