From 358c1ecebb86122e94f897fc40ed84b5db057528 Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Mon, 24 Jan 2011 04:08:19 +0000 Subject: [PATCH] Ox.Filter, round 2 --- build/js/ox.js | 8 + build/js/ox.ui.js | 606 ++++++++++++++++++++++++++++------------------ 2 files changed, 384 insertions(+), 230 deletions(-) diff --git a/build/js/ox.js b/build/js/ox.js index fabc0f22..93b60956 100644 --- a/build/js/ox.js +++ b/build/js/ox.js @@ -1226,6 +1226,10 @@ Format functions ================================================================================ */ +Ox.formatColor = function() { + +}; + Ox.formatCurrency = function(num, str, dec) { return str + formatNumber(num, dec); }; @@ -1511,6 +1515,10 @@ Ox.formatValue = function(num, str) { return val; }; +Ox.formatUnit = function(num, str) { + return num + ' ' + str; +}; + /* ================================================================================ Geo functions diff --git a/build/js/ox.ui.js b/build/js/ox.ui.js index 92fe8cf1..7fc3f308 100644 --- a/build/js/ox.ui.js +++ b/build/js/ox.ui.js @@ -2085,71 +2085,80 @@ requires ============================================================================ */ - /** - */ Ox.Filter = function(options, self) { + /*** + Options: + Methods: + Events: + ***/ + var self = self || {}, that = new Ox.Element('div', self) .defaults({ - keys: [], + findKeys: [], query: { conditions: [], operator: '&' - } + }, + sortKeys: [], + viewKeys: [] }) .options(options || {}); - Ox.print('s.o', self.options) + Ox.print('Ox.Filter self.options', self.options) + + $.extend(self, { + conditionOperators: { + date: [ + {id: '', title: 'is'}, + {id: '!', title: 'is not'}, + {id: '<', title: 'is before'}, + {id: '>', title: 'is after'}, + {id: '>&<', title: 'is between'}, + {id: '<|>', title: 'is not between'} + ], + list: [ + {id: '', title: 'is'}, + {id: '!', title: 'is not'} + ], + number: [ + {id: '', title: 'is'}, + {id: '!', title: 'is not'}, + {id: '<', title: 'is less than'}, + {id: '>', title: 'is greater than'}, + {id: '>&<', title: 'is between'}, + {id: '<|>', title: 'is not between'} + ], + string: [ + {id: '=', title: 'is'}, + {id: '!=', title: 'is not'}, + {id: '^', title: 'begins with'}, + {id: '$', title: 'ends with'}, + {id: '', title: 'contains'}, + {id: '!', title: 'does not contain'} + ], + text: [ + {id: '', title: 'contains'}, + {id: '!', title: 'does not contain'} + ] + }, + operators: [ + {id: '&', title: 'all'}, + {id: '|', title: 'any'} + ] + }); if (!self.options.query.conditions.length) { self.options.query.conditions = [{ - key: self.options.keys[0].id, - value: '' + key: self.options.findKeys[0].id, + value: '', + operator: self.conditionOperators[ + getConditionType(self.options.findKeys[0].type) + ][0].id }]; } - $.extend(self, { - operators: [ - {title: 'all', operator: '&'}, - {title: 'any', operator: '|'} - ], - relations: { - date: [ - {title: 'is', operator: '='}, - {title: 'is not', operator: '!'}, - {title: 'is before', operator: '<'}, - {title: 'is after', operator: '>'}, - {title: 'is between', operator: '>&<'}, - {title: 'is not between', operator: '<|>'} - ], - list: [ - {title: 'is', operator: '='}, - {title: 'is not', operator: '!'} - ], - number: [ - {title: 'is', operator: '='}, - {title: 'is not', operator: '!'}, - {title: 'is less than', operator: '<'}, - {title: 'is greater than', operator: '>'}, - {title: 'is between', operator: '>&<'}, - {title: 'is not between', operator: '<|>'} - ], - string: [ - {title: 'is', operator: '='}, - {title: 'is not', operator: '!='}, - {title: 'begins with', operator: '^'}, - {title: 'ends with', operator: '$'}, - {title: 'contains', operator: ''}, - {title: 'does not contain', operator: '!'} - ], - text: [ - {title: 'contains', operator: ''}, - {title: 'does not contain', operator: '!'} - ] - } - }); - self.$operator = new Ox.FormElementGroup({ elements: [ new Ox.Label({ @@ -2157,18 +2166,24 @@ requires overlap: 'right', width: 48 }), - new Ox.Select({ - items: [ - {id: 'all', title: 'all'}, - {id: 'any', title: 'any'}, + new Ox.FormElementGroup({ + elements: [ + new Ox.Select({ + items: self.operators, + width: 48 + }) + .bindEvent({ + change: changeOperator + }), + new Ox.Label({ + overlap: 'left', + title: 'of the following conditions', + width: 160 + }) ], - overlap: 'right', - width: 48 - }), - new Ox.Label({ - title: 'of the following conditions', - width: 160 - }), + float: 'right', + width: 208 + }) ], float: 'left', }); @@ -2205,40 +2220,109 @@ requires width: 120 }), new Ox.Select({ - /* - items: $.map(self.options.keys, function(key) { - return {id: key.id, title: key.title}; - }), - */ - items: [ - {id: "title", title: "Title"}, - {id: "director", title: "Director"} - ], + items: self.options.sortKeys, width: 128 + }), + new Ox.FormElementGroup({ + elements: [ + new Ox.Select({ + items: [ + {id: 'ascending', title: 'ascending'}, + {id: 'descending', title: 'descending'} + ], + width: 96 + }), + new Ox.Label({ + overlap: 'left', + title: 'order', + width: 72 + }) + ], + float: 'right', + width: 168 }) ], separators: [ {title: 'Limit to', width: 56}, - {title: 'sorted by', width: 64} + {title: 'sorted by', width: 64}, + {title: 'in', width: 32} ] }); - self.$items = $.merge($.merge([self.$operator], self.$conditions), [self.$limit]); + self.$view = new Ox.InputGroup({ + inputs: [ + new Ox.Checkbox({ + width: 16 + }), + new Ox.Select({ + items: self.options.viewKeys, + width: 128 + }) + ], + separators: [ + {title: 'By default, view', width: 112} + ] + }); - that = new Ox.Form({ + self.$save = new Ox.InputGroup({ + inputs: [ + new Ox.Checkbox({ + width: 16 + }), + new Ox.Input({ + id: 'list', + width: 128 + }) + ], + separators: [ + {title: 'Save as Smart List', width: 112} + ] + }); + + self.$items = $.merge($.merge([self.$operator], self.$conditions), [self.$limit, self.$view, self.$save]); + + self.$form = new Ox.Form({ items: self.$items - }, $.extend({}, self)); + }); + that.$element = self.$form.$element; function addCondition(pos) { - var key = self.options.keys[0]; + var key = self.options.findKeys[0]; self.options.query.conditions.splice(pos, 0, { key: key.id, value: '', - operator: self.relations[key.type][0].operator + operator: self.conditionOperators[key.type][0].id }); self.$conditions.splice(pos, 0, constructCondition({}, pos)); updateConditions(); - that.addItem(pos + 1, self.$conditions[pos]); + self.$form.addItem(pos + 1, self.$conditions[pos]); + } + + function changeConditionKey(pos, key) { + Ox.print('changeConditionKey', pos, key); + var oldOperator = self.options.query.conditions[pos].operator, + oldType = Ox.getObjectById( + self.options.findKeys, self.options.query.conditions[pos].key + ).type, + newType = Ox.getObjectById( + self.options.findKeys, key + ).type, + oldConditionType = getConditionType(oldType), + newConditionType = getConditionType(newType); + changeConditionType = oldConditionType != newConditionType; + Ox.print('old new', oldConditionType, newConditionType) + self.options.query.conditions[pos].key = key; + if (changeConditionType) { + self.$conditions[pos].replaceElement(1, constructConditionOperator(pos, oldOperator)); + } + } + + function changeConditionOperator(pos, operator) { + + } + + function changeOperator(event, data) { + self.options.query.operator = data.selected[0].id; } function constructCondition(condition, pos) { @@ -2246,17 +2330,23 @@ requires return $condition = new Ox.FormElementGroup({ elements: [ new Ox.Select({ - items: $.extend({}, self.options.keys), // fixme: Ox.Menu messes with keys - overlap: 'right', - width: 128 - }), - new Ox.Select({ - items: $.map(self.relations[self.options.keys[0].type], function(relation) { - return {id: relation.title, title: relation.title} + 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); + } }), - overlap: 'right', - width: 128 - }), + constructConditionOperator(pos), new Ox.Input({ width: 256 }), @@ -2282,6 +2372,7 @@ requires .css({margin: '0 4px 0 4px'}) .bindEvent({ click: function() { + Ox.print('add', $(this).parent().parent().data('position')) addCondition($condition.data('position') + 1) } }), @@ -2291,17 +2382,54 @@ requires tooltip: 'Add Group of Conditions', type: 'image' }) - .css({margin: '0 0 0 4px'}), + .css({margin: '0 0 0 4px'}) + .bindEvent({ + click: function() { + + } + }) ] }) .data({position: pos}); } + function constructConditionOperator(pos, selected) { + return new Ox.Select({ + items: $.map(self.conditionOperators[getConditionType( + Ox.getObjectById( + self.options.findKeys, + self.options.query.conditions[pos].key + ).type + )], function(operator) { + return { + checked: operator.id == selected, // fixme: should be "selected", not "checked" + id: operator.operator, + title: operator.title + }; + }), + overlap: 'right', + width: 128 + }) + .bindEvent({ + change: function(event, data) { + changeConditionOperator(/*$condition.data('position')*/ pos, data.selected[0].id) + } + }); + } + + function getConditionType(type) { + type = Ox.isArray(type) ? type[0] : type; + if (['float', 'integer', 'year'].indexOf(type) > 1) { + type = 'number'; + } + return type; + } + function removeCondition(pos) { self.options.query.conditions.splice(pos, 1); self.$conditions.splice(pos, 1); updateConditions(); - that.removeItem(pos + 1); + self.$form.removeItem(pos + 1); } function updateConditions() { @@ -2317,9 +2445,11 @@ requires }; - /** - */ Ox.Form = function(options, self) { + + /** + */ + var self = self || {}, that = new Ox.Element('div', self) .defaults({ @@ -2437,8 +2567,6 @@ requires }; - /** - */ Ox.FormItem = function(options, self) { var self = self || {}, @@ -2471,18 +2599,20 @@ requires Form Elements */ - /** - methods: - toggleDisabled enable/disable button - toggleSelected select/unselect button - toggleTitle if more than one title was provided, - toggle to next title. - events: - click non-selectable button was clicked - deselect selectable button was deselected - select selectable button was selected - */ Ox.Button = function(options, self) { + + /** + methods: + toggleDisabled enable/disable button + toggleSelected select/unselect button + toggleTitle if more than one title was provided, + toggle to next title. + events: + click non-selectable button was clicked + deselect selectable button was deselected + select selectable button was selected + */ + var self = self || {}, that = new Ox.Element('input', self) .defaults({ @@ -2632,18 +2762,20 @@ requires }; - /** - options - buttons array of buttons - max integer, maximum number of selected buttons, 0 for all - min integer, minimum number of selected buttons, 0 for none - selectable if true, buttons are selectable - type string, 'image' or 'text' - methods: - events: - change {id, value} selection within a group changed - */ Ox.ButtonGroup = function(options, self) { + + /** + options + buttons array of buttons + max integer, maximum number of selected buttons, 0 for all + min integer, minimum number of selected buttons, 0 for none + selectable if true, buttons are selectable + type string, 'image' or 'text' + methods: + events: + change {id, value} selection within a group changed + */ + var self = self || {}, that = new Ox.Element({}, self) .defaults({ @@ -2705,24 +2837,24 @@ requires return that; }; - /** - options - disabled boolean, if true, checkbox is disabled - id element id - group boolean, if true, checkbox is part of a group - checked boolean, if true, checkbox is checked - title string, text on label - width integer, width in px - methods: - toggleChecked function() - toggles checked property - returns that - events: - change triggered when checked property changes - passes {checked, id, title} - */ Ox.Checkbox = function(options, self) { + /** + options + disabled boolean, if true, checkbox is disabled + id element id + group boolean, if true, checkbox is part of a group + checked boolean, if true, checkbox is checked + title string, text on label + width integer, width in px + methods: + toggleChecked function() + toggles checked property + returns that + events: + change triggered when checked property changes + passes {checked, id, title} + */ var self = self || {}, that = new Ox.Element('div', self) @@ -2810,18 +2942,19 @@ requires }; - /** - options - checkboxes [] array of checkboxes - max 1 integer - min 1 integer - width integer, width in px - events: - change triggered when checked property changes - passes {checked, id, title} - */ Ox.CheckboxGroup = function(options, self) { + /** + options + checkboxes [] array of checkboxes + max 1 integer + min 1 integer + width integer, width in px + events: + change triggered when checked property changes + passes {checked, id, title} + */ + var self = self || {}, that = new Ox.Element('div', self) .defaults({ @@ -2880,60 +3013,62 @@ requires }; - /** - options - arrows boolearn, if true, and type is 'float' or 'integer', display arrows - arrowStep number, step when clicking arrows - autocomplete array of possible values, or - function(key, value, callback), returns one or more values - autocompleteReplace boolean, if true, value is replaced - autocompleteReplaceCorrect boolean, if true, only valid values can be entered - autocompleteSelect boolean, if true, menu is displayed - autocompleteSelectHighlight boolean, if true, value in menu is highlighted - autocompleteSelectSubmit boolean, if true, submit input on menu selection - autocorrect string ('email', 'float', 'integer', 'phone', 'url'), or - regexp(value), or - function(key, value, blur, callback), returns value - auto validate --remote validation-- - clear boolean, if true, has clear button - disabled boolean, if true, is disabled - height integer, px (for type='textarea' and type='range' with orientation='horizontal') - id string, element id - key string, to be passed to autocomplete and autovalidate functions - max number, max value if type is 'integer' or 'float' - min number, min value if type is 'integer' or 'float' - name string, will be displayed by autovalidate function ('invalid ' + name) - overlap string, '', 'left' or 'right', will cause padding and negative margin - picker - //rangeOptions - arrows boolean, if true, display arrows - //arrowStep number, step when clicking arrows - //arrowSymbols array of two strings - max number, maximum value - min number, minimum value - orientation 'horizontal' or 'vertical' - step number, step - thumbValue boolean, if true, value is displayed on thumb, or - array of strings per value, or - function(value), returns string - thumbSize integer, px - trackGradient string, css gradient for track - trackImage string, image url, or - array of image urls - //trackStep number, 0 for 'scroll here', positive for step - trackValues boolean - serialize - textAlign 'left', 'center' or 'right' - type 'float', 'integer', 'password', 'text' - value string - validate function, remote validation - width integer, px - methods: - events: - change - submit - */ Ox.Input = function(options, self) { + + /** + options + arrows boolearn, if true, and type is 'float' or 'integer', display arrows + arrowStep number, step when clicking arrows + autocomplete array of possible values, or + function(key, value, callback), returns one or more values + autocompleteReplace boolean, if true, value is replaced + autocompleteReplaceCorrect boolean, if true, only valid values can be entered + autocompleteSelect boolean, if true, menu is displayed + autocompleteSelectHighlight boolean, if true, value in menu is highlighted + autocompleteSelectSubmit boolean, if true, submit input on menu selection + autocorrect string ('email', 'float', 'integer', 'phone', 'url'), or + regexp(value), or + function(key, value, blur, callback), returns value + autovalidate --remote validation-- + clear boolean, if true, has clear button + disabled boolean, if true, is disabled + height integer, px (for type='textarea' and type='range' with orientation='horizontal') + id string, element id + key string, to be passed to autocomplete and autovalidate functions + max number, max value if type is 'integer' or 'float' + min number, min value if type is 'integer' or 'float' + name string, will be displayed by autovalidate function ('invalid ' + name) + overlap string, '', 'left' or 'right', will cause padding and negative margin + picker + //rangeOptions + arrows boolean, if true, display arrows + //arrowStep number, step when clicking arrows + //arrowSymbols array of two strings + max number, maximum value + min number, minimum value + orientation 'horizontal' or 'vertical' + step number, step + thumbValue boolean, if true, value is displayed on thumb, or + array of strings per value, or + function(value), returns string + thumbSize integer, px + trackGradient string, css gradient for track + trackImage string, image url, or + array of image urls + //trackStep number, 0 for 'scroll here', positive for step + trackValues boolean + serialize + textAlign 'left', 'center' or 'right' + type 'float', 'integer', 'password', 'text' + value string + validate function, remote validation + width integer, px + methods: + events: + change + submit + */ + var self = self || {}, that = new Ox.Element('div', self) .defaults({ @@ -3809,20 +3944,21 @@ requires }; - /** - options: - format: 'short' - value: date value - weekday: false - width: { - day: 32, - month: options.format == 'long' ? 80 : (options.format == 'medium' ? 40 : 32), - weekday: options.format == 'long' ? 80 : 40, - year: 48 - } - */ Ox.DateInput = function(options, self) { + /** + options: + format: 'short' + value: date value + weekday: false + width: { + day: 32, + month: options.format == 'long' ? 80 : (options.format == 'medium' ? 40 : 32), + weekday: options.format == 'long' ? 80 : 40, + year: 48 + } + */ + var self = $.extend(self || {}, { options: $.extend({ format: 'short', @@ -4402,25 +4538,27 @@ requires } - /** - options - arrows boolean if true, show arrows - arrowStep number step when clicking arrows - arrowSymbols array arrow symbols, like ['minus', 'plus'] - max number maximum value - min number minimum value - orientation string 'horizontal' or 'vertical' - step number step between values - size number width or height, in px - thumbSize number minimum width or height of thumb, in px - thumbValue boolean if true, display value on thumb - trackGradient array colors - trackImages string or array one or multiple track background image URLs - trackStep number 0 (scroll here) or step when clicking track - value number initial value - valueNames array value names to display on thumb - */ Ox.Range = function(options, self) { + + /** + options + arrows boolean if true, show arrows + arrowStep number step when clicking arrows + arrowSymbols array arrow symbols, like ['minus', 'plus'] + max number maximum value + min number minimum value + orientation string 'horizontal' or 'vertical' + step number step between values + size number width or height, in px + thumbSize number minimum width or height of thumb, in px + thumbValue boolean if true, display value on thumb + trackGradient array colors + trackImages string or array one or multiple track background image URLs + trackStep number 0 (scroll here) or step when clicking track + value number initial value + valueNames array value names to display on thumb + */ + var self = self || {}, that = new Ox.Element({}, self) .defaults({ @@ -4851,10 +4989,14 @@ requires } self.onChange = function(key, value) { - if (key == 'trackColors') { - - } - } + + }; + + that.replaceElement = function(pos, element) { + Ox.print('Ox.FormElementGroup replaceElement', pos, element) + self.options.elements[pos].replaceWith(element.$element); + self.options.elements[pos] = element; + }; that.value = function() { return $.map(self.options.elements, function(element) { @@ -7817,6 +7959,8 @@ requires .options(options || {}) .addClass('OxTextList'); + Ox.print('Ox.TextList self.options', self.options) + $.each(self.options.columns, function(i, v) { // fixme: can this go into a generic ox.js function? // fixme: and can't these just remain undefined? if (Ox.isUndefined(v.align)) { @@ -8012,7 +8156,7 @@ requires isSelected = self.options.sort[0].key == self.options.columns[i].id; that.sortList( self.options.columns[i].id, isSelected ? - (self.options.sort[0].operator === '' ? '-' : '') : + (self.options.sort[0].operator == '+' ? '-' : '+') : self.options.columns[i].operator ); } @@ -8050,7 +8194,7 @@ requires $order = $('
') .addClass('OxOrder') .html(oxui.symbols['triangle_' + ( - v.operator === '' ? 'up' : 'down' + v.operator == '+' ? 'up' : 'down' )]) .click(function() { $(this).prev().trigger('click') @@ -8367,7 +8511,7 @@ requires var pos = getColumnPositionById(id); //Ox.print(id, pos) that.$titles[pos].next().html(oxui.symbols[ - 'triangle_' + (self.options.sort[0].operator === '' ? 'up' : 'down') + 'triangle_' + (self.options.sort[0].operator == '+' ? 'up' : 'down') ]); } @@ -9423,7 +9567,7 @@ requires that.items = []; $.each(items, function(i, item) { var position; - if (item.id) { + if ('id' in item) { that.items.push(new Ox.MenuItem($.extend(item, { menu: that, position: position = that.items.length @@ -9941,9 +10085,11 @@ requires title: Ox.makeArray(options.title || self.defaults.title) })) .addClass('OxItem' + (self.options.disabled ? ' OxDisabled' : '')) + /* .attr({ id: Ox.toCamelCase(self.options.menu.options('id') + '/' + self.options.id) }) + */ .data('group', self.options.group); // fixme: why? if (self.options.group && self.options.checked === null) {