From d660e0e30ac9473d6717335f2edf1b9986230c55 Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Thu, 2 Jun 2011 01:04:52 +0000 Subject: [PATCH] filter rewrite, allow for nested conditions --- source/Ox.UI/js/Form/Ox.Filter.js | 359 ++++++++++++++++-------------- 1 file changed, 192 insertions(+), 167 deletions(-) diff --git a/source/Ox.UI/js/Form/Ox.Filter.js b/source/Ox.UI/js/Form/Ox.Filter.js index 79a617e7..a4339ef6 100644 --- a/source/Ox.UI/js/Form/Ox.Filter.js +++ b/source/Ox.UI/js/Form/Ox.Filter.js @@ -110,11 +110,6 @@ Ox.Filter = function(options, self) { float: 'left', }); - self.$buttons = []; - self.$conditions = $.map(self.options.query.conditions, function(condition, i) { - return constructCondition(condition, i); - }); - self.$limit = Ox.InputGroup({ inputs: [ Ox.Checkbox({ @@ -201,42 +196,38 @@ Ox.Filter = function(options, self) { ] }); - self.$items = Ox.merge([self.$operator], self.$conditions, [self.$limit, self.$view, self.$save]); + self.$items = [self.$operator, self.$limit, self.$view, self.$save]; self.$form = Ox.Form({ items: self.$items }); + renderConditions(); that.$element = self.$form.$element; - function addCondition(pos, isInGroup) { - var key = self.options.findKeys[0]; - self.options.query.conditions.splice(pos, 0, { - key: key.id, - value: '', - operator: self.conditionOperators[key.type][0].id - }); - self.$conditions.splice(pos, 0, constructCondition({}, pos, isInGroup)); - updateConditions(); - self.$form.addItem(pos + 1, self.$conditions[pos]); + function addCondition(pos, subpos, isGroup) { + subpos = Ox.isUndefined(subpos) ? -1 : subpos; + var key = self.options.findKeys[0], + condition = { + key: key.id, + value: '', + operator: self.conditionOperators[key.type][0].id + }; + if (isGroup) { + condition = { + conditions: [condition], + operator: self.options.query.operator == '&' ? '|' : '&' + }; + } + if (subpos == -1) { + self.options.query.conditions.splice(pos, 0, condition); + } else { + self.options.query.conditions[pos].conditions.splice(subpos, 0, condition); + } + renderConditions(); } - function addGroup(pos) { - self.$form.addItem(pos + 1, constructGroup(pos)); - self.options.query.conditions.splice(pos + 1, 0, { - conditions: [ - { - key: '?', - value: '?', - operator: '?' - } - ], - operator: '?' - }); - addCondition(pos + 1, true); - } - - function changeConditionKey(pos, key) { - Ox.print('changeConditionKey', pos, key); + function changeConditionKey(pos, subpos, key) { + Ox.print('changeConditionKey', pos, subpos, key); var oldOperator = self.options.query.conditions[pos].operator, oldType = Ox.getObjectById( self.options.findKeys, self.options.query.conditions[pos].key @@ -269,83 +260,15 @@ Ox.Filter = function(options, self) { that.$element.find('.OxGroupLabel').html(self.options.query.operator == '&' ? 'and' : 'or'); } - function constructButtons(isGroup, isInGroup) { - return Ox.merge([ - new Ox.Button({ - disabled: self.options.query.conditions.length == 1, - id: 'remove', - title: 'remove', - type: 'image' - }) - .css({margin: '0 4px 0 ' + (isGroup ? '264px' : '8px')}) - .bind({ - click: function() { - removeCondition($(this).parent().data('position')); - } - }), - Ox.Button({ - id: 'add', - title: 'add', - type: 'image' - }) - .css({margin: '0 ' + (isInGroup ? '0' : '4px') + ' 0 4px'}) - .bind({ - click: function() { - Ox.print('add', $(this).parent().data('position')) - addCondition($(this).parent().data('position') + 1) - } - }) - ], isInGroup ? [] : [ - Ox.Button({ - id: 'addgroup', - title: 'bracket', - type: 'image' - }) - .css({margin: '0 0 0 4px'}) - .bind({ - click: function() { - addGroup($(this).parent().data('position') + 1) - } - }) - ]); - } - - function constructCondition(condition, pos, isInGroup) { - var $condition = {}; - return $condition = Ox.FormElementGroup({ - elements: Ox.merge([ - Ox.Select({ - items: $.map(self.options.findKeys, function(key) { - return { - id: key.id, - title: key.title - }; - }), - //items: $.extend({}, self.options.findKeys), // fixme: Ox.Menu messes with keys - overlap: 'right', - width: 128 - }) - .bindEvent({ - change: function(event, data) { - Ox.print('event', event) - changeConditionKey($condition.data('position'), data.selected[0].id); - } - }), - constructConditionOperator(pos), - constructInput() - ], constructButtons(false, isInGroup)) - }) - .css({marginLeft: isInGroup ? '24px' : 0}) - .data({position: pos}); - } - - function constructConditionOperator(pos, selected) { + function constructConditionOperator(pos, subpos, selected) { + subpos = Ox.isUndefined(subpos) ? -1 : subpos; + Ox.print('constructConditionOperator', pos, subpos) + var condition = subpos == -1 + ? self.options.query.conditions[pos] + : self.options.query.conditions[pos].conditions[subpos]; return Ox.Select({ items: $.map(self.conditionOperators[getConditionType( - Ox.getObjectById( - self.options.findKeys, - self.options.query.conditions[pos].key - ).type + Ox.getObjectById(self.options.findKeys, condition.key).type )], function(operator) { return { checked: operator.id == selected, // fixme: should be "selected", not "checked" @@ -363,49 +286,8 @@ Ox.Filter = function(options, self) { }); } - function constructGroup() { - // fixme: duplicated - return Ox.FormElementGroup({ - elements: [ - Ox.Label({ - title: self.options.query.operator == '&' ? 'and' : 'or', - overlap: 'right', - width: 48 - }).addClass('OxGroupLabel'), - Ox.FormElementGroup({ - elements: Ox.merge([ - Ox.Select({ - items: $.map(self.operators, function(operator) { - return { - checked: operator.id != self.options.query.operator, - id: operator.id, - // fixme: should be operator.title, - // but is passed by reference to some select, - // which makes it an array - title: operator.title[0] - }; - }), - width: 48 - }) - .bindEvent({ - change: changeOperator - }), - Ox.Label({ - overlap: 'left', - title: 'of the following conditions', - width: 160 - }) - ], constructButtons(true)), - float: 'right', - width: 208 - }) - ], - float: 'left', - }); - } - function constructInput(isBetween) { - var $input + var $input; if (!isBetween) { $input = Ox.Input({ width: 288 @@ -417,17 +299,6 @@ Ox.Filter = function(options, self) { id: 'start', width: 128 }), - /* - Ox.TimeInput({ - id: 'start', - //seconds: true, - width: { - hours: 38, - minutes: 37, - seconds: 37 - } - }), - */ Ox.DateInput({ id: 'end', width: { @@ -453,16 +324,170 @@ Ox.Filter = function(options, self) { return type; } - function removeCondition(pos) { - self.options.query.conditions.splice(pos, 1); - self.$conditions.splice(pos, 1); - updateConditions(); - self.$form.removeItem(pos + 1); + function removeCondition(pos, subpos) { + Ox.print('removeCondition', pos, subpos) + subpos = Ox.isUndefined(subpos) ? -1 : subpos; + if (subpos == -1) { + self.options.query.conditions.splice(pos, 1); + } else { + self.options.query.conditions[pos].conditions.splice(subpos, 1); + } + renderConditions(); + } + + function renderButtons(pos, subpos) { + var isGroup = subpos == -1 && self.options.query.conditions[pos].conditions; + return Ox.merge([ + new Ox.Button({ + disabled: self.options.query.conditions.length == 1, + id: 'remove', + title: 'remove', + type: 'image' + }) + .css({margin: '0 4px 0 ' + (isGroup ? '296px' : '8px')}) + .bind({ + click: function() { + removeCondition( + $(this).parent().data('position'), + $(this).parent().data('subposition') + ); + } + }), + Ox.Button({ + id: 'add', + title: 'add', + type: 'image' + }) + .css({margin: '0 ' + (subpos == -1 ? '4px' : '0') + ' 0 4px'}) + .bind({ + click: function() { + if (subpos == -1) { + addCondition($(this).parent().data('position') + 1); + } else { + addCondition( + $(this).parent().data('position'), + $(this).parent().data('subposition') + 1 + ); + } + } + }) + ], subpos == -1 ? [ + Ox.Button({ + id: 'addgroup', + title: 'bracket', + type: 'image' + }) + .css({margin: '0 0 0 4px'}) + .bind({ + click: function() { + addCondition($(this).parent().data('position') + 1, -1, true) + } + }) + ] : []); + } + + function renderCondition(condition, pos, subpos) { + subpos = Ox.isUndefined(subpos) ? -1 : subpos; + Ox.print('renderCondition', condition, pos, subpos) + var $condition = Ox.FormElementGroup({ + elements: Ox.merge([ + Ox.Select({ + items: $.map(self.options.findKeys, function(key) { + return { + id: key.id, + title: key.title + }; + }), + //items: $.extend({}, self.options.findKeys), // fixme: Ox.Menu messes with keys + overlap: 'right', + width: 128 + }) + .bindEvent({ + change: function(event, data) { + Ox.print('event', event) + changeConditionKey( + $condition.data('position'), + $condition.data('subposition'), + data.selected[0].id + ); + } + }), + constructConditionOperator(pos, subpos), + constructInput() + ], renderButtons(pos, subpos)) + }) + .css({marginLeft: subpos == -1 ? 0 : '24px'}) + .data({position: pos, subpostion: subpos}); + return $condition; + } + + function renderConditions() { + Ox.print('renderConditions', self.options.query) + var $conditions = []; + while (self.$form.options('items').length > 4) { + self.$form.removeItem(1); + } + self.options.query.conditions.forEach(function(condition, pos) { + if (!condition.conditions) { + $conditions.push(renderCondition(condition, pos)); + } else { + $conditions.push(renderGroup(condition, pos)); + condition.conditions.forEach(function(subcondition, subpos) { + $conditions.push(renderCondition(subcondition, pos, subpos)); + }); + } + }); + $conditions.forEach(function($condition, pos) { + self.$form.addItem(1 + pos, $condition); + }); + } + + function renderGroup(condition, pos) { + var subpos = -1; + var $condition = Ox.FormElementGroup({ + elements: Ox.merge([ + Ox.Label({ + title: self.options.query.operator == '&' ? 'and' : 'or', + overlap: 'right', + width: 48 + }).addClass('OxGroupLabel'), + Ox.FormElementGroup({ + elements: [ + Ox.Select({ + items: $.map(self.operators, function(operator) { + return { + checked: operator.id != self.options.query.operator, + id: operator.id, + // fixme: should be operator.title, + // but is passed by reference to some select, + // which makes it an array + title: operator.title[0] + }; + }), + width: 48 + }) + .bindEvent({ + change: changeOperator + }), + Ox.Label({ + overlap: 'left', + title: 'of the following conditions', + width: 160 + }) + ], + float: 'right', + width: 208 + }), + ], renderButtons(pos, subpos, true)), + float: 'left', + }) + .data({position: pos, subposition: subpos}); + return $condition; } function updateConditions() { self.$conditions.forEach(function(condition, pos) { - condition.data({position: pos}); + condition.data({position: pos, subposition: -1}); }); self.$conditions[0].options('elements')[3].options({ disabled: self.options.query.conditions.length == 1