diff --git a/src/defaults.js b/src/defaults.js index b6c5a5eb..380cb792 100644 --- a/src/defaults.js +++ b/src/defaults.js @@ -37,6 +37,7 @@ QueryBuilder.inputs = [ */ QueryBuilder.modifiable_options = [ 'display_errors', + 'read_only', 'allow_groups', 'allow_empty', 'default_condition', @@ -128,6 +129,7 @@ QueryBuilder.DEFAULTS = { sort_filters: false, display_errors: true, + read_only: false, allow_groups: -1, allow_empty: false, conditions: ['AND', 'OR'], diff --git a/src/main.js b/src/main.js index f799af6f..132355f3 100644 --- a/src/main.js +++ b/src/main.js @@ -140,6 +140,11 @@ var QueryBuilder = function($el, options) { this.operators = this.checkOperators(this.operators); this.bindEvents(); this.initPlugins(); + + // if read only, disable interative elements + if (this.settings.read_only) { + setTimeout(function () { $el.find(':input').prop('disabled', true)}); + } }; $.extend(QueryBuilder.prototype, /** @lends QueryBuilder.prototype */ { diff --git a/src/plugins/sortable/plugin.js b/src/plugins/sortable/plugin.js index 0d7dcaab..5110f900 100644 --- a/src/plugins/sortable/plugin.js +++ b/src/plugins/sortable/plugin.js @@ -51,6 +51,11 @@ QueryBuilder.define('sortable', function(options) { .draggable({ allowFrom: QueryBuilder.selectors.drag_handle, onstart: function(event) { + // ignore when readonly + if (e.builder.settings.read_only) { + return; + } + moved = false; // get model of dragged element @@ -72,11 +77,21 @@ QueryBuilder.define('sortable', function(options) { src.$el.hide(); }, onmove: function(event) { + // ignore when readonly + if (e.builder.settings.read_only) { + return; + } + // make the ghost follow the cursor ghost[0].style.top = event.clientY - 15 + 'px'; ghost[0].style.left = event.clientX - 15 + 'px'; }, onend: function(event) { + // ignore when readonly + if (e.builder.settings.read_only) { + return; + } + // starting from Interact 1.3.3, onend is called before ondrop if (event.dropzone) { moveSortableToTarget(src, $(event.relatedTarget), self); @@ -204,6 +219,11 @@ QueryBuilder.defaults({ * @private */ function moveSortableToTarget(node, target, builder) { + // ignore when readonly + if (builder.settings.read_only) { + return; + } + var parent, method; var Selectors = QueryBuilder.selectors; diff --git a/src/public.js b/src/public.js index 79491b96..92f493a8 100644 --- a/src/public.js +++ b/src/public.js @@ -52,6 +52,12 @@ QueryBuilder.prototype.reset = function() { this.addRule(this.model.root); + // if read only, disable interative elements + var $el = this.$el; + if (this.settings.read_only) { + setTimeout(function () { $el.find(':input').prop('disabled', true)}); + } + /** * After the {@link QueryBuilder#reset} method * @event afterReset @@ -105,6 +111,9 @@ QueryBuilder.prototype.setOptions = function(options) { $.each(options, function(opt, value) { if (QueryBuilder.modifiable_options.indexOf(opt) !== -1) { this.settings[opt] = value; + if (opt === 'read_only') { + this.$el.find(':input').prop('disabled', value); + } } }.bind(this)); }; diff --git a/src/template.js b/src/template.js index 004d4693..367984ab 100644 --- a/src/template.js +++ b/src/template.js @@ -2,16 +2,16 @@ QueryBuilder.templates.group = '\
\
\
\ - \ {{? it.settings.allow_groups===-1 || it.settings.allow_groups>=it.level }} \ - \ {{?}} \ {{? it.level>1 }} \ - \ {{?}} \ @@ -19,7 +19,7 @@ QueryBuilder.templates.group = '\
\ {{~ it.conditions: condition }} \ \ {{~}} \
\ @@ -36,7 +36,7 @@ QueryBuilder.templates.rule = '\
\
\
\ - \
\ @@ -51,7 +51,7 @@ QueryBuilder.templates.rule = '\ QueryBuilder.templates.filterSelect = '\ {{ var optgroup = null; }} \ - \ {{? it.settings.display_empty_filter }} \ \ {{?}} \ @@ -74,7 +74,7 @@ QueryBuilder.templates.operatorSelect = '\ \ {{?}} \ {{ var optgroup = null; }} \ - \ {{~ it.operators: operator }} \ {{? optgroup !== operator.optgroup }} \ {{? optgroup !== null }}{{?}} \ @@ -89,7 +89,7 @@ QueryBuilder.templates.operatorSelect = '\ QueryBuilder.templates.ruleValueSelect = '\ {{ var optgroup = null; }} \ - \ {{? it.rule.filter.placeholder }} \ \ {{?}} \