From cdd366f0c60ad190508cb2ae0f73d782b2b79259 Mon Sep 17 00:00:00 2001 From: windy <1374721899@qq.com> Date: Wed, 29 Mar 2017 09:16:53 +0800 Subject: [PATCH] update --- demo/js/config/widget.js | 4 + demo/js/widget/demo.filterpane.js | 45 ++++ src/widget/filterpane/abstract.item.filter.js | 49 ++++ src/widget/filterpane/expander.filter.js | 79 ++++++ src/widget/filterpane/filter.js | 188 ++++++++++++++ src/widget/filterpane/filter.list.js | 59 +++++ src/widget/filterpane/operation.filter.js | 240 ++++++++++++++++++ src/widget/filterpane/pane.filter.js | 55 ++++ 8 files changed, 719 insertions(+) create mode 100644 demo/js/widget/demo.filterpane.js create mode 100644 src/widget/filterpane/abstract.item.filter.js create mode 100644 src/widget/filterpane/expander.filter.js create mode 100644 src/widget/filterpane/filter.js create mode 100644 src/widget/filterpane/filter.list.js create mode 100644 src/widget/filterpane/operation.filter.js create mode 100644 src/widget/filterpane/pane.filter.js diff --git a/demo/js/config/widget.js b/demo/js/config/widget.js index bb559fde4..27f3b4845 100644 --- a/demo/js/config/widget.js +++ b/demo/js/config/widget.js @@ -25,4 +25,8 @@ Demo.WIDGET_CONFIG = [{ pId: 4, text: "bi.relation_view", value: "demo.relation_view" +}, { + pId: 4, + text: "bi.filter_pane", + value: "demo.filter_pane" }]; \ No newline at end of file diff --git a/demo/js/widget/demo.filterpane.js b/demo/js/widget/demo.filterpane.js new file mode 100644 index 000000000..786f2200c --- /dev/null +++ b/demo/js/widget/demo.filterpane.js @@ -0,0 +1,45 @@ +/** + * Created by User on 2017/3/29. + */ +Demo.FilterPane = BI.inherit(BI.Widget, { + props: { + baseCls: "demo-filter-pane" + }, + + _createFilter: function () { + var filter = BI.createWidget({ + type: "bi.filter", + width: 600, + height: 300, + itemCreator: function(item){ + if(item.value === BICst.FILTER_TYPE.EMPTY_CONDITION || item.value === BICst.FILTER_TYPE.EMPTY_FORMULA){ + item.type = "bi.label"; + item.value = "这是一个新添的数据"; + } + } + }); + + return filter; + }, + + render: function () { + var filter = this._createFilter(); + + return { + type: "bi.vertical", + hgap: 30, + vgap: 20, + items: [{ + el: filter + }, { + type: "bi.button", + text: "过滤结构getValue()", + height: 30, + handler: function () { + BI.Msg.alert("过滤结构", JSON.stringify(filter.getValue())); + } + }] + } + } +}); +BI.shortcut("demo.filter_pane", Demo.FilterPane); \ No newline at end of file diff --git a/src/widget/filterpane/abstract.item.filter.js b/src/widget/filterpane/abstract.item.filter.js new file mode 100644 index 000000000..d6ce85bfe --- /dev/null +++ b/src/widget/filterpane/abstract.item.filter.js @@ -0,0 +1,49 @@ +/** + * 过滤条件抽象类 + * + * @class BI.AbstractFilterItem + * @extend BI.Widget + */ +BI.AbstractFilterItem = BI.inherit(BI.Widget, { + + _defaultConfig: function () { + return BI.extend(BI.AbstractFilterItem.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-filter-item" + }) + }, + + _init: function () { + BI.AbstractFilterItem.superclass._init.apply(this, arguments); + }, + + isSelectedCondition: function () { + return this.emptyItem && this.emptyItem.isVisible(); + }, + + setSelectedCondition: function (b) { + if (!!b) { + if (!this.emptyItem) { + this.emptyItem = BI.createWidget({ + type: "bi.absolute", + height: 40, + cls: "filter-item-empty-item", + items: [{ + el: { + type: "bi.center_adapt", + cls: "empty-filter-item-leaf" + } + }], + hgap: 10, + vgap: 5 + }); + BI.createWidget({ + type: "bi.vertical", + element: this, + items: [this.emptyItem], + scrolly: false + }); + } + } + this.emptyItem && this.emptyItem.setVisible(b); + } +}); \ No newline at end of file diff --git a/src/widget/filterpane/expander.filter.js b/src/widget/filterpane/expander.filter.js new file mode 100644 index 000000000..572dd0e12 --- /dev/null +++ b/src/widget/filterpane/expander.filter.js @@ -0,0 +1,79 @@ +/** + * @class BI.FilterExpander + * @extend BI.AbstractFilterItem + * 过滤树的一个expander节点 + */ +BI.FilterExpander = BI.inherit(BI.AbstractFilterItem, { + + _constant: { + EXPANDER_WIDTH: 20 + }, + + _defaultConfig: function () { + var conf = BI.FilterExpander.superclass._defaultConfig.apply(this, arguments); + return BI.extend(conf, { + baseCls: (conf.baseCls || "") + " bi-filter-expander", + el: {}, + popup: {} + }) + }, + + _init: function () { + BI.FilterExpander.superclass._init.apply(this, arguments); + this._initExpander(); + this._initConditionsView(); + BI.createWidget({ + type: "bi.horizontal_adapt", + element: this, + items: [this.expander, this.conditionsView] + }); + }, + + _initExpander: function () { + var self = this, o = this.options; + var value = o.value, text = ""; + if (value === BICst.FILTER_TYPE.AND) { + text = BI.i18nText("BI-Basic_And"); + } else { + text = BI.i18nText("BI-Basic_Or"); + } + this.expander = BI.createWidget({ + type: "bi.text_button", + cls: "condition-and-or", + text: text, + value: value, + id: o.id, + width: this._constant.EXPANDER_WIDTH, + height: "100%" + }); + this.expander.on(BI.Controller.EVENT_CHANGE, function (type) { + arguments[2] = self; + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + }); + }, + + _initConditionsView: function () { + var self = this, popup = this.options.popup; + this.conditionsView = BI.createWidget(popup); + this.conditionsView.on(BI.Controller.EVENT_CHANGE, function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + }); + }, + + getValue: function () { + return { + type: this.expander.getValue(), + value: this.conditionsView.getValue(), + id: this.options.id + }; + }, + + setValue: function () { + + }, + + populate: function (items) { + this.conditionsView.populate.apply(this.conditionsView, arguments); + } +}); +BI.shortcut("bi.filter_expander", BI.FilterExpander); \ No newline at end of file diff --git a/src/widget/filterpane/filter.js b/src/widget/filterpane/filter.js new file mode 100644 index 000000000..2143aa9ff --- /dev/null +++ b/src/widget/filterpane/filter.js @@ -0,0 +1,188 @@ +/** + * 过滤 + * + * Created by GUY on 2015/11/20. + * @class BI.Filter + * @extend BI.Widget + */ +BI.Filter = BI.inherit(BI.Widget, { + + constants: { + FIELD_TYPE_NUMBER: 1, + FIELD_TYPE_STRING: 0, + FIELD_TYPE_DATE: 2 + }, + + _defaultConfig: function () { + return BI.extend(BI.Filter.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-filter", + expander: {}, + items: [], + el: {}, + itemCreator: BI.empty + }) + }, + + _init: function () { + BI.Filter.superclass._init.apply(this, arguments); + var self = this, o = this.options; + this.filter = BI.createWidget(o.el,{ + type: "bi.filter_operation", + expander: o.expander, + items: o.items, + element: this + }); + this.filter.on(BI.FilterOperation.EVENT_OPERATION, function (type) { + switch (type) { + case BICst.FILTER_OPERATION_CONDITION: + case BICst.FILTER_OPERATION_CONDITION_AND: + self._addAndOrCondition(BICst.FILTER_TYPE.EMPTY_CONDITION); + break; + case BICst.FILTER_OPERATION_CONDITION_OR: + self._addAndOrCondition(BICst.FILTER_TYPE.EMPTY_CONDITION, 1); + break; + case BICst.FILTER_OPERATION_FORMULA: + case BICst.FILTER_OPERATION_FORMULA_AND: + self._addAndOrCondition(BICst.FILTER_TYPE.EMPTY_FORMULA); + break; + case BICst.FILTER_OPERATION_FORMULA_OR: + self._addAndOrCondition(BICst.FILTER_TYPE.EMPTY_FORMULA, 1); + break; + } + }); + this.filter.on(BI.FilterOperation.EVENT_DESTROY_ITEM, function (id) { + self._removeCondition(id); + }); + + this.tree = new BI.Tree(); + this.tree.initTree(o.items); + }, + + _removeCondition: function (id) { + var finded = this.tree.search(id); + if (BI.isNotNull(finded)) { + var parent = finded.getParent(); + parent.removeChild(id); + if (parent.getChildrenLength() <= 1) { + var prev = parent.getParent(); + if (BI.isNotNull(prev)) { + var index = prev.getChildIndex(parent.id); + prev.removeChildByIndex(index); + if (parent.getChildrenLength() === 1) { + prev.addChild(parent.getFirstChild(), index); + } + } + } + this._populate(this.tree.toJSONWithNode()); + this.fireEvent(BI.Filter.EVENT_CHANGE); + } + }, + + _createEmptyNode: function (type) { + var node = new BI.Node(BI.UUID()); + node.set("data", { + value: type + }); + return node; + }, + + _insertAndOrCondition: function (id, formulaOrField, type) { + var ANDOR = ["AND", "OR"]; + type || (type = 0); + var finded = this.tree.search(id); + if (BI.isNotNull(finded)) { + var data = finded.get("data"); + var parent = finded.getParent(); + var index = parent.getChildIndex(finded.id); + var pdata = parent.get("data") || {}; + var node = this._createEmptyNode(formulaOrField); + if (data.value === BICst.FILTER_TYPE[ANDOR[type]]) { + this.tree.addNode(finded, node); + return; + } + if (data.value === BICst.FILTER_TYPE[ANDOR[1 - type]]) { + if (pdata.value === BICst.FILTER_TYPE[ANDOR[type]]) { + parent.addChild(node, index + 1); + return; + } + } + if ((data.value === BICst.FILTER_TYPE[ANDOR[1 - type]] && pdata.value !== BICst.FILTER_TYPE[ANDOR[type]]) + || pdata.value === BICst.FILTER_TYPE[ANDOR[1 - type]] + || (pdata.value !== BICst.FILTER_TYPE.AND && pdata.value !== BICst.FILTER_TYPE.OR)) { + var andor = new BI.Node(BI.UUID()); + andor.set("data", { + value: BICst.FILTER_TYPE[ANDOR[type]], + children: [finded.get("data"), node.get("data")] + }); + parent.removeChildByIndex(index); + parent.addChild(andor, index); + andor.addChild(finded); + andor.addChild(node); + return; + } + parent.addChild(node, index + 1); + } + }, + + _addAndOrCondition: function (formulaOrField, type) { + var ANDOR = ["AND", "OR"]; + type || (type = 0); + var o = this.options; + var currentSelectItem = this.filter.getCurrentSelectItem(); + if (BI.isNotNull(currentSelectItem)) { + var id = currentSelectItem.attr("id"); + this._insertAndOrCondition(id, formulaOrField, type); + } else { + var node = this._createEmptyNode(formulaOrField); + var root = this.tree.getRoot(); + var child = root.getLastChild(); + if (BI.isNotNull(child)) { + var data = child.get("data"); + if (data.value === BICst.FILTER_TYPE[ANDOR[type]]) { + this.tree.addNode(child, node); + } else { + var andor = new BI.Node(BI.UUID()); + andor.set("data", { + value: BICst.FILTER_TYPE[ANDOR[type]], + children: [child.get("data"), node.get("data")] + }); + root.removeChild(child.id); + this.tree.addNode(andor); + this.tree.addNode(andor, child); + this.tree.addNode(andor, node); + } + } else { + this.tree.addNode(node); + } + } + this._populate(this.tree.toJSONWithNode()); + this.fireEvent(BI.Filter.EVENT_CHANGE); + }, + + _populate: function (items) { + var self = this, o = this.options; + o.items = items; + ArrayUtils.traversal(items, function (i, item) { + o.itemCreator(item); + }); + this.filter.populate.apply(this.filter, [items]); + }, + + populate: function (conditions) { + this.tree.initTree(conditions); + this._populate(this.tree.toJSONWithNode()); + }, + + getValue: function () { + return this.filter.getValue(); + } +}); + +BICst.FILTER_TYPE = {}; +BICst.FILTER_TYPE.AND = 80; +BICst.FILTER_TYPE.OR = 81; +BICst.FILTER_TYPE.FORMULA = 82; +BICst.FILTER_TYPE.EMPTY_FORMULA = 90; +BICst.FILTER_TYPE.EMPTY_CONDITION = 91; +BI.Filter.EVENT_CHANGE = "EVENT_CHANGE"; +BI.shortcut("bi.filter", BI.Filter); \ No newline at end of file diff --git a/src/widget/filterpane/filter.list.js b/src/widget/filterpane/filter.list.js new file mode 100644 index 000000000..e0020f38c --- /dev/null +++ b/src/widget/filterpane/filter.list.js @@ -0,0 +1,59 @@ +/** + * Created by windy on 2017/3/28. + */ +BI.FilterList = BI.inherit(BI.Widget, { + _defaultConfig: function () { + return BI.extend(BI.FilterList.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-filter-list", + expander: {}, + items: [], + itemsCreator: BI.emptyFn + }) + }, + + render: function(){ + var self = this, o = this.options; + this.group = null; + return { + type: "bi.virtual_group", + ref: function(_ref){ + self.group = _ref; + }, + items: BI.createItems(o.items, { + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE); + } + }] + }), + layouts: [{ + type: "bi.vertical", + scrolly: false + }] + } + }, + + populate: function (items) { + var self = this; + this.group.populate(BI.map(items, function(idx, item){ + return BI.extend(item, { + listeners: [{ + eventName: BI.Controller.EVENT_CHANGE, + action: function () { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + } + }] + }); + })); + }, + + setValue: function (v) { + this.group.setValue(v); + }, + + getValue: function () { + return this.group.getValue(); + } +}); +BI.shortcut("bi.filter_list", BI.FilterList); \ No newline at end of file diff --git a/src/widget/filterpane/operation.filter.js b/src/widget/filterpane/operation.filter.js new file mode 100644 index 000000000..a1c24a0e8 --- /dev/null +++ b/src/widget/filterpane/operation.filter.js @@ -0,0 +1,240 @@ +/** + * 过滤条件 + * + * Created by GUY on 2015/9/25. + * @class BI.FilterOperation + * @extend BI.Widget + */ +BI.FilterOperation = BI.inherit(BI.Widget, { + _defaultConfig: function () { + return BI.extend(BI.FilterOperation.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-filter-operation", + expander: {}, + items: [], + selections: [BICst.FILTER_OPERATION_CONDITION, BICst.FILTER_OPERATION_FORMULA], + itemsCreator: BI.emptyFn + }) + }, + + _defaultState: function () { + if (BI.isNotNull(this.currentSelected)) { + this.currentSelected.setSelectedCondition(false); + } + this.buttonComboTab.setSelect(BI.FilterOperation.OPERATION_ADD_CONDITION); + }, + + _init: function () { + BI.FilterOperation.superclass._init.apply(this, arguments); + var self = this, o = this.options; + this.currentSelected = null; + + this.filter = BI.createWidget({ + type: "bi.filter_pane", + expander: o.expander, + items: o.items, + itemsCreator: o.itemsCreator + }); + this.filter.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { + if (type === BI.Events.CLICK) { + if (BI.isNotNull(self.currentSelected) && self.currentSelected === obj) { + obj.setSelectedCondition(!obj.isSelectedCondition()); + } else { + if (BI.isNotNull(self.currentSelected)) { + self.currentSelected.setSelectedCondition(false); + } + self.currentSelected = obj; + obj.setSelectedCondition(true); + } + if (self.currentSelected.isSelectedCondition()) { + self.buttonComboTab.setSelect(BI.FilterOperation.OPERATION_ADD_ANDOR_CONDITION); + } else { + self.buttonComboTab.setSelect(BI.FilterOperation.OPERATION_ADD_CONDITION); + } + } + if (type === BI.Events.DESTROY) { + if (self.currentSelected === obj) { + self.currentSelected = null; + self.buttonComboTab.setSelect(BI.FilterOperation.OPERATION_ADD_CONDITION); + } + self.fireEvent(BI.FilterOperation.EVENT_DESTROY_ITEM, value, obj); + } + }); + this.filter.on(BI.FilterPane.EVENT_CHANGE, function () { + self.fireEvent(BI.FilterOperation.EVENT_CHANGE, arguments); + }); + var operation = this._buildOperationTab(); + + BI.createWidget({ + type: "bi.vtape", + element: this, + items: [{ + el: operation, + height: 40 + }, { + el: { + type: "bi.absolute", + scrollable: true, + items: [{ + el: { + type: "bi.left", + items: [ + this.filter + ] + }, + top: 0, + right: 2, + bottom: 0, + left: 0 + }] + } + }] + }) + }, + + _buildOperationTab: function () { + this.buttonComboTab = BI.createWidget({ + type: "bi.tab", + tab: null, + cardCreator: BI.bind(this._createTabs, this) + }); + this.buttonComboTab.setSelect(BI.FilterOperation.OPERATION_ADD_CONDITION); + return this.buttonComboTab; + }, + + _createTabs: function (v) { + var self = this; + switch (v) { + case BI.FilterOperation.OPERATION_ADD_CONDITION: + var btnGroup = BI.createWidget({ + type: "bi.button_group", + items: BI.createItems(self._createButtons(), { + type: "bi.button", + forceNotSelected: true, + level: "ignore", + height: 25 + }), + chooseType: BI.ButtonGroup.CHOOSE_TYPE_DEFAULT, + layouts: [{ + type: "bi.right", + hgap: 10, + vgap: 5 + }] + }); + btnGroup.on(BI.ButtonGroup.EVENT_CHANGE, function (value, obj) { + self.fireEvent(BI.FilterOperation.EVENT_OPERATION, obj.getValue()); + self._defaultState(); + }); + return btnGroup; + case BI.FilterOperation.OPERATION_ADD_ANDOR_CONDITION: + var btnGroup = BI.createWidget({ + type: "bi.button_group", + chooseType: BI.ButtonGroup.CHOOSE_TYPE_DEFAULT, + items: self._createCombos(), + layouts: [{ + type: "bi.right", + hgap: 10, + vgap: 5 + }] + }); + return btnGroup; + } + }, + + _createButtons: function(){ + var buttons = []; + BI.each(this.options.selections, function(i, type){ + switch (type){ + case BICst.FILTER_OPERATION_FORMULA: + buttons.push({ + text: BI.i18nText("BI-Add_Formula"), + value: BICst.FILTER_OPERATION_FORMULA + }); + break; + case BICst.FILTER_OPERATION_CONDITION: + buttons.push({ + text: BI.i18nText("BI-Add_Condition"), + value: BICst.FILTER_OPERATION_CONDITION + }); + break; + } + }); + return buttons; + }, + + _createCombos: function () { + var self = this, combos = []; + BI.each(this.options.selections, function(i, type){ + var text = "", items = []; + switch (type) { + case BICst.FILTER_OPERATION_FORMULA: + text = BI.i18nText("BI-Add_Formula"); + items = BICst.FILTER_ADD_FORMULA_COMBO; + break; + case BICst.FILTER_OPERATION_CONDITION: + text = BI.i18nText("BI-Add_Condition"); + items = BICst.FILTER_ADD_CONDITION_COMBO; + break; + } + var addCombo = BI.createWidget({ + type: "bi.static_combo", + text: text, + width: 90, + chooseType: BI.ButtonGroup.CHOOSE_TYPE_NONE, + items: BI.createItems(items, { + type: "bi.single_select_item", + height: 25 + }) + }); + addCombo.on(BI.Combo.EVENT_CHANGE, function (value, obj) { + self.fireEvent(BI.FilterOperation.EVENT_OPERATION, obj.getValue()); + self._defaultState(); + }); + combos.push(addCombo); + }); + return combos; + }, + + getCurrentSelectItem: function () { + if (BI.isNotNull(this.currentSelected) && this.currentSelected.isSelectedCondition()) { + return this.currentSelected; + } + }, + + populate: function (items) { + + this.filter.populate.apply(this.filter, arguments); + }, + + getValue: function () { + return this.filter.getValue(); + } +}); + +BICst.FILTER_ADD_FORMULA_COMBO = [{ + text: BI.i18nText("BI-Condition_Expression_And"), value: BICst.FILTER_OPERATION_FORMULA_AND +}, { + text: BI.i18nText("BI-Condition_Expression_Or"), value: BICst.FILTER_OPERATION_FORMULA_OR +}]; + +//添加条件combo +BICst.FILTER_ADD_CONDITION_COMBO = [{ + text: BI.i18nText("BI-Condition_And"), value: BICst.FILTER_OPERATION_CONDITION_AND +}, { + text: BI.i18nText("BI-Condition_Or"), value: BICst.FILTER_OPERATION_CONDITION_OR +}]; + +BICst.FILTER_OPERATION_FORMULA = 1; +BICst.FILTER_OPERATION_CONDITION = 2; +BICst.FILTER_OPERATION_CONDITION_AND = 3; +BICst.FILTER_OPERATION_CONDITION_OR = 4; +BICst.FILTER_OPERATION_FORMULA_AND = 5; +BICst.FILTER_OPERATION_FORMULA_OR = 6; + +BI.extend(BI.FilterOperation, { + OPERATION_ADD_CONDITION: 0, + OPERATION_ADD_ANDOR_CONDITION: 1 +}); +BI.FilterOperation.EVENT_OPERATION = "EVENT_OPERATION"; +BI.FilterOperation.EVENT_CHANGE = "EVENT_CHANGE"; +BI.FilterOperation.EVENT_DESTROY_ITEM = "BI.FilterOperation.EVENT_DESTROY_ITEM"; +BI.shortcut("bi.filter_operation", BI.FilterOperation); \ No newline at end of file diff --git a/src/widget/filterpane/pane.filter.js b/src/widget/filterpane/pane.filter.js new file mode 100644 index 000000000..6dc7b39e5 --- /dev/null +++ b/src/widget/filterpane/pane.filter.js @@ -0,0 +1,55 @@ +/** + * @class BI.FilterPane + * @extend BI.Widget + * 过滤面板 + */ +BI.FilterPane = BI.inherit(BI.Widget, { + _defaultConfig: function () { + return BI.extend(BI.FilterPane.superclass._defaultConfig.apply(this, arguments), { + baseCls: "bi-filter-pane", + expander: {}, + items: [], + itemsCreator: BI.emptyFn + }) + }, + + _init: function () { + BI.FilterPane.superclass._init.apply(this, arguments); + var self = this, o = this.options; + this.tree = BI.createWidget({ + type: "bi.custom_tree", + element: this, + expander: BI.extend({ + type: "bi.filter_expander", + el: {}, + popup: { + type: "bi.custom_tree" + } + }, o.expander), + el: { + type: "bi.filter_list" + } + }); + + this.tree.on(BI.Controller.EVENT_CHANGE, function (type) { + self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); + if (type === BI.Events.CLICK) { + self.fireEvent(BI.FilterPane.EVENT_CHANGE, [].slice.call(arguments, 1)); + } + }); + + if (BI.isNotEmptyArray(o.items)) { + this.populate(o.items); + } + }, + + populate: function (items) { + this.tree.populate.apply(this.tree, arguments); + }, + + getValue: function () { + return this.tree.getValue(); + } +}); +BI.FilterPane.EVENT_CHANGE = "EVENT_CHANGE"; +BI.shortcut("bi.filter_pane", BI.FilterPane); \ No newline at end of file