From 0f9eb6313a5a1a949662eb17c5e09cfb6c7e5189 Mon Sep 17 00:00:00 2001
From: guy <guy@finereport.com>
Date: Tue, 28 Mar 2017 17:44:19 +0800
Subject: [PATCH 01/19] add

---
 bi/base.js                            | 28 +++++++++++++++++++++++----
 bi/core.js                            | 23 ++++++++++++++++------
 dist/base.js                          | 28 +++++++++++++++++++++++----
 dist/core.js                          | 23 ++++++++++++++++------
 src/base/combination/group.button.js  | 18 ++++++++++++++---
 src/base/combination/group.virtual.js | 10 +++++++++-
 src/core/wrapper/layout.js            | 23 ++++++++++++++++------
 src/css/base/single/text.css          |  2 +-
 src/less/base/single/text.less        |  2 +-
 9 files changed, 125 insertions(+), 32 deletions(-)

diff --git a/bi/base.js b/bi/base.js
index 2d39187d1d..77e8690095 100644
--- a/bi/base.js
+++ b/bi/base.js
@@ -1118,9 +1118,21 @@ BI.ButtonGroup = BI.inherit(BI.Widget, {
         this.layouts.addItems(this._packageLayout(items).items);
     },
 
-    removeItemAt: function (index) {
-        this.buttons[index].destroy();
-        this.layouts.removeItemAt(index);
+    removeItemAt: function (indexes) {
+        BI.remove(this.buttons, indexes);
+        this.layouts.removeItemAt(indexes);
+    },
+
+    removeItems: function (values) {
+        values = BI.isArray(values) ? values : [values];
+        var deleted = [];
+        BI.each(this.buttons, function (i, button) {
+            if (BI.deepContains(values, button.getValue())) {
+                deleted.push(i);
+            }
+        });
+        BI.remove(this.buttons, deleted);
+        this.layouts.removeItemAt(deleted);
     },
 
     populate: function (items) {
@@ -3609,7 +3621,15 @@ BI.shortcut("bi.combo_group", BI.ComboGroup);BI.VirtualGroup = BI.inherit(BI.Wid
     },
 
     prependItems: function (items) {
-        this.layouts.prependItems(items);  
+        this.layouts.prependItems(items);
+    },
+
+    setValue: function (v) {
+        this.layouts.setValue(v);
+    },
+
+    getValue: function () {
+        return this.layouts.getValue();
     },
 
     populate: function (items) {
diff --git a/bi/core.js b/bi/core.js
index bc36f84a65..e065a7a4b4 100644
--- a/bi/core.js
+++ b/bi/core.js
@@ -11419,13 +11419,24 @@ BI.Layout = BI.inherit(BI.Widget, {
         return w;
     },
 
-    removeItemAt: function (index) {
-        if (index < 0 || index > this.options.items.length - 1) {
-            return;
+    removeItemAt: function (indexes) {
+        indexes = BI.isArray(indexes) ? indexes : [indexes];
+        var deleted = [];
+        var newItems = [], newChildren = {};
+        for (var i = 0, len = this.options.items.length; i < len; i++) {
+            var child = this._children[this._getChildName(i)];
+            if (indexes.contains(i)) {
+                deleted.push(child);
+            } else {
+                newChildren[this._getChildName(newItems.length)] = child;
+                newItems.push(this.options.items[i]);
+            }
         }
-        var child = this._children[this._getChildName(index)];
-        this._removeItemAt(index);
-        child.destroy();
+        this.options.items = newItems;
+        this._children = newChildren;
+        BI.each(deleted, function (i, c) {
+            c.destroy();
+        });
     },
 
     updateItemAt: function (index, item) {
diff --git a/dist/base.js b/dist/base.js
index 2d39187d1d..77e8690095 100644
--- a/dist/base.js
+++ b/dist/base.js
@@ -1118,9 +1118,21 @@ BI.ButtonGroup = BI.inherit(BI.Widget, {
         this.layouts.addItems(this._packageLayout(items).items);
     },
 
-    removeItemAt: function (index) {
-        this.buttons[index].destroy();
-        this.layouts.removeItemAt(index);
+    removeItemAt: function (indexes) {
+        BI.remove(this.buttons, indexes);
+        this.layouts.removeItemAt(indexes);
+    },
+
+    removeItems: function (values) {
+        values = BI.isArray(values) ? values : [values];
+        var deleted = [];
+        BI.each(this.buttons, function (i, button) {
+            if (BI.deepContains(values, button.getValue())) {
+                deleted.push(i);
+            }
+        });
+        BI.remove(this.buttons, deleted);
+        this.layouts.removeItemAt(deleted);
     },
 
     populate: function (items) {
@@ -3609,7 +3621,15 @@ BI.shortcut("bi.combo_group", BI.ComboGroup);BI.VirtualGroup = BI.inherit(BI.Wid
     },
 
     prependItems: function (items) {
-        this.layouts.prependItems(items);  
+        this.layouts.prependItems(items);
+    },
+
+    setValue: function (v) {
+        this.layouts.setValue(v);
+    },
+
+    getValue: function () {
+        return this.layouts.getValue();
     },
 
     populate: function (items) {
diff --git a/dist/core.js b/dist/core.js
index 18bd9eefae..efa58d6bb2 100644
--- a/dist/core.js
+++ b/dist/core.js
@@ -19552,13 +19552,24 @@ BI.Layout = BI.inherit(BI.Widget, {
         return w;
     },
 
-    removeItemAt: function (index) {
-        if (index < 0 || index > this.options.items.length - 1) {
-            return;
+    removeItemAt: function (indexes) {
+        indexes = BI.isArray(indexes) ? indexes : [indexes];
+        var deleted = [];
+        var newItems = [], newChildren = {};
+        for (var i = 0, len = this.options.items.length; i < len; i++) {
+            var child = this._children[this._getChildName(i)];
+            if (indexes.contains(i)) {
+                deleted.push(child);
+            } else {
+                newChildren[this._getChildName(newItems.length)] = child;
+                newItems.push(this.options.items[i]);
+            }
         }
-        var child = this._children[this._getChildName(index)];
-        this._removeItemAt(index);
-        child.destroy();
+        this.options.items = newItems;
+        this._children = newChildren;
+        BI.each(deleted, function (i, c) {
+            c.destroy();
+        });
     },
 
     updateItemAt: function (index, item) {
diff --git a/src/base/combination/group.button.js b/src/base/combination/group.button.js
index f680af2cc7..d4d7ad2787 100644
--- a/src/base/combination/group.button.js
+++ b/src/base/combination/group.button.js
@@ -155,9 +155,21 @@ BI.ButtonGroup = BI.inherit(BI.Widget, {
         this.layouts.addItems(this._packageLayout(items).items);
     },
 
-    removeItemAt: function (index) {
-        this.buttons[index].destroy();
-        this.layouts.removeItemAt(index);
+    removeItemAt: function (indexes) {
+        BI.remove(this.buttons, indexes);
+        this.layouts.removeItemAt(indexes);
+    },
+
+    removeItems: function (values) {
+        values = BI.isArray(values) ? values : [values];
+        var deleted = [];
+        BI.each(this.buttons, function (i, button) {
+            if (BI.deepContains(values, button.getValue())) {
+                deleted.push(i);
+            }
+        });
+        BI.remove(this.buttons, deleted);
+        this.layouts.removeItemAt(deleted);
     },
 
     populate: function (items) {
diff --git a/src/base/combination/group.virtual.js b/src/base/combination/group.virtual.js
index 2a959d710e..48ebdcb104 100644
--- a/src/base/combination/group.virtual.js
+++ b/src/base/combination/group.virtual.js
@@ -52,7 +52,15 @@ BI.VirtualGroup = BI.inherit(BI.Widget, {
     },
 
     prependItems: function (items) {
-        this.layouts.prependItems(items);  
+        this.layouts.prependItems(items);
+    },
+
+    setValue: function (v) {
+        this.layouts.setValue(v);
+    },
+
+    getValue: function () {
+        return this.layouts.getValue();
     },
 
     populate: function (items) {
diff --git a/src/core/wrapper/layout.js b/src/core/wrapper/layout.js
index 4074b3fd74..f4b0dbd48b 100644
--- a/src/core/wrapper/layout.js
+++ b/src/core/wrapper/layout.js
@@ -220,13 +220,24 @@ BI.Layout = BI.inherit(BI.Widget, {
         return w;
     },
 
-    removeItemAt: function (index) {
-        if (index < 0 || index > this.options.items.length - 1) {
-            return;
+    removeItemAt: function (indexes) {
+        indexes = BI.isArray(indexes) ? indexes : [indexes];
+        var deleted = [];
+        var newItems = [], newChildren = {};
+        for (var i = 0, len = this.options.items.length; i < len; i++) {
+            var child = this._children[this._getChildName(i)];
+            if (indexes.contains(i)) {
+                deleted.push(child);
+            } else {
+                newChildren[this._getChildName(newItems.length)] = child;
+                newItems.push(this.options.items[i]);
+            }
         }
-        var child = this._children[this._getChildName(index)];
-        this._removeItemAt(index);
-        child.destroy();
+        this.options.items = newItems;
+        this._children = newChildren;
+        BI.each(deleted, function (i, c) {
+            c.destroy();
+        });
     },
 
     updateItemAt: function (index, item) {
diff --git a/src/css/base/single/text.css b/src/css/base/single/text.css
index 34613e8aa1..ce71f6ee51 100644
--- a/src/css/base/single/text.css
+++ b/src/css/base/single/text.css
@@ -6,5 +6,5 @@
   overflow-x: hidden;
   overflow-y: hidden;
   white-space: nowrap;
-  word-break: break-all;
+  word-break: break-word;
 }
diff --git a/src/less/base/single/text.less b/src/less/base/single/text.less
index 568122a9c2..a6f1d83cd4 100644
--- a/src/less/base/single/text.less
+++ b/src/less/base/single/text.less
@@ -2,5 +2,5 @@
 
 .bi-text{
   .overflow-dot();
-  word-break: break-all;
+  word-break: break-word;
 }
\ No newline at end of file

From b894a850a8e8bf5cb1bceed91f0a89df965bb39b Mon Sep 17 00:00:00 2001
From: guy <guy@finereport.com>
Date: Tue, 28 Mar 2017 22:43:49 +0800
Subject: [PATCH 02/19] add

---
 bi/base.css                                 |  2 +-
 bi/core.js                                  | 18 +++++++++---------
 demo/js/core/abstract/demo.virtual_group.js |  1 +
 dist/base.css                               |  2 +-
 dist/core.js                                | 18 +++++++++---------
 src/core/base.js                            |  7 +++----
 src/core/widget.js                          |  5 +++--
 src/core/wrapper/layout.js                  |  6 +++---
 8 files changed, 30 insertions(+), 29 deletions(-)

diff --git a/bi/base.css b/bi/base.css
index a97667728a..542cd75be5 100644
--- a/bi/base.css
+++ b/bi/base.css
@@ -1035,7 +1035,7 @@ li.CodeMirror-hint-active {
   overflow-x: hidden;
   overflow-y: hidden;
   white-space: nowrap;
-  word-break: break-all;
+  word-break: break-word;
 }
 /****添加计算宽度的--运算符直接需要space****/
 /****** common color(常用颜色,可用于普遍场景) *****/
diff --git a/bi/core.js b/bi/core.js
index e065a7a4b4..dad5b489de 100644
--- a/bi/core.js
+++ b/bi/core.js
@@ -2036,7 +2036,7 @@ if (!window.BI) {
         },
 
         formatEL: function (obj) {
-            if (obj && obj.el) {
+            if (obj && !obj.type && obj.el) {
                 return obj;
             }
             return {
@@ -2995,9 +2995,8 @@ if (!window.BI) {
 
 
                 option.data = BI.cjkEncodeDO(option.data);
-                    
-                    
-                
+
+
                 $.ajax({
                     url: option.url,
                     type: "POST",
@@ -4458,7 +4457,8 @@ BI.Widget = BI.inherit(BI.OB, {
 
     mounted: null,
 
-    update: null,
+    update: function () {
+    },
 
     destroyed: null,
 
@@ -4682,7 +4682,7 @@ BI.Widget = BI.inherit(BI.OB, {
         }
         widget._setParent && widget._setParent(this);
         widget.on(BI.Events.DESTROY, function () {
-            delete self._children[name]
+            BI.remove(self._children, this);
         });
         return (this._children[name] = widget);
     },
@@ -11445,9 +11445,9 @@ BI.Layout = BI.inherit(BI.Widget, {
         }
 
         var child = this._children[this._getChildName(index)];
-        if (child.update) {
-            child.update(this._getOptions(item));
-            return true;
+        var updated;
+        if (updated = child.update(this._getOptions(item))) {
+            return updated;
         }
         var del = this._children[this._getChildName(index)];
         delete this._children[this._getChildName(index)];
diff --git a/demo/js/core/abstract/demo.virtual_group.js b/demo/js/core/abstract/demo.virtual_group.js
index c933aa7b62..eb75071389 100644
--- a/demo/js/core/abstract/demo.virtual_group.js
+++ b/demo/js/core/abstract/demo.virtual_group.js
@@ -66,6 +66,7 @@ Demo.Item = BI.inherit(BI.Widget, {
     update: function (item) {
         this.label.setText(item.value);
         console.log("更新了一项");
+        return true;
     },
 
     created: function () {
diff --git a/dist/base.css b/dist/base.css
index a97667728a..542cd75be5 100644
--- a/dist/base.css
+++ b/dist/base.css
@@ -1035,7 +1035,7 @@ li.CodeMirror-hint-active {
   overflow-x: hidden;
   overflow-y: hidden;
   white-space: nowrap;
-  word-break: break-all;
+  word-break: break-word;
 }
 /****添加计算宽度的--运算符直接需要space****/
 /****** common color(常用颜色,可用于普遍场景) *****/
diff --git a/dist/core.js b/dist/core.js
index efa58d6bb2..b3875a09c7 100644
--- a/dist/core.js
+++ b/dist/core.js
@@ -13052,7 +13052,7 @@ if (!window.BI) {
         },
 
         formatEL: function (obj) {
-            if (obj && obj.el) {
+            if (obj && !obj.type && obj.el) {
                 return obj;
             }
             return {
@@ -14011,9 +14011,8 @@ if (!window.BI) {
 
 
                 option.data = BI.cjkEncodeDO(option.data);
-                    
-                    
-                
+
+
                 $.ajax({
                     url: option.url,
                     type: "POST",
@@ -14370,7 +14369,8 @@ BI.Widget = BI.inherit(BI.OB, {
 
     mounted: null,
 
-    update: null,
+    update: function () {
+    },
 
     destroyed: null,
 
@@ -14594,7 +14594,7 @@ BI.Widget = BI.inherit(BI.OB, {
         }
         widget._setParent && widget._setParent(this);
         widget.on(BI.Events.DESTROY, function () {
-            delete self._children[name]
+            BI.remove(self._children, this);
         });
         return (this._children[name] = widget);
     },
@@ -19578,9 +19578,9 @@ BI.Layout = BI.inherit(BI.Widget, {
         }
 
         var child = this._children[this._getChildName(index)];
-        if (child.update) {
-            child.update(this._getOptions(item));
-            return true;
+        var updated;
+        if (updated = child.update(this._getOptions(item))) {
+            return updated;
         }
         var del = this._children[this._getChildName(index)];
         delete this._children[this._getChildName(index)];
diff --git a/src/core/base.js b/src/core/base.js
index ddfe30fa98..e91ddc1643 100644
--- a/src/core/base.js
+++ b/src/core/base.js
@@ -141,7 +141,7 @@ if (!window.BI) {
         },
 
         formatEL: function (obj) {
-            if (obj && obj.el) {
+            if (obj && !obj.type && obj.el) {
                 return obj;
             }
             return {
@@ -1100,9 +1100,8 @@ if (!window.BI) {
 
 
                 option.data = BI.cjkEncodeDO(option.data);
-                    
-                    
-                
+
+
                 $.ajax({
                     url: option.url,
                     type: "POST",
diff --git a/src/core/widget.js b/src/core/widget.js
index 2f4f3d3902..dcc30ec9dc 100644
--- a/src/core/widget.js
+++ b/src/core/widget.js
@@ -34,7 +34,8 @@ BI.Widget = BI.inherit(BI.OB, {
 
     mounted: null,
 
-    update: null,
+    update: function () {
+    },
 
     destroyed: null,
 
@@ -258,7 +259,7 @@ BI.Widget = BI.inherit(BI.OB, {
         }
         widget._setParent && widget._setParent(this);
         widget.on(BI.Events.DESTROY, function () {
-            delete self._children[name]
+            BI.remove(self._children, this);
         });
         return (this._children[name] = widget);
     },
diff --git a/src/core/wrapper/layout.js b/src/core/wrapper/layout.js
index f4b0dbd48b..5a4a6931fe 100644
--- a/src/core/wrapper/layout.js
+++ b/src/core/wrapper/layout.js
@@ -246,9 +246,9 @@ BI.Layout = BI.inherit(BI.Widget, {
         }
 
         var child = this._children[this._getChildName(index)];
-        if (child.update) {
-            child.update(this._getOptions(item));
-            return true;
+        var updated;
+        if (updated = child.update(this._getOptions(item))) {
+            return updated;
         }
         var del = this._children[this._getChildName(index)];
         delete this._children[this._getChildName(index)];

From 46a99d86835b9055a80c7742ac94502fb743b9ac Mon Sep 17 00:00:00 2001
From: windy <1374721899@qq.com>
Date: Wed, 29 Mar 2017 09:15:40 +0800
Subject: [PATCH 03/19] update

---
 src/base/combination/group.virtual.js | 4 ++--
 src/core/base.js                      | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/base/combination/group.virtual.js b/src/base/combination/group.virtual.js
index 48ebdcb104..03a356efb7 100644
--- a/src/base/combination/group.virtual.js
+++ b/src/base/combination/group.virtual.js
@@ -67,11 +67,11 @@ BI.VirtualGroup = BI.inherit(BI.Widget, {
         var self = this;
         items = items || [];
         this.options.items = items;
-        items = this._packageItems(items, this._packageBtns(items));
+        items = this._packageBtns(items);
         if (!this.layouts) {
             this.layouts = BI.createWidget(BI.extend({element: this}, this._packageLayout(items)));
         } else {
-            this.layouts.populate(this._packageLayout(items).items);
+            this.layouts.populate(items);
         }
     }
 });
diff --git a/src/core/base.js b/src/core/base.js
index ddfe30fa98..1c14fc7adc 100644
--- a/src/core/base.js
+++ b/src/core/base.js
@@ -141,7 +141,7 @@ if (!window.BI) {
         },
 
         formatEL: function (obj) {
-            if (obj && obj.el) {
+            if (obj && !obj.type && obj.el) {
                 return obj;
             }
             return {

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 04/19] 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 bb559fde40..27f3b48453 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 0000000000..786f2200cd
--- /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 0000000000..d6ce85bfe0
--- /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 0000000000..572dd0e128
--- /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 0000000000..2143aa9ffc
--- /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 0000000000..e0020f38cf
--- /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 0000000000..a1c24a0e8f
--- /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 0000000000..6dc7b39e5b
--- /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

From 3a943e43ee3c4569f031b78bf18a4f7e3e176c0a Mon Sep 17 00:00:00 2001
From: windy <1374721899@qq.com>
Date: Wed, 29 Mar 2017 11:19:22 +0800
Subject: [PATCH 05/19] update

---
 bi/widget.js                                  | 664 ------------------
 demo/js/config/widget.js                      |   4 -
 demo/js/widget/demo.filterpane.js             |  45 --
 dist/widget.js                                | 664 ------------------
 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 --
 10 files changed, 2047 deletions(-)
 delete mode 100644 demo/js/widget/demo.filterpane.js
 delete mode 100644 src/widget/filterpane/abstract.item.filter.js
 delete mode 100644 src/widget/filterpane/expander.filter.js
 delete mode 100644 src/widget/filterpane/filter.js
 delete mode 100644 src/widget/filterpane/filter.list.js
 delete mode 100644 src/widget/filterpane/operation.filter.js
 delete mode 100644 src/widget/filterpane/pane.filter.js

diff --git a/bi/widget.js b/bi/widget.js
index 905245cf0d..fec31d1b5f 100644
--- a/bi/widget.js
+++ b/bi/widget.js
@@ -7017,670 +7017,6 @@ BI.extend(BI.FileManagerNav, {
 });
 BI.FileManagerNav.EVENT_CHANGE = "FileManagerNav.EVENT_CHANGE";
 BI.shortcut("bi.file_manager_nav", BI.FileManagerNav);/**
- * 过滤条件抽象类
- *
- * @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);
-    }
-});/**
- * @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);/**
- * 过滤
- *
- * 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);/**
- * 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);/**
- * 过滤条件
- *
- * 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);/**
- * @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);/**
  * Created by windy on 2017/3/13.
  * 数值微调器
  */
diff --git a/demo/js/config/widget.js b/demo/js/config/widget.js
index 27f3b48453..bb559fde40 100644
--- a/demo/js/config/widget.js
+++ b/demo/js/config/widget.js
@@ -25,8 +25,4 @@ 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
deleted file mode 100644
index 786f2200cd..0000000000
--- a/demo/js/widget/demo.filterpane.js
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * 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/dist/widget.js b/dist/widget.js
index 905245cf0d..fec31d1b5f 100644
--- a/dist/widget.js
+++ b/dist/widget.js
@@ -7017,670 +7017,6 @@ BI.extend(BI.FileManagerNav, {
 });
 BI.FileManagerNav.EVENT_CHANGE = "FileManagerNav.EVENT_CHANGE";
 BI.shortcut("bi.file_manager_nav", BI.FileManagerNav);/**
- * 过滤条件抽象类
- *
- * @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);
-    }
-});/**
- * @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);/**
- * 过滤
- *
- * 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);/**
- * 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);/**
- * 过滤条件
- *
- * 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);/**
- * @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);/**
  * Created by windy on 2017/3/13.
  * 数值微调器
  */
diff --git a/src/widget/filterpane/abstract.item.filter.js b/src/widget/filterpane/abstract.item.filter.js
deleted file mode 100644
index d6ce85bfe0..0000000000
--- a/src/widget/filterpane/abstract.item.filter.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * 过滤条件抽象类
- *
- * @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
deleted file mode 100644
index 572dd0e128..0000000000
--- a/src/widget/filterpane/expander.filter.js
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * @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
deleted file mode 100644
index 2143aa9ffc..0000000000
--- a/src/widget/filterpane/filter.js
+++ /dev/null
@@ -1,188 +0,0 @@
-/**
- * 过滤
- *
- * 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
deleted file mode 100644
index e0020f38cf..0000000000
--- a/src/widget/filterpane/filter.list.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * 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
deleted file mode 100644
index a1c24a0e8f..0000000000
--- a/src/widget/filterpane/operation.filter.js
+++ /dev/null
@@ -1,240 +0,0 @@
-/**
- * 过滤条件
- *
- * 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
deleted file mode 100644
index 6dc7b39e5b..0000000000
--- a/src/widget/filterpane/pane.filter.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * @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

From 59f546ba3f1bd521dfaa2a3b65b16b0fc1dc34c9 Mon Sep 17 00:00:00 2001
From: guy <guy@finereport.com>
Date: Wed, 29 Mar 2017 17:00:57 +0800
Subject: [PATCH 06/19] =?UTF-8?q?=E6=95=B4=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 bi/base.js                             |  4 ++
 bi/core.js                             | 59 ++++++++++++++++----------
 dist/base.js                           |  4 ++
 dist/core.js                           | 59 ++++++++++++++++----------
 src/base/combination/group.virtual.js  |  4 ++
 src/core/view.js                       | 12 ------
 src/core/widget.js                     |  2 +-
 src/core/wrapper/layout.js             | 11 +++--
 src/core/wrapper/layout/layout.card.js | 34 ++++++++++++---
 9 files changed, 123 insertions(+), 66 deletions(-)

diff --git a/bi/base.js b/bi/base.js
index 77e8690095..e5b2ba8977 100644
--- a/bi/base.js
+++ b/bi/base.js
@@ -3632,6 +3632,10 @@ BI.shortcut("bi.combo_group", BI.ComboGroup);BI.VirtualGroup = BI.inherit(BI.Wid
         return this.layouts.getValue();
     },
 
+    empty: function () {
+        this.layouts.empty();
+    },
+
     populate: function (items) {
         var self = this;
         items = items || [];
diff --git a/bi/core.js b/bi/core.js
index dad5b489de..8e63aed81c 100644
--- a/bi/core.js
+++ b/bi/core.js
@@ -4795,8 +4795,8 @@ BI.Widget = BI.inherit(BI.OB, {
     isolate: function () {
         if (this._parent) {
             this._parent.removeWidget(this);
-            BI.DOM.hang([this]);
         }
+        BI.DOM.hang([this]);
     },
 
     empty: function () {
@@ -5649,18 +5649,6 @@ BI.View = BI.inherit(BI.V, {
         return this.model.getEditing();
     },
 
-    read: function (options) {
-        this.model.read(options)
-    },
-
-    update: function (options) {
-        this.model.update(options);
-    },
-
-    patch: function (options) {
-        this.model.patch(options);
-    },
-
     reading: function (options) {
         var self = this;
         var name = BI.UUID();
@@ -11526,8 +11514,8 @@ BI.Layout = BI.inherit(BI.Widget, {
 
     update: function (item) {
         var o = this.options;
-        var items = item.items;
-        var updated = false, i, len;
+        var items = item.items || [];
+        var updated, i, len;
         for (i = 0, len = Math.min(o.items.length, items.length); i < len; i++) {
             if (!this._compare(o.items[i], items[i])) {
                 updated = this.updateItemAt(i, items[i]) || updated;
@@ -11538,6 +11526,7 @@ BI.Layout = BI.inherit(BI.Widget, {
             for (i = items.length; i < o.items.length; i++) {
                 deleted.push(this._children[this._getChildName(i)]);
             }
+            o.items.splice(items.length);
             BI.each(deleted, function (i, w) {
                 w.destroy();
             })
@@ -11546,7 +11535,6 @@ BI.Layout = BI.inherit(BI.Widget, {
                 this.addItemAt(i, items[i]);
             }
         }
-        this.options.items = items;
         return updated;
     },
 
@@ -11580,6 +11568,11 @@ BI.Layout = BI.inherit(BI.Widget, {
         this.options.items = [];
     },
 
+    destroy: function () {
+        BI.Layout.superclass.destroy.apply(this, arguments);
+        this.options.items = [];
+    },
+
     populate: function (items) {
         var self = this, o = this.options;
         items = items || [];
@@ -13371,7 +13364,7 @@ BI.CardLayout = BI.inherit(BI.Layout, {
                 if (!self.hasWidget(item.cardName)) {
                     var w = BI.createWidget(item);
                     w.on(BI.Events.DESTROY, function () {
-                        var index = BI.findKey(o.items, function (i, tItem) {
+                        var index = BI.findIndex(o.items, function (i, tItem) {
                             return tItem.cardName == item.cardName;
                         });
                         if (index > -1) {
@@ -13415,17 +13408,23 @@ BI.CardLayout = BI.inherit(BI.Layout, {
         return this._children[cardName];
     },
 
-    deleteCardByName: function (cardName) {
-        if (!this.isCardExisted(cardName)) {
-            throw new Error("cardName is not exist");
-        }
-        var index = BI.findKey(this.options.items, function (i, item) {
+    _deleteCardByName: function (cardName) {
+        delete this._children[cardName];
+        var index = BI.findIndex(this.options.items, function (i, item) {
             return item.cardName == cardName;
         });
         if (index > -1) {
             this.options.items.splice(index, 1);
         }
+    },
+
+    deleteCardByName: function (cardName) {
+        if (!this.isCardExisted(cardName)) {
+            throw new Error("cardName is not exist");
+        }
+
         var child = this._children[cardName];
+        this._deleteCardByName(cardName);
         child && child.destroy();
     },
 
@@ -13521,6 +13520,22 @@ BI.CardLayout = BI.inherit(BI.Layout, {
             }
         });
         return flag;
+    },
+
+    removeWidget: function (nameOrWidget) {
+        var removeName;
+        if (BI.isWidget(nameOrWidget)) {
+            BI.each(this._children, function (name, child) {
+                if (child === nameOrWidget) {
+                    removeName = name;
+                }
+            })
+        } else {
+            removeName = nameOrWidget;
+        }
+        if (removeName) {
+            this._deleteCardByName(removeName);
+        }
     }
 });
 BI.shortcut('bi.card', BI.CardLayout);/**
diff --git a/dist/base.js b/dist/base.js
index 77e8690095..e5b2ba8977 100644
--- a/dist/base.js
+++ b/dist/base.js
@@ -3632,6 +3632,10 @@ BI.shortcut("bi.combo_group", BI.ComboGroup);BI.VirtualGroup = BI.inherit(BI.Wid
         return this.layouts.getValue();
     },
 
+    empty: function () {
+        this.layouts.empty();
+    },
+
     populate: function (items) {
         var self = this;
         items = items || [];
diff --git a/dist/core.js b/dist/core.js
index b3875a09c7..dd5cdda0ac 100644
--- a/dist/core.js
+++ b/dist/core.js
@@ -14707,8 +14707,8 @@ BI.Widget = BI.inherit(BI.OB, {
     isolate: function () {
         if (this._parent) {
             this._parent.removeWidget(this);
-            BI.DOM.hang([this]);
         }
+        BI.DOM.hang([this]);
     },
 
     empty: function () {
@@ -15561,18 +15561,6 @@ BI.View = BI.inherit(BI.V, {
         return this.model.getEditing();
     },
 
-    read: function (options) {
-        this.model.read(options)
-    },
-
-    update: function (options) {
-        this.model.update(options);
-    },
-
-    patch: function (options) {
-        this.model.patch(options);
-    },
-
     reading: function (options) {
         var self = this;
         var name = BI.UUID();
@@ -19659,8 +19647,8 @@ BI.Layout = BI.inherit(BI.Widget, {
 
     update: function (item) {
         var o = this.options;
-        var items = item.items;
-        var updated = false, i, len;
+        var items = item.items || [];
+        var updated, i, len;
         for (i = 0, len = Math.min(o.items.length, items.length); i < len; i++) {
             if (!this._compare(o.items[i], items[i])) {
                 updated = this.updateItemAt(i, items[i]) || updated;
@@ -19671,6 +19659,7 @@ BI.Layout = BI.inherit(BI.Widget, {
             for (i = items.length; i < o.items.length; i++) {
                 deleted.push(this._children[this._getChildName(i)]);
             }
+            o.items.splice(items.length);
             BI.each(deleted, function (i, w) {
                 w.destroy();
             })
@@ -19679,7 +19668,6 @@ BI.Layout = BI.inherit(BI.Widget, {
                 this.addItemAt(i, items[i]);
             }
         }
-        this.options.items = items;
         return updated;
     },
 
@@ -19713,6 +19701,11 @@ BI.Layout = BI.inherit(BI.Widget, {
         this.options.items = [];
     },
 
+    destroy: function () {
+        BI.Layout.superclass.destroy.apply(this, arguments);
+        this.options.items = [];
+    },
+
     populate: function (items) {
         var self = this, o = this.options;
         items = items || [];
@@ -26785,7 +26778,7 @@ BI.CardLayout = BI.inherit(BI.Layout, {
                 if (!self.hasWidget(item.cardName)) {
                     var w = BI.createWidget(item);
                     w.on(BI.Events.DESTROY, function () {
-                        var index = BI.findKey(o.items, function (i, tItem) {
+                        var index = BI.findIndex(o.items, function (i, tItem) {
                             return tItem.cardName == item.cardName;
                         });
                         if (index > -1) {
@@ -26829,17 +26822,23 @@ BI.CardLayout = BI.inherit(BI.Layout, {
         return this._children[cardName];
     },
 
-    deleteCardByName: function (cardName) {
-        if (!this.isCardExisted(cardName)) {
-            throw new Error("cardName is not exist");
-        }
-        var index = BI.findKey(this.options.items, function (i, item) {
+    _deleteCardByName: function (cardName) {
+        delete this._children[cardName];
+        var index = BI.findIndex(this.options.items, function (i, item) {
             return item.cardName == cardName;
         });
         if (index > -1) {
             this.options.items.splice(index, 1);
         }
+    },
+
+    deleteCardByName: function (cardName) {
+        if (!this.isCardExisted(cardName)) {
+            throw new Error("cardName is not exist");
+        }
+
         var child = this._children[cardName];
+        this._deleteCardByName(cardName);
         child && child.destroy();
     },
 
@@ -26935,6 +26934,22 @@ BI.CardLayout = BI.inherit(BI.Layout, {
             }
         });
         return flag;
+    },
+
+    removeWidget: function (nameOrWidget) {
+        var removeName;
+        if (BI.isWidget(nameOrWidget)) {
+            BI.each(this._children, function (name, child) {
+                if (child === nameOrWidget) {
+                    removeName = name;
+                }
+            })
+        } else {
+            removeName = nameOrWidget;
+        }
+        if (removeName) {
+            this._deleteCardByName(removeName);
+        }
     }
 });
 BI.shortcut('bi.card', BI.CardLayout);/**
diff --git a/src/base/combination/group.virtual.js b/src/base/combination/group.virtual.js
index 48ebdcb104..5ffe00d42c 100644
--- a/src/base/combination/group.virtual.js
+++ b/src/base/combination/group.virtual.js
@@ -63,6 +63,10 @@ BI.VirtualGroup = BI.inherit(BI.Widget, {
         return this.layouts.getValue();
     },
 
+    empty: function () {
+        this.layouts.empty();
+    },
+
     populate: function (items) {
         var self = this;
         items = items || [];
diff --git a/src/core/view.js b/src/core/view.js
index 5dcab2c4ff..baac6b554b 100644
--- a/src/core/view.js
+++ b/src/core/view.js
@@ -369,18 +369,6 @@ BI.View = BI.inherit(BI.V, {
         return this.model.getEditing();
     },
 
-    read: function (options) {
-        this.model.read(options)
-    },
-
-    update: function (options) {
-        this.model.update(options);
-    },
-
-    patch: function (options) {
-        this.model.patch(options);
-    },
-
     reading: function (options) {
         var self = this;
         var name = BI.UUID();
diff --git a/src/core/widget.js b/src/core/widget.js
index dcc30ec9dc..7c478c31d6 100644
--- a/src/core/widget.js
+++ b/src/core/widget.js
@@ -372,8 +372,8 @@ BI.Widget = BI.inherit(BI.OB, {
     isolate: function () {
         if (this._parent) {
             this._parent.removeWidget(this);
-            BI.DOM.hang([this]);
         }
+        BI.DOM.hang([this]);
     },
 
     empty: function () {
diff --git a/src/core/wrapper/layout.js b/src/core/wrapper/layout.js
index 5a4a6931fe..f4f76a5c0a 100644
--- a/src/core/wrapper/layout.js
+++ b/src/core/wrapper/layout.js
@@ -327,8 +327,8 @@ BI.Layout = BI.inherit(BI.Widget, {
 
     update: function (item) {
         var o = this.options;
-        var items = item.items;
-        var updated = false, i, len;
+        var items = item.items || [];
+        var updated, i, len;
         for (i = 0, len = Math.min(o.items.length, items.length); i < len; i++) {
             if (!this._compare(o.items[i], items[i])) {
                 updated = this.updateItemAt(i, items[i]) || updated;
@@ -339,6 +339,7 @@ BI.Layout = BI.inherit(BI.Widget, {
             for (i = items.length; i < o.items.length; i++) {
                 deleted.push(this._children[this._getChildName(i)]);
             }
+            o.items.splice(items.length);
             BI.each(deleted, function (i, w) {
                 w.destroy();
             })
@@ -347,7 +348,6 @@ BI.Layout = BI.inherit(BI.Widget, {
                 this.addItemAt(i, items[i]);
             }
         }
-        this.options.items = items;
         return updated;
     },
 
@@ -381,6 +381,11 @@ BI.Layout = BI.inherit(BI.Widget, {
         this.options.items = [];
     },
 
+    destroy: function () {
+        BI.Layout.superclass.destroy.apply(this, arguments);
+        this.options.items = [];
+    },
+
     populate: function (items) {
         var self = this, o = this.options;
         items = items || [];
diff --git a/src/core/wrapper/layout/layout.card.js b/src/core/wrapper/layout/layout.card.js
index 9711da9e2e..73d466dbc4 100644
--- a/src/core/wrapper/layout/layout.card.js
+++ b/src/core/wrapper/layout/layout.card.js
@@ -30,7 +30,7 @@ BI.CardLayout = BI.inherit(BI.Layout, {
                 if (!self.hasWidget(item.cardName)) {
                     var w = BI.createWidget(item);
                     w.on(BI.Events.DESTROY, function () {
-                        var index = BI.findKey(o.items, function (i, tItem) {
+                        var index = BI.findIndex(o.items, function (i, tItem) {
                             return tItem.cardName == item.cardName;
                         });
                         if (index > -1) {
@@ -74,17 +74,23 @@ BI.CardLayout = BI.inherit(BI.Layout, {
         return this._children[cardName];
     },
 
-    deleteCardByName: function (cardName) {
-        if (!this.isCardExisted(cardName)) {
-            throw new Error("cardName is not exist");
-        }
-        var index = BI.findKey(this.options.items, function (i, item) {
+    _deleteCardByName: function (cardName) {
+        delete this._children[cardName];
+        var index = BI.findIndex(this.options.items, function (i, item) {
             return item.cardName == cardName;
         });
         if (index > -1) {
             this.options.items.splice(index, 1);
         }
+    },
+
+    deleteCardByName: function (cardName) {
+        if (!this.isCardExisted(cardName)) {
+            throw new Error("cardName is not exist");
+        }
+
         var child = this._children[cardName];
+        this._deleteCardByName(cardName);
         child && child.destroy();
     },
 
@@ -180,6 +186,22 @@ BI.CardLayout = BI.inherit(BI.Layout, {
             }
         });
         return flag;
+    },
+
+    removeWidget: function (nameOrWidget) {
+        var removeName;
+        if (BI.isWidget(nameOrWidget)) {
+            BI.each(this._children, function (name, child) {
+                if (child === nameOrWidget) {
+                    removeName = name;
+                }
+            })
+        } else {
+            removeName = nameOrWidget;
+        }
+        if (removeName) {
+            this._deleteCardByName(removeName);
+        }
     }
 });
 BI.shortcut('bi.card', BI.CardLayout);
\ No newline at end of file

From 1f6e01399914ae2b8ed2cbe694ed8bda4e923e53 Mon Sep 17 00:00:00 2001
From: guy <guy@finereport.com>
Date: Wed, 29 Mar 2017 20:25:30 +0800
Subject: [PATCH 07/19] add

---
 bi/base.js                           |  4 ++-
 bi/core.js                           | 40 +++++++++++++++-------------
 dist/base.js                         |  4 ++-
 dist/core.js                         | 40 +++++++++++++++-------------
 src/base/combination/group.button.js |  4 ++-
 src/core/view.js                     |  8 +++---
 src/core/widget.js                   |  6 +----
 src/core/wrapper/layout.js           | 26 +++++++++++-------
 8 files changed, 75 insertions(+), 57 deletions(-)

diff --git a/bi/base.js b/bi/base.js
index 100afaa6ce..959a0defcf 100644
--- a/bi/base.js
+++ b/bi/base.js
@@ -1020,9 +1020,11 @@ BI.ButtonGroup = BI.inherit(BI.Widget, {
                             self.setValue([]);
                             break;
                     }
+                    self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
                     self.fireEvent(BI.ButtonGroup.EVENT_CHANGE, value, obj);
+                } else {
+                    self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
                 }
-                self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
             });
             btn.on(BI.Events.DESTROY, function () {
                 BI.remove(self.buttons, btn);
diff --git a/bi/core.js b/bi/core.js
index 8e63aed81c..dcf9434540 100644
--- a/bi/core.js
+++ b/bi/core.js
@@ -4711,11 +4711,7 @@ BI.Widget = BI.inherit(BI.OB, {
     removeWidget: function (nameOrWidget) {
         var self = this;
         if (BI.isWidget(nameOrWidget)) {
-            BI.each(this._children, function (name, widget) {
-                if (widget === nameOrWidget) {
-                    delete self._children[name];
-                }
-            })
+            BI.remove(this._children, nameOrWidget);
         } else {
             delete this._children[nameOrWidget];
         }
@@ -5607,7 +5603,7 @@ BI.View = BI.inherit(BI.V, {
         }
         //采用静默方式读数据,该数据变化不引起data的change事件触发
         var success = options.success;
-        this.read(BI.extend({
+        this.model.read(BI.extend({
             silent: true
         }, options, {
             success: function (data, model) {
@@ -5652,7 +5648,7 @@ BI.View = BI.inherit(BI.V, {
     reading: function (options) {
         var self = this;
         var name = BI.UUID();
-        this.read(BI.extend({}, options, {
+        this.model.read(BI.extend({}, options, {
             beforeSend: function () {
                 var loading = BI.createWidget({
                     type: 'bi.vertical',
@@ -5675,7 +5671,7 @@ BI.View = BI.inherit(BI.V, {
     updating: function (options) {
         var self = this;
         var name = BI.UUID();
-        this.update(BI.extend({}, options, {
+        this.model.update(BI.extend({}, options, {
             noset: true,
             beforeSend: function () {
                 var loading = BI.createWidget({
@@ -5699,7 +5695,7 @@ BI.View = BI.inherit(BI.V, {
     patching: function (options) {
         var self = this;
         var name = BI.UUID();
-        this.patch(BI.extend({}, options, {
+        this.model.patch(BI.extend({}, options, {
             noset: true,
             beforeSend: function () {
                 var loading = BI.createWidget({
@@ -11261,6 +11257,7 @@ BI.Layout = BI.inherit(BI.Widget, {
             w.on(BI.Events.DESTROY, function () {
                 BI.each(self._children, function (name, child) {
                     if (child === w) {
+                        BI.remove(self._children, child);
                         self.removeItemAt(name | 0);
                     }
                 });
@@ -11414,7 +11411,7 @@ BI.Layout = BI.inherit(BI.Widget, {
         for (var i = 0, len = this.options.items.length; i < len; i++) {
             var child = this._children[this._getChildName(i)];
             if (indexes.contains(i)) {
-                deleted.push(child);
+                child && deleted.push(child);
             } else {
                 newChildren[this._getChildName(newItems.length)] = child;
                 newItems.push(this.options.items[i]);
@@ -11489,26 +11486,32 @@ BI.Layout = BI.inherit(BI.Widget, {
     },
 
     getValue: function () {
-        var self = this, value = [];
+        var self = this, value = [], child;
         BI.each(this.options.items, function (i) {
-            var v = self._children[self._getChildName(i)].getValue();
-            v = BI.isArray(v) ? v : [v];
-            value = value.concat(v);
+            if (child = self._children[self._getChildName(i)]) {
+                var v = child.getValue();
+                v = BI.isArray(v) ? v : [v];
+                value = value.concat(v);
+            }
         });
         return value;
     },
 
     setValue: function (v) {
-        var self = this;
+        var self = this, child;
         BI.each(this.options.items, function (i) {
-            self._children[self._getChildName(i)].setValue(v);
+            if (child = self._children[self._getChildName(i)]) {
+                child.setValue(v);
+            }
         })
     },
 
     setText: function (v) {
-        var self = this;
+        var self = this, child;
         BI.each(this.options.items, function (i) {
-            self._children[self._getChildName(i)].setText(v);
+            if (child = self._children[self._getChildName(i)]) {
+                child.setText(v);
+            }
         })
     },
 
@@ -11525,6 +11528,7 @@ BI.Layout = BI.inherit(BI.Widget, {
             var deleted = [];
             for (i = items.length; i < o.items.length; i++) {
                 deleted.push(this._children[this._getChildName(i)]);
+                delete this._children[this._getChildName(i)];
             }
             o.items.splice(items.length);
             BI.each(deleted, function (i, w) {
diff --git a/dist/base.js b/dist/base.js
index 100afaa6ce..959a0defcf 100644
--- a/dist/base.js
+++ b/dist/base.js
@@ -1020,9 +1020,11 @@ BI.ButtonGroup = BI.inherit(BI.Widget, {
                             self.setValue([]);
                             break;
                     }
+                    self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
                     self.fireEvent(BI.ButtonGroup.EVENT_CHANGE, value, obj);
+                } else {
+                    self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
                 }
-                self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
             });
             btn.on(BI.Events.DESTROY, function () {
                 BI.remove(self.buttons, btn);
diff --git a/dist/core.js b/dist/core.js
index dd5cdda0ac..2ccd75f2d4 100644
--- a/dist/core.js
+++ b/dist/core.js
@@ -14623,11 +14623,7 @@ BI.Widget = BI.inherit(BI.OB, {
     removeWidget: function (nameOrWidget) {
         var self = this;
         if (BI.isWidget(nameOrWidget)) {
-            BI.each(this._children, function (name, widget) {
-                if (widget === nameOrWidget) {
-                    delete self._children[name];
-                }
-            })
+            BI.remove(this._children, nameOrWidget);
         } else {
             delete this._children[nameOrWidget];
         }
@@ -15519,7 +15515,7 @@ BI.View = BI.inherit(BI.V, {
         }
         //采用静默方式读数据,该数据变化不引起data的change事件触发
         var success = options.success;
-        this.read(BI.extend({
+        this.model.read(BI.extend({
             silent: true
         }, options, {
             success: function (data, model) {
@@ -15564,7 +15560,7 @@ BI.View = BI.inherit(BI.V, {
     reading: function (options) {
         var self = this;
         var name = BI.UUID();
-        this.read(BI.extend({}, options, {
+        this.model.read(BI.extend({}, options, {
             beforeSend: function () {
                 var loading = BI.createWidget({
                     type: 'bi.vertical',
@@ -15587,7 +15583,7 @@ BI.View = BI.inherit(BI.V, {
     updating: function (options) {
         var self = this;
         var name = BI.UUID();
-        this.update(BI.extend({}, options, {
+        this.model.update(BI.extend({}, options, {
             noset: true,
             beforeSend: function () {
                 var loading = BI.createWidget({
@@ -15611,7 +15607,7 @@ BI.View = BI.inherit(BI.V, {
     patching: function (options) {
         var self = this;
         var name = BI.UUID();
-        this.patch(BI.extend({}, options, {
+        this.model.patch(BI.extend({}, options, {
             noset: true,
             beforeSend: function () {
                 var loading = BI.createWidget({
@@ -19394,6 +19390,7 @@ BI.Layout = BI.inherit(BI.Widget, {
             w.on(BI.Events.DESTROY, function () {
                 BI.each(self._children, function (name, child) {
                     if (child === w) {
+                        BI.remove(self._children, child);
                         self.removeItemAt(name | 0);
                     }
                 });
@@ -19547,7 +19544,7 @@ BI.Layout = BI.inherit(BI.Widget, {
         for (var i = 0, len = this.options.items.length; i < len; i++) {
             var child = this._children[this._getChildName(i)];
             if (indexes.contains(i)) {
-                deleted.push(child);
+                child && deleted.push(child);
             } else {
                 newChildren[this._getChildName(newItems.length)] = child;
                 newItems.push(this.options.items[i]);
@@ -19622,26 +19619,32 @@ BI.Layout = BI.inherit(BI.Widget, {
     },
 
     getValue: function () {
-        var self = this, value = [];
+        var self = this, value = [], child;
         BI.each(this.options.items, function (i) {
-            var v = self._children[self._getChildName(i)].getValue();
-            v = BI.isArray(v) ? v : [v];
-            value = value.concat(v);
+            if (child = self._children[self._getChildName(i)]) {
+                var v = child.getValue();
+                v = BI.isArray(v) ? v : [v];
+                value = value.concat(v);
+            }
         });
         return value;
     },
 
     setValue: function (v) {
-        var self = this;
+        var self = this, child;
         BI.each(this.options.items, function (i) {
-            self._children[self._getChildName(i)].setValue(v);
+            if (child = self._children[self._getChildName(i)]) {
+                child.setValue(v);
+            }
         })
     },
 
     setText: function (v) {
-        var self = this;
+        var self = this, child;
         BI.each(this.options.items, function (i) {
-            self._children[self._getChildName(i)].setText(v);
+            if (child = self._children[self._getChildName(i)]) {
+                child.setText(v);
+            }
         })
     },
 
@@ -19658,6 +19661,7 @@ BI.Layout = BI.inherit(BI.Widget, {
             var deleted = [];
             for (i = items.length; i < o.items.length; i++) {
                 deleted.push(this._children[this._getChildName(i)]);
+                delete this._children[this._getChildName(i)];
             }
             o.items.splice(items.length);
             BI.each(deleted, function (i, w) {
diff --git a/src/base/combination/group.button.js b/src/base/combination/group.button.js
index d4d7ad2787..353f18cd0f 100644
--- a/src/base/combination/group.button.js
+++ b/src/base/combination/group.button.js
@@ -57,9 +57,11 @@ BI.ButtonGroup = BI.inherit(BI.Widget, {
                             self.setValue([]);
                             break;
                     }
+                    self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
                     self.fireEvent(BI.ButtonGroup.EVENT_CHANGE, value, obj);
+                } else {
+                    self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
                 }
-                self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
             });
             btn.on(BI.Events.DESTROY, function () {
                 BI.remove(self.buttons, btn);
diff --git a/src/core/view.js b/src/core/view.js
index baac6b554b..c0ae68237d 100644
--- a/src/core/view.js
+++ b/src/core/view.js
@@ -327,7 +327,7 @@ BI.View = BI.inherit(BI.V, {
         }
         //采用静默方式读数据,该数据变化不引起data的change事件触发
         var success = options.success;
-        this.read(BI.extend({
+        this.model.read(BI.extend({
             silent: true
         }, options, {
             success: function (data, model) {
@@ -372,7 +372,7 @@ BI.View = BI.inherit(BI.V, {
     reading: function (options) {
         var self = this;
         var name = BI.UUID();
-        this.read(BI.extend({}, options, {
+        this.model.read(BI.extend({}, options, {
             beforeSend: function () {
                 var loading = BI.createWidget({
                     type: 'bi.vertical',
@@ -395,7 +395,7 @@ BI.View = BI.inherit(BI.V, {
     updating: function (options) {
         var self = this;
         var name = BI.UUID();
-        this.update(BI.extend({}, options, {
+        this.model.update(BI.extend({}, options, {
             noset: true,
             beforeSend: function () {
                 var loading = BI.createWidget({
@@ -419,7 +419,7 @@ BI.View = BI.inherit(BI.V, {
     patching: function (options) {
         var self = this;
         var name = BI.UUID();
-        this.patch(BI.extend({}, options, {
+        this.model.patch(BI.extend({}, options, {
             noset: true,
             beforeSend: function () {
                 var loading = BI.createWidget({
diff --git a/src/core/widget.js b/src/core/widget.js
index 7c478c31d6..693734fc91 100644
--- a/src/core/widget.js
+++ b/src/core/widget.js
@@ -288,11 +288,7 @@ BI.Widget = BI.inherit(BI.OB, {
     removeWidget: function (nameOrWidget) {
         var self = this;
         if (BI.isWidget(nameOrWidget)) {
-            BI.each(this._children, function (name, widget) {
-                if (widget === nameOrWidget) {
-                    delete self._children[name];
-                }
-            })
+            BI.remove(this._children, nameOrWidget);
         } else {
             delete this._children[nameOrWidget];
         }
diff --git a/src/core/wrapper/layout.js b/src/core/wrapper/layout.js
index f4f76a5c0a..cf23c39745 100644
--- a/src/core/wrapper/layout.js
+++ b/src/core/wrapper/layout.js
@@ -74,6 +74,7 @@ BI.Layout = BI.inherit(BI.Widget, {
             w.on(BI.Events.DESTROY, function () {
                 BI.each(self._children, function (name, child) {
                     if (child === w) {
+                        BI.remove(self._children, child);
                         self.removeItemAt(name | 0);
                     }
                 });
@@ -227,7 +228,7 @@ BI.Layout = BI.inherit(BI.Widget, {
         for (var i = 0, len = this.options.items.length; i < len; i++) {
             var child = this._children[this._getChildName(i)];
             if (indexes.contains(i)) {
-                deleted.push(child);
+                child && deleted.push(child);
             } else {
                 newChildren[this._getChildName(newItems.length)] = child;
                 newItems.push(this.options.items[i]);
@@ -302,26 +303,32 @@ BI.Layout = BI.inherit(BI.Widget, {
     },
 
     getValue: function () {
-        var self = this, value = [];
+        var self = this, value = [], child;
         BI.each(this.options.items, function (i) {
-            var v = self._children[self._getChildName(i)].getValue();
-            v = BI.isArray(v) ? v : [v];
-            value = value.concat(v);
+            if (child = self._children[self._getChildName(i)]) {
+                var v = child.getValue();
+                v = BI.isArray(v) ? v : [v];
+                value = value.concat(v);
+            }
         });
         return value;
     },
 
     setValue: function (v) {
-        var self = this;
+        var self = this, child;
         BI.each(this.options.items, function (i) {
-            self._children[self._getChildName(i)].setValue(v);
+            if (child = self._children[self._getChildName(i)]) {
+                child.setValue(v);
+            }
         })
     },
 
     setText: function (v) {
-        var self = this;
+        var self = this, child;
         BI.each(this.options.items, function (i) {
-            self._children[self._getChildName(i)].setText(v);
+            if (child = self._children[self._getChildName(i)]) {
+                child.setText(v);
+            }
         })
     },
 
@@ -338,6 +345,7 @@ BI.Layout = BI.inherit(BI.Widget, {
             var deleted = [];
             for (i = items.length; i < o.items.length; i++) {
                 deleted.push(this._children[this._getChildName(i)]);
+                delete this._children[this._getChildName(i)];
             }
             o.items.splice(items.length);
             BI.each(deleted, function (i, w) {

From 22933f334e44e9690139ec460a3cc83ef8fdc451 Mon Sep 17 00:00:00 2001
From: guy <guy@finereport.com>
Date: Wed, 29 Mar 2017 20:28:42 +0800
Subject: [PATCH 08/19] add

---
 bi/core.js                             | 12 +++++++-----
 dist/core.js                           | 12 +++++++-----
 src/core/wrapper/layout/layout.card.js | 12 +++++++-----
 3 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/bi/core.js b/bi/core.js
index dcf9434540..b8335b3789 100644
--- a/bi/core.js
+++ b/bi/core.js
@@ -13461,11 +13461,13 @@ BI.CardLayout = BI.inherit(BI.Layout, {
         var flag = false;
         BI.each(this.options.items, function (i, item) {
             var el = self._children[item.cardName];
-            if (name != item.cardName) {
-                //动画效果只有在全部都隐藏的时候才有意义,且只要执行一次动画操作就够了
-                !flag && !exist && (BI.Action && action instanceof BI.Action) ? (action.actionBack(el), flag = true) : el.invisible();
-            } else {
-                (BI.Action && action instanceof BI.Action) ? action.actionPerformed(void 0, el, callback) : (el.visible(), callback && callback())
+            if (el) {
+                if (name != item.cardName) {
+                    //动画效果只有在全部都隐藏的时候才有意义,且只要执行一次动画操作就够了
+                    !flag && !exist && (BI.Action && action instanceof BI.Action) ? (action.actionBack(el), flag = true) : el.invisible();
+                } else {
+                    (BI.Action && action instanceof BI.Action) ? action.actionPerformed(void 0, el, callback) : (el.visible(), callback && callback())
+                }
             }
         });
     },
diff --git a/dist/core.js b/dist/core.js
index 2ccd75f2d4..f426c41a0b 100644
--- a/dist/core.js
+++ b/dist/core.js
@@ -26875,11 +26875,13 @@ BI.CardLayout = BI.inherit(BI.Layout, {
         var flag = false;
         BI.each(this.options.items, function (i, item) {
             var el = self._children[item.cardName];
-            if (name != item.cardName) {
-                //动画效果只有在全部都隐藏的时候才有意义,且只要执行一次动画操作就够了
-                !flag && !exist && (BI.Action && action instanceof BI.Action) ? (action.actionBack(el), flag = true) : el.invisible();
-            } else {
-                (BI.Action && action instanceof BI.Action) ? action.actionPerformed(void 0, el, callback) : (el.visible(), callback && callback())
+            if (el) {
+                if (name != item.cardName) {
+                    //动画效果只有在全部都隐藏的时候才有意义,且只要执行一次动画操作就够了
+                    !flag && !exist && (BI.Action && action instanceof BI.Action) ? (action.actionBack(el), flag = true) : el.invisible();
+                } else {
+                    (BI.Action && action instanceof BI.Action) ? action.actionPerformed(void 0, el, callback) : (el.visible(), callback && callback())
+                }
             }
         });
     },
diff --git a/src/core/wrapper/layout/layout.card.js b/src/core/wrapper/layout/layout.card.js
index 73d466dbc4..aa0921291d 100644
--- a/src/core/wrapper/layout/layout.card.js
+++ b/src/core/wrapper/layout/layout.card.js
@@ -123,11 +123,13 @@ BI.CardLayout = BI.inherit(BI.Layout, {
         var flag = false;
         BI.each(this.options.items, function (i, item) {
             var el = self._children[item.cardName];
-            if (name != item.cardName) {
-                //动画效果只有在全部都隐藏的时候才有意义,且只要执行一次动画操作就够了
-                !flag && !exist && (BI.Action && action instanceof BI.Action) ? (action.actionBack(el), flag = true) : el.invisible();
-            } else {
-                (BI.Action && action instanceof BI.Action) ? action.actionPerformed(void 0, el, callback) : (el.visible(), callback && callback())
+            if (el) {
+                if (name != item.cardName) {
+                    //动画效果只有在全部都隐藏的时候才有意义,且只要执行一次动画操作就够了
+                    !flag && !exist && (BI.Action && action instanceof BI.Action) ? (action.actionBack(el), flag = true) : el.invisible();
+                } else {
+                    (BI.Action && action instanceof BI.Action) ? action.actionPerformed(void 0, el, callback) : (el.visible(), callback && callback())
+                }
             }
         });
     },

From 52c98fa24ba7c532237cd303a1e653fc29b75beb Mon Sep 17 00:00:00 2001
From: windy <1374721899@qq.com>
Date: Thu, 30 Mar 2017 11:58:54 +0800
Subject: [PATCH 09/19] update

---
 bi/core.js                                    | 80 +++++++++----------
 bi/widget.css                                 |  4 +-
 bi/widget.js                                  |  3 +-
 dist/core.js                                  | 80 +++++++++----------
 dist/widget.css                               |  4 +-
 dist/widget.js                                |  3 +-
 src/core/proto/date.js                        | 80 +++++++++----------
 .../finetuning.number.editor.css              |  4 +-
 .../finetuning.number.editor.less             |  4 +-
 src/widget/date/trigger.date.js               |  3 +-
 10 files changed, 135 insertions(+), 130 deletions(-)

diff --git a/bi/core.js b/bi/core.js
index b8335b3789..29b81c77f8 100644
--- a/bi/core.js
+++ b/bi/core.js
@@ -6301,56 +6301,56 @@ BI.Cache = {
         document.cookie = cookieString;
     }
 };// full day names
-Date._DN = [BI.i18nText("BI-Sunday"),
-    BI.i18nText("BI-Monday"),
-    BI.i18nText("BI-Tuesday"),
-    BI.i18nText("BI-Wednesday"),
-    BI.i18nText("BI-Thursday"),
-    BI.i18nText("BI-Friday"),
-    BI.i18nText("BI-Saturday"),
-    BI.i18nText("BI-Sunday")];
+Date._DN = [BI.i18nText("BI-Basic_Sunday"),
+    BI.i18nText("BI-Basic_Monday"),
+    BI.i18nText("BI-Basic_Tuesday"),
+    BI.i18nText("BI-Basic_Wednesday"),
+    BI.i18nText("BI-Basic_Thursday"),
+    BI.i18nText("BI-Basic_Friday"),
+    BI.i18nText("BI-Basic_Saturday"),
+    BI.i18nText("BI-Basic_Sunday")];
 
 // short day names
-Date._SDN = ['',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    ''];
+Date._SDN = [BI.i18nText("BI-Day_Ri"),
+    BI.i18nText("BI-Basic_One"),
+    BI.i18nText("BI-Basic_Two"),
+    BI.i18nText("BI-Basic_Three"),
+    BI.i18nText("BI-Basic_Four"),
+    BI.i18nText("BI-Basic_Five"),
+    BI.i18nText("BI-Basic_Six"),
+    BI.i18nText("BI-Day_Ri")];
 
 // Monday first, etc.
 Date._FD = 1;
 
 // full month names
 Date._MN = [
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    ''];
+    BI.i18nText("BI-Basic_January"),
+    BI.i18nText("BI-Basic_February"),
+    BI.i18nText("BI-Basic_March"),
+    BI.i18nText("BI-Basic_April"),
+    BI.i18nText("BI-Basic_May"),
+    BI.i18nText("BI-Basic_June"),
+    BI.i18nText("BI-Basic_July"),
+    BI.i18nText("BI-Basic_August"),
+    BI.i18nText("BI-Basic_September"),
+    BI.i18nText("BI-Basic_October"),
+    BI.i18nText("BI-Basic_November"),
+    BI.i18nText("BI-Basic_December")];
 
 // short month names
-Date._SMN = ['',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    ''];
+Date._SMN = [0,
+    1,
+    2,
+    3,
+    4,
+    5,
+    6,
+    7,
+    8,
+    9,
+    10,
+    11];
 
 Date._QN = ["", BI.i18nText("BI-Quarter_1"),
     BI.i18nText("BI-Quarter_2"),
diff --git a/bi/widget.css b/bi/widget.css
index 51d0750008..a048dd5bc5 100644
--- a/bi/widget.css
+++ b/bi/widget.css
@@ -233,11 +233,13 @@
 }
 .bi-fine-tuning-number-editor .top-button {
   border-left: 1px solid #d4dadd;
-  border-bottom: 1px solid #d4dadd;
 }
 .bi-fine-tuning-number-editor .bottom-button {
   border-left: 1px solid #d4dadd;
 }
+.bi-fine-tuning-number-editor .split-line {
+  background-color: #d4dadd;
+}
 /****添加计算宽度的--运算符直接需要space****/
 /****** common color(常用颜色,可用于普遍场景) *****/
 /**** custom color(自定义颜色,用于特定场景) ****/
diff --git a/bi/widget.js b/bi/widget.js
index fec31d1b5f..75b27e101c 100644
--- a/bi/widget.js
+++ b/bi/widget.js
@@ -4857,7 +4857,6 @@ BI.shortcut('bi.date_combo', BI.DateCombo);BI.DateTrigger = BI.inherit(BI.Trigge
         hgap: 4,
         vgap: 2,
         triggerWidth: 30,
-        watermark: BI.i18nText("BI-Unrestricted"),
         yearLength: 4,
         yearMonthLength: 7
     },
@@ -4891,7 +4890,7 @@ BI.shortcut('bi.date_combo', BI.DateCombo);BI.DateTrigger = BI.inherit(BI.Trigge
             hgap: c.hgap,
             vgap: c.vgap,
             allowBlank: true,
-            watermark: c.watermark,
+            watermark: BI.i18nText("BI-Unrestricted"),
             errorText: function () {
                 if (self.editor.isEditing()) {
                     return BI.i18nText("BI-Date_Trigger_Error_Text");
diff --git a/dist/core.js b/dist/core.js
index f426c41a0b..870551ae6e 100644
--- a/dist/core.js
+++ b/dist/core.js
@@ -23672,56 +23672,56 @@ BI.Cache = {
         document.cookie = cookieString;
     }
 };// full day names
-Date._DN = [BI.i18nText("BI-Sunday"),
-    BI.i18nText("BI-Monday"),
-    BI.i18nText("BI-Tuesday"),
-    BI.i18nText("BI-Wednesday"),
-    BI.i18nText("BI-Thursday"),
-    BI.i18nText("BI-Friday"),
-    BI.i18nText("BI-Saturday"),
-    BI.i18nText("BI-Sunday")];
+Date._DN = [BI.i18nText("BI-Basic_Sunday"),
+    BI.i18nText("BI-Basic_Monday"),
+    BI.i18nText("BI-Basic_Tuesday"),
+    BI.i18nText("BI-Basic_Wednesday"),
+    BI.i18nText("BI-Basic_Thursday"),
+    BI.i18nText("BI-Basic_Friday"),
+    BI.i18nText("BI-Basic_Saturday"),
+    BI.i18nText("BI-Basic_Sunday")];
 
 // short day names
-Date._SDN = ['',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    ''];
+Date._SDN = [BI.i18nText("BI-Day_Ri"),
+    BI.i18nText("BI-Basic_One"),
+    BI.i18nText("BI-Basic_Two"),
+    BI.i18nText("BI-Basic_Three"),
+    BI.i18nText("BI-Basic_Four"),
+    BI.i18nText("BI-Basic_Five"),
+    BI.i18nText("BI-Basic_Six"),
+    BI.i18nText("BI-Day_Ri")];
 
 // Monday first, etc.
 Date._FD = 1;
 
 // full month names
 Date._MN = [
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    ''];
+    BI.i18nText("BI-Basic_January"),
+    BI.i18nText("BI-Basic_February"),
+    BI.i18nText("BI-Basic_March"),
+    BI.i18nText("BI-Basic_April"),
+    BI.i18nText("BI-Basic_May"),
+    BI.i18nText("BI-Basic_June"),
+    BI.i18nText("BI-Basic_July"),
+    BI.i18nText("BI-Basic_August"),
+    BI.i18nText("BI-Basic_September"),
+    BI.i18nText("BI-Basic_October"),
+    BI.i18nText("BI-Basic_November"),
+    BI.i18nText("BI-Basic_December")];
 
 // short month names
-Date._SMN = ['',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    ''];
+Date._SMN = [0,
+    1,
+    2,
+    3,
+    4,
+    5,
+    6,
+    7,
+    8,
+    9,
+    10,
+    11];
 
 Date._QN = ["", BI.i18nText("BI-Quarter_1"),
     BI.i18nText("BI-Quarter_2"),
diff --git a/dist/widget.css b/dist/widget.css
index 51d0750008..a048dd5bc5 100644
--- a/dist/widget.css
+++ b/dist/widget.css
@@ -233,11 +233,13 @@
 }
 .bi-fine-tuning-number-editor .top-button {
   border-left: 1px solid #d4dadd;
-  border-bottom: 1px solid #d4dadd;
 }
 .bi-fine-tuning-number-editor .bottom-button {
   border-left: 1px solid #d4dadd;
 }
+.bi-fine-tuning-number-editor .split-line {
+  background-color: #d4dadd;
+}
 /****添加计算宽度的--运算符直接需要space****/
 /****** common color(常用颜色,可用于普遍场景) *****/
 /**** custom color(自定义颜色,用于特定场景) ****/
diff --git a/dist/widget.js b/dist/widget.js
index fec31d1b5f..75b27e101c 100644
--- a/dist/widget.js
+++ b/dist/widget.js
@@ -4857,7 +4857,6 @@ BI.shortcut('bi.date_combo', BI.DateCombo);BI.DateTrigger = BI.inherit(BI.Trigge
         hgap: 4,
         vgap: 2,
         triggerWidth: 30,
-        watermark: BI.i18nText("BI-Unrestricted"),
         yearLength: 4,
         yearMonthLength: 7
     },
@@ -4891,7 +4890,7 @@ BI.shortcut('bi.date_combo', BI.DateCombo);BI.DateTrigger = BI.inherit(BI.Trigge
             hgap: c.hgap,
             vgap: c.vgap,
             allowBlank: true,
-            watermark: c.watermark,
+            watermark: BI.i18nText("BI-Unrestricted"),
             errorText: function () {
                 if (self.editor.isEditing()) {
                     return BI.i18nText("BI-Date_Trigger_Error_Text");
diff --git a/src/core/proto/date.js b/src/core/proto/date.js
index 636fafdc70..d1c240377c 100644
--- a/src/core/proto/date.js
+++ b/src/core/proto/date.js
@@ -1,54 +1,54 @@
 // full day names
-Date._DN = [BI.i18nText("BI-Sunday"),
-    BI.i18nText("BI-Monday"),
-    BI.i18nText("BI-Tuesday"),
-    BI.i18nText("BI-Wednesday"),
-    BI.i18nText("BI-Thursday"),
-    BI.i18nText("BI-Friday"),
-    BI.i18nText("BI-Saturday"),
-    BI.i18nText("BI-Sunday")];
+Date._DN = [BI.i18nText("BI-Basic_Sunday"),
+    BI.i18nText("BI-Basic_Monday"),
+    BI.i18nText("BI-Basic_Tuesday"),
+    BI.i18nText("BI-Basic_Wednesday"),
+    BI.i18nText("BI-Basic_Thursday"),
+    BI.i18nText("BI-Basic_Friday"),
+    BI.i18nText("BI-Basic_Saturday"),
+    BI.i18nText("BI-Basic_Sunday")];
 
 // short day names
-Date._SDN = ['',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    ''];
+Date._SDN = [BI.i18nText("BI-Day_Ri"),
+    BI.i18nText("BI-Basic_One"),
+    BI.i18nText("BI-Basic_Two"),
+    BI.i18nText("BI-Basic_Three"),
+    BI.i18nText("BI-Basic_Four"),
+    BI.i18nText("BI-Basic_Five"),
+    BI.i18nText("BI-Basic_Six"),
+    BI.i18nText("BI-Day_Ri")];
 
 // Monday first, etc.
 Date._FD = 1;
 
 // full month names
 Date._MN = [
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    ''];
+    BI.i18nText("BI-Basic_January"),
+    BI.i18nText("BI-Basic_February"),
+    BI.i18nText("BI-Basic_March"),
+    BI.i18nText("BI-Basic_April"),
+    BI.i18nText("BI-Basic_May"),
+    BI.i18nText("BI-Basic_June"),
+    BI.i18nText("BI-Basic_July"),
+    BI.i18nText("BI-Basic_August"),
+    BI.i18nText("BI-Basic_September"),
+    BI.i18nText("BI-Basic_October"),
+    BI.i18nText("BI-Basic_November"),
+    BI.i18nText("BI-Basic_December")];
 
 // short month names
-Date._SMN = ['',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    '',
-    ''];
+Date._SMN = [0,
+    1,
+    2,
+    3,
+    4,
+    5,
+    6,
+    7,
+    8,
+    9,
+    10,
+    11];
 
 Date._QN = ["", BI.i18nText("BI-Quarter_1"),
     BI.i18nText("BI-Quarter_2"),
diff --git a/src/css/widget/finetuningnumbereditor/finetuning.number.editor.css b/src/css/widget/finetuningnumbereditor/finetuning.number.editor.css
index d8afcf2390..69e34450ae 100644
--- a/src/css/widget/finetuningnumbereditor/finetuning.number.editor.css
+++ b/src/css/widget/finetuningnumbereditor/finetuning.number.editor.css
@@ -9,8 +9,10 @@
 }
 .bi-fine-tuning-number-editor .top-button {
   border-left: 1px solid #d4dadd;
-  border-bottom: 1px solid #d4dadd;
 }
 .bi-fine-tuning-number-editor .bottom-button {
   border-left: 1px solid #d4dadd;
 }
+.bi-fine-tuning-number-editor .split-line {
+  background-color: #d4dadd;
+}
diff --git a/src/less/widget/finetuningnumbereditor/finetuning.number.editor.less b/src/less/widget/finetuningnumbereditor/finetuning.number.editor.less
index 2f7905f81a..3074def162 100644
--- a/src/less/widget/finetuningnumbereditor/finetuning.number.editor.less
+++ b/src/less/widget/finetuningnumbereditor/finetuning.number.editor.less
@@ -5,9 +5,11 @@
   .border-radius(2px);
   & .top-button {
     border-left: 1px solid @border-color-normal;
-    border-bottom: 1px solid @border-color-normal;
   }
   & .bottom-button {
     border-left: 1px solid @border-color-normal;
   }
+  & .split-line{
+    background-color: @border-color-normal;
+  }
 }
\ No newline at end of file
diff --git a/src/widget/date/trigger.date.js b/src/widget/date/trigger.date.js
index a425ce6f8a..75f51a86ae 100644
--- a/src/widget/date/trigger.date.js
+++ b/src/widget/date/trigger.date.js
@@ -3,7 +3,6 @@ BI.DateTrigger = BI.inherit(BI.Trigger, {
         hgap: 4,
         vgap: 2,
         triggerWidth: 30,
-        watermark: BI.i18nText("BI-Unrestricted"),
         yearLength: 4,
         yearMonthLength: 7
     },
@@ -37,7 +36,7 @@ BI.DateTrigger = BI.inherit(BI.Trigger, {
             hgap: c.hgap,
             vgap: c.vgap,
             allowBlank: true,
-            watermark: c.watermark,
+            watermark: BI.i18nText("BI-Unrestricted"),
             errorText: function () {
                 if (self.editor.isEditing()) {
                     return BI.i18nText("BI-Date_Trigger_Error_Text");

From 3ebf571467d03d6162f7b81bb9bc4b668f0d0e3d Mon Sep 17 00:00:00 2001
From: windy <1374721899@qq.com>
Date: Thu, 30 Mar 2017 15:48:31 +0800
Subject: [PATCH 10/19] ajax

---
 demo/version.js  |   6 +-
 src/base/base.js |   6 +-
 src/core/base.js | 176 +----------------------------------------------
 3 files changed, 9 insertions(+), 179 deletions(-)

diff --git a/demo/version.js b/demo/version.js
index 51c96d1785..5e16777ec5 100644
--- a/demo/version.js
+++ b/demo/version.js
@@ -4,4 +4,8 @@ Demo = {
 
 BI.i18n = {
     "BI-Basic_OK": "确定"
-};
\ No newline at end of file
+};
+
+BI.servletURL = "dist/";
+BI.resourceURL = "dist/resource/";
+BI.i18n = {};
\ No newline at end of file
diff --git a/src/base/base.js b/src/base/base.js
index 1198a5d522..49c5b21091 100644
--- a/src/base/base.js
+++ b/src/base/base.js
@@ -5,8 +5,4 @@ BI.Bubbles = new BI.BubblesController();
 BI.Tooltips = new BI.TooltipsController();
 BI.Popovers = new BI.FloatBoxController();
 BI.Broadcasts = new BI.BroadcastController();
-BI.StyleLoaders = new BI.StyleLoaderManager();
-
-BI.servletURL = "dist/";
-BI.resourceURL = "dist/resource/";
-BI.i18n = {};
\ No newline at end of file
+BI.StyleLoaders = new BI.StyleLoaderManager();
\ No newline at end of file
diff --git a/src/core/base.js b/src/core/base.js
index e91ddc1643..cdee5f2d50 100644
--- a/src/core/base.js
+++ b/src/core/base.js
@@ -1076,28 +1076,7 @@ if (!window.BI) {
                 //encode
                 encodeBIParam(option.data);
 
-                var async = true;
-                if (BI.isNotNull(option.async)) {
-                    async = option.async;
-                }
-
-                if (BI.isNull(loading)) {
-                    loading = BI.createWidget({
-                        type: "bi.request_loading"
-                    });
-                }
-
-                if (BI.isNull(timeoutToast)) {
-                    timeoutToast = BI.createWidget({
-                        type: "bi.timeout_toast"
-                    });
-                    timeoutToast.setCallback(function (op) {
-                        decodeBIParam(op.data);
-                        BI.ajax(op);
-                    });
-                }
-                timeoutToast.addReq(option);
-
+                var async = option.async;
 
                 option.data = BI.cjkEncodeDO(option.data);
 
@@ -1107,68 +1086,14 @@ if (!window.BI) {
                     type: "POST",
                     data: option.data,
                     async: async,
-                    error: function () {
-                        if (!timeoutToast.hasReq(option)) {
-                            return;
-                        }
-                        timeoutToast.removeReq(option);
-                        //失败 取消、重新加载
-                        loading.setCallback(function () {
-                            decodeBIParam(option.data);
-                            BI.ajax(option);
-                        });
-                        loading.showError();
-                    },
+                    error: option.error,
                     complete: function (res, status) {
-                        if (!timeoutToast.hasReq(option)) {
-                            return;
-                        }
-                        timeoutToast.removeReq(option);
-                        //登录超时
-                        if (BI.isNotNull(res.responseText) &&
-                            res.responseText.indexOf("fs-login-content") > -1 &&
-                            res.responseText.indexOf("fs-login-input-password-confirm") === -1) {
-                            if (BI.Popovers.isVisible(BI.LoginTimeOut.POPOVER_ID)) {
-                                return;
-                            }
-                            if (BI.isNotNull(BI.Popovers.get(BI.LoginTimeOut.POPOVER_ID))) {
-                                BI.Popovers.open(BI.LoginTimeOut.POPOVER_ID);
-                                return;
-                            }
-                            var loginTimeout = BI.createWidget({
-                                type: "bi.login_timeout"
-                            });
-                            loginTimeout.on(BI.LoginTimeOut.EVENT_LOGIN, function () {
-                                decodeBIParam(option.data);
-                                BI.ajax(option);
-                                BI.Popovers.remove(BI.LoginTimeOut.POPOVER_ID);
-                            });
-                            BI.Popovers.create(BI.LoginTimeOut.POPOVER_ID, loginTimeout, {
-                                width: 600,
-                                height: 400
-                            }).open(BI.LoginTimeOut.POPOVER_ID);
-                        } else if (BI.isNotNull(res.responseText) &&
-                            res.responseText.indexOf("script") > -1 &&
-                            res.responseText.indexOf("Session Timeout...") > -1) {
-                            //登录失效
-                            loading.setCallback(function () {
-                                location.reload();
-                            });
-                            loading.showError();
-
-                        } else if (status === "success" && BI.isFunction(option.success)) {
-                            option.success(BI.jsonDecode(res.responseText));
-                        }
                         if (BI.isFunction(option.complete)) {
                             option.complete(BI.jsonDecode(res.responseText), status);
                         }
                     }
                 });
 
-                return function cancel() {
-                    timeoutToast.removeReq(option);
-                };
-
                 function encodeBIParam(data) {
                     for (var key in data) {
                         if (_.isObject(data[key])) {
@@ -1188,101 +1113,6 @@ if (!window.BI) {
                     }
                 }
             }
-        })(),
-
-        /**
-         * 异步ajax请求
-         * @param {String} op op参数
-         * @param {String} cmd cmd参数
-         * @param {JSON} data ajax请求的参数
-         * @param {Function} callback 回调函数
-         * @param {Function} complete 回调
-         */
-        requestAsync: function (op, cmd, data, callback, complete) {
-            data = data || {};
-            if (!BI.isKey(op)) {
-                op = 'fr_bi_dezi';
-            }
-            if (op === "fr_bi_dezi" || op === "fr_bi_configure") {
-                data.sessionID = Data.SharingPool.get("sessionID");
-            }
-            var url = BI.servletURL + '?op=' + op + '&cmd=' + cmd + "&_=" + Math.random();
-            return (BI.ajax)({
-                url: url,
-                type: 'POST',
-                data: data,
-                error: function () {
-                    // BI.Msg.toast(BI.i18nText("BI-Ajax_Error"));
-                },
-                success: function (res) {
-                    if (BI.isFunction(callback)) {
-                        callback(res);
-                    }
-                },
-                complete: function (res, status) {
-                    if (BI.isFunction(complete)) {
-                        complete(res);
-                    }
-                }
-            });
-        },
-
-        /**
-         * 同步ajax请求
-         * @param {String} op op参数
-         * @param {String} cmd cmd参数
-         * @param {JSON} data ajax请求的参�?
-         * @returns {Object} ajax同步请求返回的JSON对象
-         */
-        requestSync: function (op, cmd, data) {
-            data = data || {};
-            if (!BI.isKey(op)) {
-                op = 'fr_bi_dezi';
-            }
-            if (op === "fr_bi_dezi") {
-                data.sessionID = Data.SharingPool.get("sessionID");
-            }
-            var url = BI.servletURL + '?op=' + op + '&cmd=' + cmd + "&_=" + Math.random();
-            var result = {};
-            (BI.ajax)({
-                url: url,
-                type: 'POST',
-                async: false,
-                data: data,
-                error: function () {
-                    BI.Msg.toast(BI.i18nText("BI-Ajax_Error"));
-                },
-                complete: function (res, status) {
-                    if (status === 'success') {
-                        result = res;
-                    }
-                }
-            });
-            return result;
-        },
-
-        /**
-         * 请求方法
-         * @param cmd 命令
-         * @param data 数据
-         * @param extend 参数
-         * @returns {*}
-         */
-        request: function (cmd, data, extend) {
-            extend = extend || {};
-            data = data || {};
-            var op = extend.op;
-            if (!BI.isKey(op)) {
-                op = 'fr_bi_dezi';
-            }
-            if (op === "fr_bi_dezi") {
-                data.sessionID = Data.SharingPool.get("sessionID");
-            }
-            if (extend.async === true) {
-                BI.requestAsync(op, cmd, data, extend.complete || extend.success);
-            } else {
-                return BI.requestSync(op, cmd, data);
-            }
-        }
+        })()
     });
 })(jQuery);
\ No newline at end of file

From 4413970d1a53616e6afe461e4402f4519ac885ff Mon Sep 17 00:00:00 2001
From: guy <guy@finereport.com>
Date: Thu, 30 Mar 2017 16:05:05 +0800
Subject: [PATCH 11/19] delete

---
 src/css/widget/responsivetable/responsivetable.css   |  8 --------
 src/less/widget/responsivetable/responsivetable.less | 11 -----------
 2 files changed, 19 deletions(-)
 delete mode 100644 src/css/widget/responsivetable/responsivetable.css
 delete mode 100644 src/less/widget/responsivetable/responsivetable.less

diff --git a/src/css/widget/responsivetable/responsivetable.css b/src/css/widget/responsivetable/responsivetable.css
deleted file mode 100644
index e19ce6816c..0000000000
--- a/src/css/widget/responsivetable/responsivetable.css
+++ /dev/null
@@ -1,8 +0,0 @@
-/****添加计算宽度的--运算符直接需要space****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-responsive-table > div.bottom-left > div > div > table > * > * > td.last-col,
-.bi-responsive-table > div.bottom-right > div > div > table > * > * > td.last-col,
-.bi-responsive-table > div > div > table > * > * > td.last-col {
-  min-width: 80px;
-}
diff --git a/src/less/widget/responsivetable/responsivetable.less b/src/less/widget/responsivetable/responsivetable.less
deleted file mode 100644
index 87cbfb2890..0000000000
--- a/src/less/widget/responsivetable/responsivetable.less
+++ /dev/null
@@ -1,11 +0,0 @@
-@import "../../bibase";
-
-.bi-responsive-table {
-  & > div.bottom-left > div > div > table, & > div.bottom-right > div > div > table, > div > div > table {
-    & > * > * > td {
-      &.last-col {
-        min-width: 80px;
-      }
-    }
-  }
-}
\ No newline at end of file

From 4a7d4dcc76276436a2d738df784884a31b740549 Mon Sep 17 00:00:00 2001
From: guy <guy@finereport.com>
Date: Thu, 30 Mar 2017 16:23:15 +0800
Subject: [PATCH 12/19] =?UTF-8?q?=E8=A1=A5=E6=96=B9=E6=B3=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 bi/base.js        |   6 +-
 bi/core.js        | 228 +++++++++++-----------------------------------
 bi/widget.css     |   8 --
 dist/base.js      |   6 +-
 dist/core.js      | 228 +++++++++++-----------------------------------
 dist/widget.css   |   8 --
 src/core/alias.js |  52 +++++++++++
 7 files changed, 164 insertions(+), 372 deletions(-)

diff --git a/bi/base.js b/bi/base.js
index 959a0defcf..8f157d02a5 100644
--- a/bi/base.js
+++ b/bi/base.js
@@ -2368,11 +2368,7 @@ BI.Bubbles = new BI.BubblesController();
 BI.Tooltips = new BI.TooltipsController();
 BI.Popovers = new BI.FloatBoxController();
 BI.Broadcasts = new BI.BroadcastController();
-BI.StyleLoaders = new BI.StyleLoaderManager();
-
-BI.servletURL = "dist/";
-BI.resourceURL = "dist/resource/";
-BI.i18n = {};/**
+BI.StyleLoaders = new BI.StyleLoaderManager();/**
  * canvas绘图
  *
  * Created by GUY on 2015/11/18.
diff --git a/bi/core.js b/bi/core.js
index 29b81c77f8..a39580f0c7 100644
--- a/bi/core.js
+++ b/bi/core.js
@@ -2971,28 +2971,7 @@ if (!window.BI) {
                 //encode
                 encodeBIParam(option.data);
 
-                var async = true;
-                if (BI.isNotNull(option.async)) {
-                    async = option.async;
-                }
-
-                if (BI.isNull(loading)) {
-                    loading = BI.createWidget({
-                        type: "bi.request_loading"
-                    });
-                }
-
-                if (BI.isNull(timeoutToast)) {
-                    timeoutToast = BI.createWidget({
-                        type: "bi.timeout_toast"
-                    });
-                    timeoutToast.setCallback(function (op) {
-                        decodeBIParam(op.data);
-                        BI.ajax(op);
-                    });
-                }
-                timeoutToast.addReq(option);
-
+                var async = option.async;
 
                 option.data = BI.cjkEncodeDO(option.data);
 
@@ -3002,68 +2981,14 @@ if (!window.BI) {
                     type: "POST",
                     data: option.data,
                     async: async,
-                    error: function () {
-                        if (!timeoutToast.hasReq(option)) {
-                            return;
-                        }
-                        timeoutToast.removeReq(option);
-                        //失败 取消、重新加载
-                        loading.setCallback(function () {
-                            decodeBIParam(option.data);
-                            BI.ajax(option);
-                        });
-                        loading.showError();
-                    },
+                    error: option.error,
                     complete: function (res, status) {
-                        if (!timeoutToast.hasReq(option)) {
-                            return;
-                        }
-                        timeoutToast.removeReq(option);
-                        //登录超时
-                        if (BI.isNotNull(res.responseText) &&
-                            res.responseText.indexOf("fs-login-content") > -1 &&
-                            res.responseText.indexOf("fs-login-input-password-confirm") === -1) {
-                            if (BI.Popovers.isVisible(BI.LoginTimeOut.POPOVER_ID)) {
-                                return;
-                            }
-                            if (BI.isNotNull(BI.Popovers.get(BI.LoginTimeOut.POPOVER_ID))) {
-                                BI.Popovers.open(BI.LoginTimeOut.POPOVER_ID);
-                                return;
-                            }
-                            var loginTimeout = BI.createWidget({
-                                type: "bi.login_timeout"
-                            });
-                            loginTimeout.on(BI.LoginTimeOut.EVENT_LOGIN, function () {
-                                decodeBIParam(option.data);
-                                BI.ajax(option);
-                                BI.Popovers.remove(BI.LoginTimeOut.POPOVER_ID);
-                            });
-                            BI.Popovers.create(BI.LoginTimeOut.POPOVER_ID, loginTimeout, {
-                                width: 600,
-                                height: 400
-                            }).open(BI.LoginTimeOut.POPOVER_ID);
-                        } else if (BI.isNotNull(res.responseText) &&
-                            res.responseText.indexOf("script") > -1 &&
-                            res.responseText.indexOf("Session Timeout...") > -1) {
-                            //登录失效
-                            loading.setCallback(function () {
-                                location.reload();
-                            });
-                            loading.showError();
-
-                        } else if (status === "success" && BI.isFunction(option.success)) {
-                            option.success(BI.jsonDecode(res.responseText));
-                        }
                         if (BI.isFunction(option.complete)) {
                             option.complete(BI.jsonDecode(res.responseText), status);
                         }
                     }
                 });
 
-                return function cancel() {
-                    timeoutToast.removeReq(option);
-                };
-
                 function encodeBIParam(data) {
                     for (var key in data) {
                         if (_.isObject(data[key])) {
@@ -3083,102 +3008,7 @@ if (!window.BI) {
                     }
                 }
             }
-        })(),
-
-        /**
-         * 异步ajax请求
-         * @param {String} op op参数
-         * @param {String} cmd cmd参数
-         * @param {JSON} data ajax请求的参数
-         * @param {Function} callback 回调函数
-         * @param {Function} complete 回调
-         */
-        requestAsync: function (op, cmd, data, callback, complete) {
-            data = data || {};
-            if (!BI.isKey(op)) {
-                op = 'fr_bi_dezi';
-            }
-            if (op === "fr_bi_dezi" || op === "fr_bi_configure") {
-                data.sessionID = Data.SharingPool.get("sessionID");
-            }
-            var url = BI.servletURL + '?op=' + op + '&cmd=' + cmd + "&_=" + Math.random();
-            return (BI.ajax)({
-                url: url,
-                type: 'POST',
-                data: data,
-                error: function () {
-                    // BI.Msg.toast(BI.i18nText("BI-Ajax_Error"));
-                },
-                success: function (res) {
-                    if (BI.isFunction(callback)) {
-                        callback(res);
-                    }
-                },
-                complete: function (res, status) {
-                    if (BI.isFunction(complete)) {
-                        complete(res);
-                    }
-                }
-            });
-        },
-
-        /**
-         * 同步ajax请求
-         * @param {String} op op参数
-         * @param {String} cmd cmd参数
-         * @param {JSON} data ajax请求的参�?
-         * @returns {Object} ajax同步请求返回的JSON对象
-         */
-        requestSync: function (op, cmd, data) {
-            data = data || {};
-            if (!BI.isKey(op)) {
-                op = 'fr_bi_dezi';
-            }
-            if (op === "fr_bi_dezi") {
-                data.sessionID = Data.SharingPool.get("sessionID");
-            }
-            var url = BI.servletURL + '?op=' + op + '&cmd=' + cmd + "&_=" + Math.random();
-            var result = {};
-            (BI.ajax)({
-                url: url,
-                type: 'POST',
-                async: false,
-                data: data,
-                error: function () {
-                    BI.Msg.toast(BI.i18nText("BI-Ajax_Error"));
-                },
-                complete: function (res, status) {
-                    if (status === 'success') {
-                        result = res;
-                    }
-                }
-            });
-            return result;
-        },
-
-        /**
-         * 请求方法
-         * @param cmd 命令
-         * @param data 数据
-         * @param extend 参数
-         * @returns {*}
-         */
-        request: function (cmd, data, extend) {
-            extend = extend || {};
-            data = data || {};
-            var op = extend.op;
-            if (!BI.isKey(op)) {
-                op = 'fr_bi_dezi';
-            }
-            if (op === "fr_bi_dezi") {
-                data.sessionID = Data.SharingPool.get("sessionID");
-            }
-            if (extend.async === true) {
-                BI.requestAsync(op, cmd, data, extend.complete || extend.success);
-            } else {
-                return BI.requestSync(op, cmd, data);
-            }
-        }
+        })()
     });
 })(jQuery);;(function () {
     function isEmpty(value) {
@@ -3320,6 +3150,58 @@ if (!window.BI) {
         }
     };
 
+    BI.jsonDecode = function (text) {
+
+        try {
+            // 注意0啊
+            //var jo = $.parseJSON(text) || {};
+            var jo = $.parseJSON(text);
+            if (jo == null) {
+                jo = {};
+            }
+        } catch (e) {
+            /*
+             * richie:浏览器只支持标准的JSON字符串转换,而jQuery会默认调用浏览器的window.JSON.parse()函数进行解析
+             * 比如:var str = "{'a':'b'}",这种形式的字符串转换为JSON就会抛异常
+             */
+            try {
+                jo = new Function("return " + text)() || {};
+            } catch (e) {
+                //do nothing
+            }
+            if (jo == null) {
+                jo = [];
+            }
+        }
+        if (!_hasDateInJson(text)) {
+            return jo;
+        }
+
+        function _hasDateInJson(json) {
+            if (!json || typeof json !== "string") {
+                return false;
+            }
+            return json.indexOf("__time__") != -1;
+        }
+
+        return (function (o) {
+            if (typeof o === "string") {
+                return o;
+            }
+            if (o && o.__time__ != null) {
+                return new Date(o.__time__);
+            }
+            for (var a in o) {
+                if (o[a] == o || typeof o[a] == 'object' || $.isFunction(o[a])) {
+                    break;
+                }
+                o[a] = arguments.callee(o[a]);
+            }
+
+            return o;
+        })(jo);
+    }
+
     BI.contentFormat = function (cv, fmt) {
         if (isEmpty(cv)) {
             //原值为空,返回空字符
diff --git a/bi/widget.css b/bi/widget.css
index a048dd5bc5..39a07dbd61 100644
--- a/bi/widget.css
+++ b/bi/widget.css
@@ -634,14 +634,6 @@
 /****添加计算宽度的--运算符直接需要space****/
 /****** common color(常用颜色,可用于普遍场景) *****/
 /**** custom color(自定义颜色,用于特定场景) ****/
-.bi-responsive-table > div.bottom-left > div > div > table > * > * > td.last-col,
-.bi-responsive-table > div.bottom-right > div > div > table > * > * > td.last-col,
-.bi-responsive-table > div > div > table > * > * > td.last-col {
-  min-width: 80px;
-}
-/****添加计算宽度的--运算符直接需要space****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
 .bi-sequence-table-dynamic-number .sequence-table-title-cell {
   overflow: hidden;
   overflow-x: hidden;
diff --git a/dist/base.js b/dist/base.js
index 959a0defcf..8f157d02a5 100644
--- a/dist/base.js
+++ b/dist/base.js
@@ -2368,11 +2368,7 @@ BI.Bubbles = new BI.BubblesController();
 BI.Tooltips = new BI.TooltipsController();
 BI.Popovers = new BI.FloatBoxController();
 BI.Broadcasts = new BI.BroadcastController();
-BI.StyleLoaders = new BI.StyleLoaderManager();
-
-BI.servletURL = "dist/";
-BI.resourceURL = "dist/resource/";
-BI.i18n = {};/**
+BI.StyleLoaders = new BI.StyleLoaderManager();/**
  * canvas绘图
  *
  * Created by GUY on 2015/11/18.
diff --git a/dist/core.js b/dist/core.js
index 870551ae6e..f1b2417b32 100644
--- a/dist/core.js
+++ b/dist/core.js
@@ -13987,28 +13987,7 @@ if (!window.BI) {
                 //encode
                 encodeBIParam(option.data);
 
-                var async = true;
-                if (BI.isNotNull(option.async)) {
-                    async = option.async;
-                }
-
-                if (BI.isNull(loading)) {
-                    loading = BI.createWidget({
-                        type: "bi.request_loading"
-                    });
-                }
-
-                if (BI.isNull(timeoutToast)) {
-                    timeoutToast = BI.createWidget({
-                        type: "bi.timeout_toast"
-                    });
-                    timeoutToast.setCallback(function (op) {
-                        decodeBIParam(op.data);
-                        BI.ajax(op);
-                    });
-                }
-                timeoutToast.addReq(option);
-
+                var async = option.async;
 
                 option.data = BI.cjkEncodeDO(option.data);
 
@@ -14018,68 +13997,14 @@ if (!window.BI) {
                     type: "POST",
                     data: option.data,
                     async: async,
-                    error: function () {
-                        if (!timeoutToast.hasReq(option)) {
-                            return;
-                        }
-                        timeoutToast.removeReq(option);
-                        //失败 取消、重新加载
-                        loading.setCallback(function () {
-                            decodeBIParam(option.data);
-                            BI.ajax(option);
-                        });
-                        loading.showError();
-                    },
+                    error: option.error,
                     complete: function (res, status) {
-                        if (!timeoutToast.hasReq(option)) {
-                            return;
-                        }
-                        timeoutToast.removeReq(option);
-                        //登录超时
-                        if (BI.isNotNull(res.responseText) &&
-                            res.responseText.indexOf("fs-login-content") > -1 &&
-                            res.responseText.indexOf("fs-login-input-password-confirm") === -1) {
-                            if (BI.Popovers.isVisible(BI.LoginTimeOut.POPOVER_ID)) {
-                                return;
-                            }
-                            if (BI.isNotNull(BI.Popovers.get(BI.LoginTimeOut.POPOVER_ID))) {
-                                BI.Popovers.open(BI.LoginTimeOut.POPOVER_ID);
-                                return;
-                            }
-                            var loginTimeout = BI.createWidget({
-                                type: "bi.login_timeout"
-                            });
-                            loginTimeout.on(BI.LoginTimeOut.EVENT_LOGIN, function () {
-                                decodeBIParam(option.data);
-                                BI.ajax(option);
-                                BI.Popovers.remove(BI.LoginTimeOut.POPOVER_ID);
-                            });
-                            BI.Popovers.create(BI.LoginTimeOut.POPOVER_ID, loginTimeout, {
-                                width: 600,
-                                height: 400
-                            }).open(BI.LoginTimeOut.POPOVER_ID);
-                        } else if (BI.isNotNull(res.responseText) &&
-                            res.responseText.indexOf("script") > -1 &&
-                            res.responseText.indexOf("Session Timeout...") > -1) {
-                            //登录失效
-                            loading.setCallback(function () {
-                                location.reload();
-                            });
-                            loading.showError();
-
-                        } else if (status === "success" && BI.isFunction(option.success)) {
-                            option.success(BI.jsonDecode(res.responseText));
-                        }
                         if (BI.isFunction(option.complete)) {
                             option.complete(BI.jsonDecode(res.responseText), status);
                         }
                     }
                 });
 
-                return function cancel() {
-                    timeoutToast.removeReq(option);
-                };
-
                 function encodeBIParam(data) {
                     for (var key in data) {
                         if (_.isObject(data[key])) {
@@ -14099,102 +14024,7 @@ if (!window.BI) {
                     }
                 }
             }
-        })(),
-
-        /**
-         * 异步ajax请求
-         * @param {String} op op参数
-         * @param {String} cmd cmd参数
-         * @param {JSON} data ajax请求的参数
-         * @param {Function} callback 回调函数
-         * @param {Function} complete 回调
-         */
-        requestAsync: function (op, cmd, data, callback, complete) {
-            data = data || {};
-            if (!BI.isKey(op)) {
-                op = 'fr_bi_dezi';
-            }
-            if (op === "fr_bi_dezi" || op === "fr_bi_configure") {
-                data.sessionID = Data.SharingPool.get("sessionID");
-            }
-            var url = BI.servletURL + '?op=' + op + '&cmd=' + cmd + "&_=" + Math.random();
-            return (BI.ajax)({
-                url: url,
-                type: 'POST',
-                data: data,
-                error: function () {
-                    // BI.Msg.toast(BI.i18nText("BI-Ajax_Error"));
-                },
-                success: function (res) {
-                    if (BI.isFunction(callback)) {
-                        callback(res);
-                    }
-                },
-                complete: function (res, status) {
-                    if (BI.isFunction(complete)) {
-                        complete(res);
-                    }
-                }
-            });
-        },
-
-        /**
-         * 同步ajax请求
-         * @param {String} op op参数
-         * @param {String} cmd cmd参数
-         * @param {JSON} data ajax请求的参�?
-         * @returns {Object} ajax同步请求返回的JSON对象
-         */
-        requestSync: function (op, cmd, data) {
-            data = data || {};
-            if (!BI.isKey(op)) {
-                op = 'fr_bi_dezi';
-            }
-            if (op === "fr_bi_dezi") {
-                data.sessionID = Data.SharingPool.get("sessionID");
-            }
-            var url = BI.servletURL + '?op=' + op + '&cmd=' + cmd + "&_=" + Math.random();
-            var result = {};
-            (BI.ajax)({
-                url: url,
-                type: 'POST',
-                async: false,
-                data: data,
-                error: function () {
-                    BI.Msg.toast(BI.i18nText("BI-Ajax_Error"));
-                },
-                complete: function (res, status) {
-                    if (status === 'success') {
-                        result = res;
-                    }
-                }
-            });
-            return result;
-        },
-
-        /**
-         * 请求方法
-         * @param cmd 命令
-         * @param data 数据
-         * @param extend 参数
-         * @returns {*}
-         */
-        request: function (cmd, data, extend) {
-            extend = extend || {};
-            data = data || {};
-            var op = extend.op;
-            if (!BI.isKey(op)) {
-                op = 'fr_bi_dezi';
-            }
-            if (op === "fr_bi_dezi") {
-                data.sessionID = Data.SharingPool.get("sessionID");
-            }
-            if (extend.async === true) {
-                BI.requestAsync(op, cmd, data, extend.complete || extend.success);
-            } else {
-                return BI.requestSync(op, cmd, data);
-            }
-        }
+        })()
     });
 })(jQuery);/**
  * 客户端观察者,主要处理事件的添加、删除、执行等
@@ -19998,6 +19828,58 @@ BI.PopoverSection.EVENT_CLOSE = "EVENT_CLOSE";;(function () {
         }
     };
 
+    BI.jsonDecode = function (text) {
+
+        try {
+            // 注意0啊
+            //var jo = $.parseJSON(text) || {};
+            var jo = $.parseJSON(text);
+            if (jo == null) {
+                jo = {};
+            }
+        } catch (e) {
+            /*
+             * richie:浏览器只支持标准的JSON字符串转换,而jQuery会默认调用浏览器的window.JSON.parse()函数进行解析
+             * 比如:var str = "{'a':'b'}",这种形式的字符串转换为JSON就会抛异常
+             */
+            try {
+                jo = new Function("return " + text)() || {};
+            } catch (e) {
+                //do nothing
+            }
+            if (jo == null) {
+                jo = [];
+            }
+        }
+        if (!_hasDateInJson(text)) {
+            return jo;
+        }
+
+        function _hasDateInJson(json) {
+            if (!json || typeof json !== "string") {
+                return false;
+            }
+            return json.indexOf("__time__") != -1;
+        }
+
+        return (function (o) {
+            if (typeof o === "string") {
+                return o;
+            }
+            if (o && o.__time__ != null) {
+                return new Date(o.__time__);
+            }
+            for (var a in o) {
+                if (o[a] == o || typeof o[a] == 'object' || $.isFunction(o[a])) {
+                    break;
+                }
+                o[a] = arguments.callee(o[a]);
+            }
+
+            return o;
+        })(jo);
+    }
+
     BI.contentFormat = function (cv, fmt) {
         if (isEmpty(cv)) {
             //原值为空,返回空字符
diff --git a/dist/widget.css b/dist/widget.css
index a048dd5bc5..39a07dbd61 100644
--- a/dist/widget.css
+++ b/dist/widget.css
@@ -634,14 +634,6 @@
 /****添加计算宽度的--运算符直接需要space****/
 /****** common color(常用颜色,可用于普遍场景) *****/
 /**** custom color(自定义颜色,用于特定场景) ****/
-.bi-responsive-table > div.bottom-left > div > div > table > * > * > td.last-col,
-.bi-responsive-table > div.bottom-right > div > div > table > * > * > td.last-col,
-.bi-responsive-table > div > div > table > * > * > td.last-col {
-  min-width: 80px;
-}
-/****添加计算宽度的--运算符直接需要space****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
 .bi-sequence-table-dynamic-number .sequence-table-title-cell {
   overflow: hidden;
   overflow-x: hidden;
diff --git a/src/core/alias.js b/src/core/alias.js
index b507b66f1f..26d5c2a120 100644
--- a/src/core/alias.js
+++ b/src/core/alias.js
@@ -138,6 +138,58 @@
         }
     };
 
+    BI.jsonDecode = function (text) {
+
+        try {
+            // 注意0啊
+            //var jo = $.parseJSON(text) || {};
+            var jo = $.parseJSON(text);
+            if (jo == null) {
+                jo = {};
+            }
+        } catch (e) {
+            /*
+             * richie:浏览器只支持标准的JSON字符串转换,而jQuery会默认调用浏览器的window.JSON.parse()函数进行解析
+             * 比如:var str = "{'a':'b'}",这种形式的字符串转换为JSON就会抛异常
+             */
+            try {
+                jo = new Function("return " + text)() || {};
+            } catch (e) {
+                //do nothing
+            }
+            if (jo == null) {
+                jo = [];
+            }
+        }
+        if (!_hasDateInJson(text)) {
+            return jo;
+        }
+
+        function _hasDateInJson(json) {
+            if (!json || typeof json !== "string") {
+                return false;
+            }
+            return json.indexOf("__time__") != -1;
+        }
+
+        return (function (o) {
+            if (typeof o === "string") {
+                return o;
+            }
+            if (o && o.__time__ != null) {
+                return new Date(o.__time__);
+            }
+            for (var a in o) {
+                if (o[a] == o || typeof o[a] == 'object' || $.isFunction(o[a])) {
+                    break;
+                }
+                o[a] = arguments.callee(o[a]);
+            }
+
+            return o;
+        })(jo);
+    }
+
     BI.contentFormat = function (cv, fmt) {
         if (isEmpty(cv)) {
             //原值为空,返回空字符

From 568a88da0843f311fed20e2c56cf645f5ef1a9d9 Mon Sep 17 00:00:00 2001
From: guy <guy@finereport.com>
Date: Thu, 30 Mar 2017 16:28:35 +0800
Subject: [PATCH 13/19] add

---
 bi/core.js        | 587 +++++++++++++++++++++++-----------------------
 dist/core.js      | 587 +++++++++++++++++++++++-----------------------
 src/core/alias.js | 587 +++++++++++++++++++++++-----------------------
 3 files changed, 867 insertions(+), 894 deletions(-)

diff --git a/bi/core.js b/bi/core.js
index a39580f0c7..5e5a78631c 100644
--- a/bi/core.js
+++ b/bi/core.js
@@ -3017,230 +3017,59 @@ if (!window.BI) {
         return result;
     }
 
-    BI.cjkEncode = function (text) {
-        // alex:如果非字符串,返回其本身(cjkEncode(234) 返回 ""是不对的)
-        if (typeof text !== 'string') {
-            return text;
-        }
-
-        var newText = "";
-        for (var i = 0; i < text.length; i++) {
-            var code = text.charCodeAt(i);
-            if (code >= 128 || code === 91 || code === 93) {//91 is "[", 93 is "]".
-                newText += "[" + code.toString(16) + "]";
-            } else {
-                newText += text.charAt(i);
-            }
-        }
-
-        return newText
-    };
-
-    BI.cjkEncodeDO = function (o) {
-        if (BI.isPlainObject(o)) {
-            var result = {};
-            $.each(o, function (k, v) {
-                if (!(typeof v == "string")) {
-                    v = BI.jsonEncode(v);
-                }
-                //wei:bug 43338,如果key是中文,cjkencode后o的长度就加了1,ie9以下版本死循环,所以新建对象result。
-                k = BI.cjkEncode(k);
-                result[k] = BI.cjkEncode(v);
-            });
-            return result;
-        }
-        return o;
-    };
-
-    BI.jsonEncode = function (o) {
-        //james:这个Encode是抄的EXT的
-        var useHasOwn = {}.hasOwnProperty ? true : false;
-
-        // crashes Safari in some instances
-        //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
-
-        var m = {
-            "\b": '\\b',
-            "\t": '\\t',
-            "\n": '\\n',
-            "\f": '\\f',
-            "\r": '\\r',
-            '"': '\\"',
-            "\\": '\\\\'
-        };
-
-        var encodeString = function (s) {
-            if (/["\\\x00-\x1f]/.test(s)) {
-                return '"' + s.replace(/([\x00-\x1f\\"])/g, function (a, b) {
-                        var c = m[b];
-                        if (c) {
-                            return c;
-                        }
-                        c = b.charCodeAt();
-                        return "\\u00" +
-                            Math.floor(c / 16).toString(16) +
-                            (c % 16).toString(16);
-                    }) + '"';
-            }
-            return '"' + s + '"';
-        };
-
-        var encodeArray = function (o) {
-            var a = ["["], b, i, l = o.length, v;
-            for (i = 0; i < l; i += 1) {
-                v = o[i];
-                switch (typeof v) {
-                    case "undefined":
-                    case "function":
-                    case "unknown":
-                        break;
-                    default:
-                        if (b) {
-                            a.push(',');
-                        }
-                        a.push(v === null ? "null" : BI.jsonEncode(v));
-                        b = true;
-                }
-            }
-            a.push("]");
-            return a.join("");
-        };
+    // 判断是否是无效的日期
+    function isInvalidDate(date) {
+        return date == "Invalid Date" || date == "NaN";
+    }
 
-        if (typeof o == "undefined" || o === null) {
-            return "null";
-        } else if (BI.isArray(o)) {
-            return encodeArray(o);
-        } else if (o instanceof Date) {
-            /*
-             * alex:原来只是把年月日时分秒简单地拼成一个String,无法decode
-             * 现在这么处理就可以decode了,但是JS.jsonDecode和Java.JSONObject也要跟着改一下
-             */
-            return BI.jsonEncode({
-                __time__: o.getTime()
-            })
-        } else if (typeof o == "string") {
-            return encodeString(o);
-        } else if (typeof o == "number") {
-            return isFinite(o) ? String(o) : "null";
-        } else if (typeof o == "boolean") {
-            return String(o);
-        } else if (BI.isFunction(o)) {
-            return String(o);
+    /**
+     * 科学计数格式
+     */
+    function _eFormat(text, fmt) {
+        var e = fmt.indexOf("E");
+        var eleft = fmt.substr(0, e), eright = fmt.substr(e + 1);
+        if (/^[0\.-]+$/.test(text)) {
+            text = BI._numberFormat(0.0, eleft) + 'E' + BI._numberFormat(0, eright)
         } else {
-            var a = ["{"], b, i, v;
-            for (i in o) {
-                if (!useHasOwn || o.hasOwnProperty(i)) {
-                    v = o[i];
-                    switch (typeof v) {
-                        case "undefined":
-                        case "unknown":
-                            break;
-                        default:
-                            if (b) {
-                                a.push(',');
-                            }
-                            a.push(BI.jsonEncode(i), ":",
-                                v === null ? "null" : BI.jsonEncode(v));
-                            b = true;
-                    }
-                }
-            }
-            a.push("}");
-            return a.join("");
-        }
-    };
-
-    BI.jsonDecode = function (text) {
-
-        try {
-            // 注意0啊
-            //var jo = $.parseJSON(text) || {};
-            var jo = $.parseJSON(text);
-            if (jo == null) {
-                jo = {};
-            }
-        } catch (e) {
-            /*
-             * richie:浏览器只支持标准的JSON字符串转换,而jQuery会默认调用浏览器的window.JSON.parse()函数进行解析
-             * 比如:var str = "{'a':'b'}",这种形式的字符串转换为JSON就会抛异常
-             */
-            try {
-                jo = new Function("return " + text)() || {};
-            } catch (e) {
-                //do nothing
-            }
-            if (jo == null) {
-                jo = [];
-            }
-        }
-        if (!_hasDateInJson(text)) {
-            return jo;
-        }
-
-        function _hasDateInJson(json) {
-            if (!json || typeof json !== "string") {
-                return false;
-            }
-            return json.indexOf("__time__") != -1;
-        }
-
-        return (function (o) {
-            if (typeof o === "string") {
-                return o;
+            var isNegative = text < 0;
+            if (isNegative) {
+                text = text.substr(1);
             }
-            if (o && o.__time__ != null) {
-                return new Date(o.__time__);
+            var elvl = (eleft.split('.')[0] || '').length;
+            var point = text.indexOf(".");
+            if (point < 0) {
+                point = text.length;
             }
-            for (var a in o) {
-                if (o[a] == o || typeof o[a] == 'object' || $.isFunction(o[a])) {
+            var i = 0; //第一个不为0的数的位置
+            text = text.replace('.', '');
+            for (var len = text.length; i < len; i++) {
+                var ech = text.charAt(i);
+                if (ech <= '9' && ech >= '1') {
                     break;
                 }
-                o[a] = arguments.callee(o[a]);
             }
-
-            return o;
-        })(jo);
-    }
-
-    BI.contentFormat = function (cv, fmt) {
-        if (isEmpty(cv)) {
-            //原值为空,返回空字符
-            return '';
-        }
-        var text = cv.toString();
-        if (isEmpty(fmt)) {
-            //格式为空,返回原字符
-            return text;
-        }
-        if (fmt.match(/^T/)) {
-            //T - 文本格式
-            return text;
-        } else if (fmt.match(/^D/)) {
-            //D - 日期(时间)格式
-            if (!(cv instanceof Date)) {
-                if (typeof cv === 'number') {
-                    //毫秒数类型
-                    cv = new Date(cv);
-                } else {
-                    //字符串类型,如yyyyMMdd、MMddyyyy等这样无分隔符的结构
-                    cv = Date.parseDate(cv + "", Date.patterns.ISO8601Long);
+            var right = point - i - elvl;
+            var left = text.substr(i, elvl);
+            var dis = i + elvl - text.length;
+            if (dis > 0) {
+                //末位补全0
+                for (var k = 0; k < dis; k++) {
+                    left += '0';
                 }
+            } else {
+                left += '.' + text.substr(i + elvl);
             }
-            if (!BI.isNull(cv)) {
-                var needTrim = fmt.match(/^DT/);
-                text = BI.date2Str(cv, fmt.substring(needTrim ? 2 : 1));
+            left = left.replace(/^[0]+/, '');
+            if (right < 0 && eright.indexOf('-') < 0) {
+                eright += ';-' + eright;
+            }
+            text = BI._numberFormat(left, eleft) + 'E' + BI._numberFormat(right, eright);
+            if (isNegative) {
+                text = '-' + text;
             }
-        } else if (fmt.match(/E/)) {
-            //科学计数格式
-            text = BI._eFormat(text, fmt);
-        } else {
-            //数字格式
-            text = BI._numberFormat(text, fmt);
         }
-        //¤ - 货币格式
-        text = text.replace(/¤/g, '¥');
         return text;
-    };
+    }
 
     /**
      * 把日期对象按照指定格式转化成字符串
@@ -3254,7 +3083,7 @@ if (!window.BI) {
      * @param format 日期格式
      * @returns {String}
      */
-    date2Str = function (date, format) {
+    function date2Str(date, format) {
         if (!date) {
             return '';
         }
@@ -3363,7 +3192,7 @@ if (!window.BI) {
     /**
      * 数字格式
      */
-    BI._numberFormat = function (text, format) {
+    function _numberFormat(text, format) {
         var text = text + '';
         //数字格式,区分正负数
         var numMod = format.indexOf(';');
@@ -3385,7 +3214,7 @@ if (!window.BI) {
             tleft = tleft.replace(/^0+/gi, '');
             tright = tright.substr(paddingZero.length).replace(/0+$/gi, '');
         }
-        var right = BI._dealWithRight(tright, fright);
+        var right = _dealWithRight(tright, fright);
         if (right.leftPlus) {
             //小数点后有进位
             tleft = parseInt(tleft) + 1 + '';
@@ -3393,7 +3222,7 @@ if (!window.BI) {
             tleft = isNaN(tleft) ? '1' : tleft;
         }
         right = right.num;
-        var left = BI._dealWithLeft(tleft, fleft);
+        var left = _dealWithLeft(tleft, fleft);
         if (!(/[0-9]/.test(left))) {
             left = left + '0';
         }
@@ -3410,7 +3239,7 @@ if (!window.BI) {
      * @returns {JSON} 返回处理结果和整数部分是否需要进位
      * @private
      */
-    BI._dealWithRight = function (tright, fright) {
+    function _dealWithRight(tright, fright) {
         var right = '', j = 0, i = 0;
         for (var len = fright.length; i < len; i++) {
             var ch = fright.charAt(i);
@@ -3441,7 +3270,7 @@ if (!window.BI) {
             if (numReg) {
                 var num = numReg[0];
                 var orilen = num.length;
-                var newnum = BI.parseINT(num) + 1 + '';
+                var newnum = BI.parseInt(num) + 1 + '';
                 //进位到整数部分
                 if (newnum.length > orilen) {
                     newnum = newnum.substr(1);
@@ -3454,22 +3283,7 @@ if (!window.BI) {
         }
         result.num = right;
         return result;
-    };
-
-    BI.parseINT = function (str) {
-        return parseInt(str, 10);
-    };
-
-    BI.leftPad = function (val, size, ch) {
-        var result = String(val);
-        if (!ch) {
-            ch = " ";
-        }
-        while (result.length < size) {
-            result = ch + result;
-        }
-        return result.toString();
-    };
+    }
 
     /**
      * 处理小数点左边整数部分
@@ -3478,7 +3292,7 @@ if (!window.BI) {
      * @returns {string} 返回处理结果
      * @private
      */
-    BI._dealWithLeft = function (tleft, fleft) {
+    function _dealWithLeft(tleft, fleft) {
         var left = '';
         var j = tleft.length - 1;
         var combo = -1, last = -1;
@@ -3537,6 +3351,242 @@ if (!window.BI) {
             left = left.replace(/[0-9]+,/, newstr);
         }
         return left;
+    }
+
+    BI.cjkEncode = function (text) {
+        // alex:如果非字符串,返回其本身(cjkEncode(234) 返回 ""是不对的)
+        if (typeof text !== 'string') {
+            return text;
+        }
+
+        var newText = "";
+        for (var i = 0; i < text.length; i++) {
+            var code = text.charCodeAt(i);
+            if (code >= 128 || code === 91 || code === 93) {//91 is "[", 93 is "]".
+                newText += "[" + code.toString(16) + "]";
+            } else {
+                newText += text.charAt(i);
+            }
+        }
+
+        return newText
+    };
+
+    BI.cjkEncodeDO = function (o) {
+        if (BI.isPlainObject(o)) {
+            var result = {};
+            $.each(o, function (k, v) {
+                if (!(typeof v == "string")) {
+                    v = BI.jsonEncode(v);
+                }
+                //wei:bug 43338,如果key是中文,cjkencode后o的长度就加了1,ie9以下版本死循环,所以新建对象result。
+                k = BI.cjkEncode(k);
+                result[k] = BI.cjkEncode(v);
+            });
+            return result;
+        }
+        return o;
+    };
+
+    BI.jsonEncode = function (o) {
+        //james:这个Encode是抄的EXT的
+        var useHasOwn = {}.hasOwnProperty ? true : false;
+
+        // crashes Safari in some instances
+        //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
+
+        var m = {
+            "\b": '\\b',
+            "\t": '\\t',
+            "\n": '\\n',
+            "\f": '\\f',
+            "\r": '\\r',
+            '"': '\\"',
+            "\\": '\\\\'
+        };
+
+        var encodeString = function (s) {
+            if (/["\\\x00-\x1f]/.test(s)) {
+                return '"' + s.replace(/([\x00-\x1f\\"])/g, function (a, b) {
+                        var c = m[b];
+                        if (c) {
+                            return c;
+                        }
+                        c = b.charCodeAt();
+                        return "\\u00" +
+                            Math.floor(c / 16).toString(16) +
+                            (c % 16).toString(16);
+                    }) + '"';
+            }
+            return '"' + s + '"';
+        };
+
+        var encodeArray = function (o) {
+            var a = ["["], b, i, l = o.length, v;
+            for (i = 0; i < l; i += 1) {
+                v = o[i];
+                switch (typeof v) {
+                    case "undefined":
+                    case "function":
+                    case "unknown":
+                        break;
+                    default:
+                        if (b) {
+                            a.push(',');
+                        }
+                        a.push(v === null ? "null" : BI.jsonEncode(v));
+                        b = true;
+                }
+            }
+            a.push("]");
+            return a.join("");
+        };
+
+        if (typeof o == "undefined" || o === null) {
+            return "null";
+        } else if (BI.isArray(o)) {
+            return encodeArray(o);
+        } else if (o instanceof Date) {
+            /*
+             * alex:原来只是把年月日时分秒简单地拼成一个String,无法decode
+             * 现在这么处理就可以decode了,但是JS.jsonDecode和Java.JSONObject也要跟着改一下
+             */
+            return BI.jsonEncode({
+                __time__: o.getTime()
+            })
+        } else if (typeof o == "string") {
+            return encodeString(o);
+        } else if (typeof o == "number") {
+            return isFinite(o) ? String(o) : "null";
+        } else if (typeof o == "boolean") {
+            return String(o);
+        } else if (BI.isFunction(o)) {
+            return String(o);
+        } else {
+            var a = ["{"], b, i, v;
+            for (i in o) {
+                if (!useHasOwn || o.hasOwnProperty(i)) {
+                    v = o[i];
+                    switch (typeof v) {
+                        case "undefined":
+                        case "unknown":
+                            break;
+                        default:
+                            if (b) {
+                                a.push(',');
+                            }
+                            a.push(BI.jsonEncode(i), ":",
+                                v === null ? "null" : BI.jsonEncode(v));
+                            b = true;
+                    }
+                }
+            }
+            a.push("}");
+            return a.join("");
+        }
+    };
+
+    BI.jsonDecode = function (text) {
+
+        try {
+            // 注意0啊
+            //var jo = $.parseJSON(text) || {};
+            var jo = $.parseJSON(text);
+            if (jo == null) {
+                jo = {};
+            }
+        } catch (e) {
+            /*
+             * richie:浏览器只支持标准的JSON字符串转换,而jQuery会默认调用浏览器的window.JSON.parse()函数进行解析
+             * 比如:var str = "{'a':'b'}",这种形式的字符串转换为JSON就会抛异常
+             */
+            try {
+                jo = new Function("return " + text)() || {};
+            } catch (e) {
+                //do nothing
+            }
+            if (jo == null) {
+                jo = [];
+            }
+        }
+        if (!_hasDateInJson(text)) {
+            return jo;
+        }
+
+        function _hasDateInJson(json) {
+            if (!json || typeof json !== "string") {
+                return false;
+            }
+            return json.indexOf("__time__") != -1;
+        }
+
+        return (function (o) {
+            if (typeof o === "string") {
+                return o;
+            }
+            if (o && o.__time__ != null) {
+                return new Date(o.__time__);
+            }
+            for (var a in o) {
+                if (o[a] == o || typeof o[a] == 'object' || $.isFunction(o[a])) {
+                    break;
+                }
+                o[a] = arguments.callee(o[a]);
+            }
+
+            return o;
+        })(jo);
+    }
+
+    BI.contentFormat = function (cv, fmt) {
+        if (isEmpty(cv)) {
+            //原值为空,返回空字符
+            return '';
+        }
+        var text = cv.toString();
+        if (isEmpty(fmt)) {
+            //格式为空,返回原字符
+            return text;
+        }
+        if (fmt.match(/^T/)) {
+            //T - 文本格式
+            return text;
+        } else if (fmt.match(/^D/)) {
+            //D - 日期(时间)格式
+            if (!(cv instanceof Date)) {
+                if (typeof cv === 'number') {
+                    //毫秒数类型
+                    cv = new Date(cv);
+                } else {
+                    //字符串类型,如yyyyMMdd、MMddyyyy等这样无分隔符的结构
+                    cv = Date.parseDate(cv + "", Date.patterns.ISO8601Long);
+                }
+            }
+            if (!BI.isNull(cv)) {
+                var needTrim = fmt.match(/^DT/);
+                text = BI.date2Str(cv, fmt.substring(needTrim ? 2 : 1));
+            }
+        } else if (fmt.match(/E/)) {
+            //科学计数格式
+            text = _eFormat(text, fmt);
+        } else {
+            //数字格式
+            text = _numberFormat(text, fmt);
+        }
+        //¤ - 货币格式
+        text = text.replace(/¤/g, '¥');
+        return text;
+    };
+
+    BI.leftPad = function (val, size, ch) {
+        var result = String(val);
+        if (!ch) {
+            ch = " ";
+        }
+        while (result.length < size) {
+            result = ch + result;
+        }
+        return result.toString();
     };
 
     BI.object2Number = function (value) {
@@ -3567,7 +3617,7 @@ if (!window.BI) {
             var str = obj + "";
             str = str.replace(/-/g, '/');
             var dt = new Date(str);
-            if (!BI.isInvalidDate(dt)) {
+            if (!isInvalidDate(dt)) {
                 return dt;
             }
 
@@ -3575,10 +3625,6 @@ if (!window.BI) {
         }
     };
 
-    BI.isArray = function (a) {
-        return Object.prototype.toString.call(a) == '[object Array]';
-    };
-
     BI.object2Time = function (obj) {
         if (obj == null) {
             return new Date();
@@ -3589,77 +3635,22 @@ if (!window.BI) {
             var str = obj + "";
             str = str.replace(/-/g, '/');
             var dt = new Date(str);
-            if (!BI.isInvalidDate(dt)) {
+            if (!isInvalidDate(dt)) {
                 return dt;
             }
             if (str.indexOf('/') === -1 && str.indexOf(':') !== -1) {
                 dt = new Date("1970/01/01 " + str);
-                if (!BI.isInvalidDate(dt)) {
+                if (!isInvalidDate(dt)) {
                     return dt;
                 }
             }
             dt = BI.str2Date(str, "HH:mm:ss");
-            if (!BI.isInvalidDate(dt)) {
+            if (!isInvalidDate(dt)) {
                 return dt;
             }
             return new Date();
         }
     };
-
-// 判断是否是无效的日期
-    BI.isInvalidDate = function (date) {
-        return date == "Invalid Date" || date == "NaN";
-    };
-
-
-    /**
-     * 科学计数格式
-     */
-    BI._eFormat = function (text, fmt) {
-        var e = fmt.indexOf("E");
-        var eleft = fmt.substr(0, e), eright = fmt.substr(e + 1);
-        if (/^[0\.-]+$/.test(text)) {
-            text = BI._numberFormat(0.0, eleft) + 'E' + BI._numberFormat(0, eright)
-        } else {
-            var isNegative = text < 0;
-            if (isNegative) {
-                text = text.substr(1);
-            }
-            var elvl = (eleft.split('.')[0] || '').length;
-            var point = text.indexOf(".");
-            if (point < 0) {
-                point = text.length;
-            }
-            var i = 0; //第一个不为0的数的位置
-            text = text.replace('.', '');
-            for (var len = text.length; i < len; i++) {
-                var ech = text.charAt(i);
-                if (ech <= '9' && ech >= '1') {
-                    break;
-                }
-            }
-            var right = point - i - elvl;
-            var left = text.substr(i, elvl);
-            var dis = i + elvl - text.length;
-            if (dis > 0) {
-                //末位补全0
-                for (var k = 0; k < dis; k++) {
-                    left += '0';
-                }
-            } else {
-                left += '.' + text.substr(i + elvl);
-            }
-            left = left.replace(/^[0]+/, '');
-            if (right < 0 && eright.indexOf('-') < 0) {
-                eright += ';-' + eright;
-            }
-            text = BI._numberFormat(left, eleft) + 'E' + BI._numberFormat(right, eright);
-            if (isNegative) {
-                text = '-' + text;
-            }
-        }
-        return text;
-    };
 })();
 /**
  * 事件集合
diff --git a/dist/core.js b/dist/core.js
index f1b2417b32..34490f02e5 100644
--- a/dist/core.js
+++ b/dist/core.js
@@ -19695,230 +19695,59 @@ BI.PopoverSection.EVENT_CLOSE = "EVENT_CLOSE";;(function () {
         return result;
     }
 
-    BI.cjkEncode = function (text) {
-        // alex:如果非字符串,返回其本身(cjkEncode(234) 返回 ""是不对的)
-        if (typeof text !== 'string') {
-            return text;
-        }
-
-        var newText = "";
-        for (var i = 0; i < text.length; i++) {
-            var code = text.charCodeAt(i);
-            if (code >= 128 || code === 91 || code === 93) {//91 is "[", 93 is "]".
-                newText += "[" + code.toString(16) + "]";
-            } else {
-                newText += text.charAt(i);
-            }
-        }
-
-        return newText
-    };
-
-    BI.cjkEncodeDO = function (o) {
-        if (BI.isPlainObject(o)) {
-            var result = {};
-            $.each(o, function (k, v) {
-                if (!(typeof v == "string")) {
-                    v = BI.jsonEncode(v);
-                }
-                //wei:bug 43338,如果key是中文,cjkencode后o的长度就加了1,ie9以下版本死循环,所以新建对象result。
-                k = BI.cjkEncode(k);
-                result[k] = BI.cjkEncode(v);
-            });
-            return result;
-        }
-        return o;
-    };
-
-    BI.jsonEncode = function (o) {
-        //james:这个Encode是抄的EXT的
-        var useHasOwn = {}.hasOwnProperty ? true : false;
-
-        // crashes Safari in some instances
-        //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
-
-        var m = {
-            "\b": '\\b',
-            "\t": '\\t',
-            "\n": '\\n',
-            "\f": '\\f',
-            "\r": '\\r',
-            '"': '\\"',
-            "\\": '\\\\'
-        };
-
-        var encodeString = function (s) {
-            if (/["\\\x00-\x1f]/.test(s)) {
-                return '"' + s.replace(/([\x00-\x1f\\"])/g, function (a, b) {
-                        var c = m[b];
-                        if (c) {
-                            return c;
-                        }
-                        c = b.charCodeAt();
-                        return "\\u00" +
-                            Math.floor(c / 16).toString(16) +
-                            (c % 16).toString(16);
-                    }) + '"';
-            }
-            return '"' + s + '"';
-        };
-
-        var encodeArray = function (o) {
-            var a = ["["], b, i, l = o.length, v;
-            for (i = 0; i < l; i += 1) {
-                v = o[i];
-                switch (typeof v) {
-                    case "undefined":
-                    case "function":
-                    case "unknown":
-                        break;
-                    default:
-                        if (b) {
-                            a.push(',');
-                        }
-                        a.push(v === null ? "null" : BI.jsonEncode(v));
-                        b = true;
-                }
-            }
-            a.push("]");
-            return a.join("");
-        };
+    // 判断是否是无效的日期
+    function isInvalidDate(date) {
+        return date == "Invalid Date" || date == "NaN";
+    }
 
-        if (typeof o == "undefined" || o === null) {
-            return "null";
-        } else if (BI.isArray(o)) {
-            return encodeArray(o);
-        } else if (o instanceof Date) {
-            /*
-             * alex:原来只是把年月日时分秒简单地拼成一个String,无法decode
-             * 现在这么处理就可以decode了,但是JS.jsonDecode和Java.JSONObject也要跟着改一下
-             */
-            return BI.jsonEncode({
-                __time__: o.getTime()
-            })
-        } else if (typeof o == "string") {
-            return encodeString(o);
-        } else if (typeof o == "number") {
-            return isFinite(o) ? String(o) : "null";
-        } else if (typeof o == "boolean") {
-            return String(o);
-        } else if (BI.isFunction(o)) {
-            return String(o);
+    /**
+     * 科学计数格式
+     */
+    function _eFormat(text, fmt) {
+        var e = fmt.indexOf("E");
+        var eleft = fmt.substr(0, e), eright = fmt.substr(e + 1);
+        if (/^[0\.-]+$/.test(text)) {
+            text = BI._numberFormat(0.0, eleft) + 'E' + BI._numberFormat(0, eright)
         } else {
-            var a = ["{"], b, i, v;
-            for (i in o) {
-                if (!useHasOwn || o.hasOwnProperty(i)) {
-                    v = o[i];
-                    switch (typeof v) {
-                        case "undefined":
-                        case "unknown":
-                            break;
-                        default:
-                            if (b) {
-                                a.push(',');
-                            }
-                            a.push(BI.jsonEncode(i), ":",
-                                v === null ? "null" : BI.jsonEncode(v));
-                            b = true;
-                    }
-                }
-            }
-            a.push("}");
-            return a.join("");
-        }
-    };
-
-    BI.jsonDecode = function (text) {
-
-        try {
-            // 注意0啊
-            //var jo = $.parseJSON(text) || {};
-            var jo = $.parseJSON(text);
-            if (jo == null) {
-                jo = {};
-            }
-        } catch (e) {
-            /*
-             * richie:浏览器只支持标准的JSON字符串转换,而jQuery会默认调用浏览器的window.JSON.parse()函数进行解析
-             * 比如:var str = "{'a':'b'}",这种形式的字符串转换为JSON就会抛异常
-             */
-            try {
-                jo = new Function("return " + text)() || {};
-            } catch (e) {
-                //do nothing
-            }
-            if (jo == null) {
-                jo = [];
-            }
-        }
-        if (!_hasDateInJson(text)) {
-            return jo;
-        }
-
-        function _hasDateInJson(json) {
-            if (!json || typeof json !== "string") {
-                return false;
-            }
-            return json.indexOf("__time__") != -1;
-        }
-
-        return (function (o) {
-            if (typeof o === "string") {
-                return o;
+            var isNegative = text < 0;
+            if (isNegative) {
+                text = text.substr(1);
             }
-            if (o && o.__time__ != null) {
-                return new Date(o.__time__);
+            var elvl = (eleft.split('.')[0] || '').length;
+            var point = text.indexOf(".");
+            if (point < 0) {
+                point = text.length;
             }
-            for (var a in o) {
-                if (o[a] == o || typeof o[a] == 'object' || $.isFunction(o[a])) {
+            var i = 0; //第一个不为0的数的位置
+            text = text.replace('.', '');
+            for (var len = text.length; i < len; i++) {
+                var ech = text.charAt(i);
+                if (ech <= '9' && ech >= '1') {
                     break;
                 }
-                o[a] = arguments.callee(o[a]);
             }
-
-            return o;
-        })(jo);
-    }
-
-    BI.contentFormat = function (cv, fmt) {
-        if (isEmpty(cv)) {
-            //原值为空,返回空字符
-            return '';
-        }
-        var text = cv.toString();
-        if (isEmpty(fmt)) {
-            //格式为空,返回原字符
-            return text;
-        }
-        if (fmt.match(/^T/)) {
-            //T - 文本格式
-            return text;
-        } else if (fmt.match(/^D/)) {
-            //D - 日期(时间)格式
-            if (!(cv instanceof Date)) {
-                if (typeof cv === 'number') {
-                    //毫秒数类型
-                    cv = new Date(cv);
-                } else {
-                    //字符串类型,如yyyyMMdd、MMddyyyy等这样无分隔符的结构
-                    cv = Date.parseDate(cv + "", Date.patterns.ISO8601Long);
+            var right = point - i - elvl;
+            var left = text.substr(i, elvl);
+            var dis = i + elvl - text.length;
+            if (dis > 0) {
+                //末位补全0
+                for (var k = 0; k < dis; k++) {
+                    left += '0';
                 }
+            } else {
+                left += '.' + text.substr(i + elvl);
             }
-            if (!BI.isNull(cv)) {
-                var needTrim = fmt.match(/^DT/);
-                text = BI.date2Str(cv, fmt.substring(needTrim ? 2 : 1));
+            left = left.replace(/^[0]+/, '');
+            if (right < 0 && eright.indexOf('-') < 0) {
+                eright += ';-' + eright;
+            }
+            text = BI._numberFormat(left, eleft) + 'E' + BI._numberFormat(right, eright);
+            if (isNegative) {
+                text = '-' + text;
             }
-        } else if (fmt.match(/E/)) {
-            //科学计数格式
-            text = BI._eFormat(text, fmt);
-        } else {
-            //数字格式
-            text = BI._numberFormat(text, fmt);
         }
-        //¤ - 货币格式
-        text = text.replace(/¤/g, '¥');
         return text;
-    };
+    }
 
     /**
      * 把日期对象按照指定格式转化成字符串
@@ -19932,7 +19761,7 @@ BI.PopoverSection.EVENT_CLOSE = "EVENT_CLOSE";;(function () {
      * @param format 日期格式
      * @returns {String}
      */
-    date2Str = function (date, format) {
+    function date2Str(date, format) {
         if (!date) {
             return '';
         }
@@ -20041,7 +19870,7 @@ BI.PopoverSection.EVENT_CLOSE = "EVENT_CLOSE";;(function () {
     /**
      * 数字格式
      */
-    BI._numberFormat = function (text, format) {
+    function _numberFormat(text, format) {
         var text = text + '';
         //数字格式,区分正负数
         var numMod = format.indexOf(';');
@@ -20063,7 +19892,7 @@ BI.PopoverSection.EVENT_CLOSE = "EVENT_CLOSE";;(function () {
             tleft = tleft.replace(/^0+/gi, '');
             tright = tright.substr(paddingZero.length).replace(/0+$/gi, '');
         }
-        var right = BI._dealWithRight(tright, fright);
+        var right = _dealWithRight(tright, fright);
         if (right.leftPlus) {
             //小数点后有进位
             tleft = parseInt(tleft) + 1 + '';
@@ -20071,7 +19900,7 @@ BI.PopoverSection.EVENT_CLOSE = "EVENT_CLOSE";;(function () {
             tleft = isNaN(tleft) ? '1' : tleft;
         }
         right = right.num;
-        var left = BI._dealWithLeft(tleft, fleft);
+        var left = _dealWithLeft(tleft, fleft);
         if (!(/[0-9]/.test(left))) {
             left = left + '0';
         }
@@ -20088,7 +19917,7 @@ BI.PopoverSection.EVENT_CLOSE = "EVENT_CLOSE";;(function () {
      * @returns {JSON} 返回处理结果和整数部分是否需要进位
      * @private
      */
-    BI._dealWithRight = function (tright, fright) {
+    function _dealWithRight(tright, fright) {
         var right = '', j = 0, i = 0;
         for (var len = fright.length; i < len; i++) {
             var ch = fright.charAt(i);
@@ -20119,7 +19948,7 @@ BI.PopoverSection.EVENT_CLOSE = "EVENT_CLOSE";;(function () {
             if (numReg) {
                 var num = numReg[0];
                 var orilen = num.length;
-                var newnum = BI.parseINT(num) + 1 + '';
+                var newnum = BI.parseInt(num) + 1 + '';
                 //进位到整数部分
                 if (newnum.length > orilen) {
                     newnum = newnum.substr(1);
@@ -20132,22 +19961,7 @@ BI.PopoverSection.EVENT_CLOSE = "EVENT_CLOSE";;(function () {
         }
         result.num = right;
         return result;
-    };
-
-    BI.parseINT = function (str) {
-        return parseInt(str, 10);
-    };
-
-    BI.leftPad = function (val, size, ch) {
-        var result = String(val);
-        if (!ch) {
-            ch = " ";
-        }
-        while (result.length < size) {
-            result = ch + result;
-        }
-        return result.toString();
-    };
+    }
 
     /**
      * 处理小数点左边整数部分
@@ -20156,7 +19970,7 @@ BI.PopoverSection.EVENT_CLOSE = "EVENT_CLOSE";;(function () {
      * @returns {string} 返回处理结果
      * @private
      */
-    BI._dealWithLeft = function (tleft, fleft) {
+    function _dealWithLeft(tleft, fleft) {
         var left = '';
         var j = tleft.length - 1;
         var combo = -1, last = -1;
@@ -20215,6 +20029,242 @@ BI.PopoverSection.EVENT_CLOSE = "EVENT_CLOSE";;(function () {
             left = left.replace(/[0-9]+,/, newstr);
         }
         return left;
+    }
+
+    BI.cjkEncode = function (text) {
+        // alex:如果非字符串,返回其本身(cjkEncode(234) 返回 ""是不对的)
+        if (typeof text !== 'string') {
+            return text;
+        }
+
+        var newText = "";
+        for (var i = 0; i < text.length; i++) {
+            var code = text.charCodeAt(i);
+            if (code >= 128 || code === 91 || code === 93) {//91 is "[", 93 is "]".
+                newText += "[" + code.toString(16) + "]";
+            } else {
+                newText += text.charAt(i);
+            }
+        }
+
+        return newText
+    };
+
+    BI.cjkEncodeDO = function (o) {
+        if (BI.isPlainObject(o)) {
+            var result = {};
+            $.each(o, function (k, v) {
+                if (!(typeof v == "string")) {
+                    v = BI.jsonEncode(v);
+                }
+                //wei:bug 43338,如果key是中文,cjkencode后o的长度就加了1,ie9以下版本死循环,所以新建对象result。
+                k = BI.cjkEncode(k);
+                result[k] = BI.cjkEncode(v);
+            });
+            return result;
+        }
+        return o;
+    };
+
+    BI.jsonEncode = function (o) {
+        //james:这个Encode是抄的EXT的
+        var useHasOwn = {}.hasOwnProperty ? true : false;
+
+        // crashes Safari in some instances
+        //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
+
+        var m = {
+            "\b": '\\b',
+            "\t": '\\t',
+            "\n": '\\n',
+            "\f": '\\f',
+            "\r": '\\r',
+            '"': '\\"',
+            "\\": '\\\\'
+        };
+
+        var encodeString = function (s) {
+            if (/["\\\x00-\x1f]/.test(s)) {
+                return '"' + s.replace(/([\x00-\x1f\\"])/g, function (a, b) {
+                        var c = m[b];
+                        if (c) {
+                            return c;
+                        }
+                        c = b.charCodeAt();
+                        return "\\u00" +
+                            Math.floor(c / 16).toString(16) +
+                            (c % 16).toString(16);
+                    }) + '"';
+            }
+            return '"' + s + '"';
+        };
+
+        var encodeArray = function (o) {
+            var a = ["["], b, i, l = o.length, v;
+            for (i = 0; i < l; i += 1) {
+                v = o[i];
+                switch (typeof v) {
+                    case "undefined":
+                    case "function":
+                    case "unknown":
+                        break;
+                    default:
+                        if (b) {
+                            a.push(',');
+                        }
+                        a.push(v === null ? "null" : BI.jsonEncode(v));
+                        b = true;
+                }
+            }
+            a.push("]");
+            return a.join("");
+        };
+
+        if (typeof o == "undefined" || o === null) {
+            return "null";
+        } else if (BI.isArray(o)) {
+            return encodeArray(o);
+        } else if (o instanceof Date) {
+            /*
+             * alex:原来只是把年月日时分秒简单地拼成一个String,无法decode
+             * 现在这么处理就可以decode了,但是JS.jsonDecode和Java.JSONObject也要跟着改一下
+             */
+            return BI.jsonEncode({
+                __time__: o.getTime()
+            })
+        } else if (typeof o == "string") {
+            return encodeString(o);
+        } else if (typeof o == "number") {
+            return isFinite(o) ? String(o) : "null";
+        } else if (typeof o == "boolean") {
+            return String(o);
+        } else if (BI.isFunction(o)) {
+            return String(o);
+        } else {
+            var a = ["{"], b, i, v;
+            for (i in o) {
+                if (!useHasOwn || o.hasOwnProperty(i)) {
+                    v = o[i];
+                    switch (typeof v) {
+                        case "undefined":
+                        case "unknown":
+                            break;
+                        default:
+                            if (b) {
+                                a.push(',');
+                            }
+                            a.push(BI.jsonEncode(i), ":",
+                                v === null ? "null" : BI.jsonEncode(v));
+                            b = true;
+                    }
+                }
+            }
+            a.push("}");
+            return a.join("");
+        }
+    };
+
+    BI.jsonDecode = function (text) {
+
+        try {
+            // 注意0啊
+            //var jo = $.parseJSON(text) || {};
+            var jo = $.parseJSON(text);
+            if (jo == null) {
+                jo = {};
+            }
+        } catch (e) {
+            /*
+             * richie:浏览器只支持标准的JSON字符串转换,而jQuery会默认调用浏览器的window.JSON.parse()函数进行解析
+             * 比如:var str = "{'a':'b'}",这种形式的字符串转换为JSON就会抛异常
+             */
+            try {
+                jo = new Function("return " + text)() || {};
+            } catch (e) {
+                //do nothing
+            }
+            if (jo == null) {
+                jo = [];
+            }
+        }
+        if (!_hasDateInJson(text)) {
+            return jo;
+        }
+
+        function _hasDateInJson(json) {
+            if (!json || typeof json !== "string") {
+                return false;
+            }
+            return json.indexOf("__time__") != -1;
+        }
+
+        return (function (o) {
+            if (typeof o === "string") {
+                return o;
+            }
+            if (o && o.__time__ != null) {
+                return new Date(o.__time__);
+            }
+            for (var a in o) {
+                if (o[a] == o || typeof o[a] == 'object' || $.isFunction(o[a])) {
+                    break;
+                }
+                o[a] = arguments.callee(o[a]);
+            }
+
+            return o;
+        })(jo);
+    }
+
+    BI.contentFormat = function (cv, fmt) {
+        if (isEmpty(cv)) {
+            //原值为空,返回空字符
+            return '';
+        }
+        var text = cv.toString();
+        if (isEmpty(fmt)) {
+            //格式为空,返回原字符
+            return text;
+        }
+        if (fmt.match(/^T/)) {
+            //T - 文本格式
+            return text;
+        } else if (fmt.match(/^D/)) {
+            //D - 日期(时间)格式
+            if (!(cv instanceof Date)) {
+                if (typeof cv === 'number') {
+                    //毫秒数类型
+                    cv = new Date(cv);
+                } else {
+                    //字符串类型,如yyyyMMdd、MMddyyyy等这样无分隔符的结构
+                    cv = Date.parseDate(cv + "", Date.patterns.ISO8601Long);
+                }
+            }
+            if (!BI.isNull(cv)) {
+                var needTrim = fmt.match(/^DT/);
+                text = BI.date2Str(cv, fmt.substring(needTrim ? 2 : 1));
+            }
+        } else if (fmt.match(/E/)) {
+            //科学计数格式
+            text = _eFormat(text, fmt);
+        } else {
+            //数字格式
+            text = _numberFormat(text, fmt);
+        }
+        //¤ - 货币格式
+        text = text.replace(/¤/g, '¥');
+        return text;
+    };
+
+    BI.leftPad = function (val, size, ch) {
+        var result = String(val);
+        if (!ch) {
+            ch = " ";
+        }
+        while (result.length < size) {
+            result = ch + result;
+        }
+        return result.toString();
     };
 
     BI.object2Number = function (value) {
@@ -20245,7 +20295,7 @@ BI.PopoverSection.EVENT_CLOSE = "EVENT_CLOSE";;(function () {
             var str = obj + "";
             str = str.replace(/-/g, '/');
             var dt = new Date(str);
-            if (!BI.isInvalidDate(dt)) {
+            if (!isInvalidDate(dt)) {
                 return dt;
             }
 
@@ -20253,10 +20303,6 @@ BI.PopoverSection.EVENT_CLOSE = "EVENT_CLOSE";;(function () {
         }
     };
 
-    BI.isArray = function (a) {
-        return Object.prototype.toString.call(a) == '[object Array]';
-    };
-
     BI.object2Time = function (obj) {
         if (obj == null) {
             return new Date();
@@ -20267,77 +20313,22 @@ BI.PopoverSection.EVENT_CLOSE = "EVENT_CLOSE";;(function () {
             var str = obj + "";
             str = str.replace(/-/g, '/');
             var dt = new Date(str);
-            if (!BI.isInvalidDate(dt)) {
+            if (!isInvalidDate(dt)) {
                 return dt;
             }
             if (str.indexOf('/') === -1 && str.indexOf(':') !== -1) {
                 dt = new Date("1970/01/01 " + str);
-                if (!BI.isInvalidDate(dt)) {
+                if (!isInvalidDate(dt)) {
                     return dt;
                 }
             }
             dt = BI.str2Date(str, "HH:mm:ss");
-            if (!BI.isInvalidDate(dt)) {
+            if (!isInvalidDate(dt)) {
                 return dt;
             }
             return new Date();
         }
     };
-
-// 判断是否是无效的日期
-    BI.isInvalidDate = function (date) {
-        return date == "Invalid Date" || date == "NaN";
-    };
-
-
-    /**
-     * 科学计数格式
-     */
-    BI._eFormat = function (text, fmt) {
-        var e = fmt.indexOf("E");
-        var eleft = fmt.substr(0, e), eright = fmt.substr(e + 1);
-        if (/^[0\.-]+$/.test(text)) {
-            text = BI._numberFormat(0.0, eleft) + 'E' + BI._numberFormat(0, eright)
-        } else {
-            var isNegative = text < 0;
-            if (isNegative) {
-                text = text.substr(1);
-            }
-            var elvl = (eleft.split('.')[0] || '').length;
-            var point = text.indexOf(".");
-            if (point < 0) {
-                point = text.length;
-            }
-            var i = 0; //第一个不为0的数的位置
-            text = text.replace('.', '');
-            for (var len = text.length; i < len; i++) {
-                var ech = text.charAt(i);
-                if (ech <= '9' && ech >= '1') {
-                    break;
-                }
-            }
-            var right = point - i - elvl;
-            var left = text.substr(i, elvl);
-            var dis = i + elvl - text.length;
-            if (dis > 0) {
-                //末位补全0
-                for (var k = 0; k < dis; k++) {
-                    left += '0';
-                }
-            } else {
-                left += '.' + text.substr(i + elvl);
-            }
-            left = left.replace(/^[0]+/, '');
-            if (right < 0 && eright.indexOf('-') < 0) {
-                eright += ';-' + eright;
-            }
-            text = BI._numberFormat(left, eleft) + 'E' + BI._numberFormat(right, eright);
-            if (isNegative) {
-                text = '-' + text;
-            }
-        }
-        return text;
-    };
 })();
 /**
  * guy
diff --git a/src/core/alias.js b/src/core/alias.js
index 26d5c2a120..d86d76af8b 100644
--- a/src/core/alias.js
+++ b/src/core/alias.js
@@ -5,230 +5,59 @@
         return result;
     }
 
-    BI.cjkEncode = function (text) {
-        // alex:如果非字符串,返回其本身(cjkEncode(234) 返回 ""是不对的)
-        if (typeof text !== 'string') {
-            return text;
-        }
-
-        var newText = "";
-        for (var i = 0; i < text.length; i++) {
-            var code = text.charCodeAt(i);
-            if (code >= 128 || code === 91 || code === 93) {//91 is "[", 93 is "]".
-                newText += "[" + code.toString(16) + "]";
-            } else {
-                newText += text.charAt(i);
-            }
-        }
-
-        return newText
-    };
-
-    BI.cjkEncodeDO = function (o) {
-        if (BI.isPlainObject(o)) {
-            var result = {};
-            $.each(o, function (k, v) {
-                if (!(typeof v == "string")) {
-                    v = BI.jsonEncode(v);
-                }
-                //wei:bug 43338,如果key是中文,cjkencode后o的长度就加了1,ie9以下版本死循环,所以新建对象result。
-                k = BI.cjkEncode(k);
-                result[k] = BI.cjkEncode(v);
-            });
-            return result;
-        }
-        return o;
-    };
-
-    BI.jsonEncode = function (o) {
-        //james:这个Encode是抄的EXT的
-        var useHasOwn = {}.hasOwnProperty ? true : false;
-
-        // crashes Safari in some instances
-        //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
-
-        var m = {
-            "\b": '\\b',
-            "\t": '\\t',
-            "\n": '\\n',
-            "\f": '\\f',
-            "\r": '\\r',
-            '"': '\\"',
-            "\\": '\\\\'
-        };
-
-        var encodeString = function (s) {
-            if (/["\\\x00-\x1f]/.test(s)) {
-                return '"' + s.replace(/([\x00-\x1f\\"])/g, function (a, b) {
-                        var c = m[b];
-                        if (c) {
-                            return c;
-                        }
-                        c = b.charCodeAt();
-                        return "\\u00" +
-                            Math.floor(c / 16).toString(16) +
-                            (c % 16).toString(16);
-                    }) + '"';
-            }
-            return '"' + s + '"';
-        };
-
-        var encodeArray = function (o) {
-            var a = ["["], b, i, l = o.length, v;
-            for (i = 0; i < l; i += 1) {
-                v = o[i];
-                switch (typeof v) {
-                    case "undefined":
-                    case "function":
-                    case "unknown":
-                        break;
-                    default:
-                        if (b) {
-                            a.push(',');
-                        }
-                        a.push(v === null ? "null" : BI.jsonEncode(v));
-                        b = true;
-                }
-            }
-            a.push("]");
-            return a.join("");
-        };
+    // 判断是否是无效的日期
+    function isInvalidDate(date) {
+        return date == "Invalid Date" || date == "NaN";
+    }
 
-        if (typeof o == "undefined" || o === null) {
-            return "null";
-        } else if (BI.isArray(o)) {
-            return encodeArray(o);
-        } else if (o instanceof Date) {
-            /*
-             * alex:原来只是把年月日时分秒简单地拼成一个String,无法decode
-             * 现在这么处理就可以decode了,但是JS.jsonDecode和Java.JSONObject也要跟着改一下
-             */
-            return BI.jsonEncode({
-                __time__: o.getTime()
-            })
-        } else if (typeof o == "string") {
-            return encodeString(o);
-        } else if (typeof o == "number") {
-            return isFinite(o) ? String(o) : "null";
-        } else if (typeof o == "boolean") {
-            return String(o);
-        } else if (BI.isFunction(o)) {
-            return String(o);
+    /**
+     * 科学计数格式
+     */
+    function _eFormat(text, fmt) {
+        var e = fmt.indexOf("E");
+        var eleft = fmt.substr(0, e), eright = fmt.substr(e + 1);
+        if (/^[0\.-]+$/.test(text)) {
+            text = BI._numberFormat(0.0, eleft) + 'E' + BI._numberFormat(0, eright)
         } else {
-            var a = ["{"], b, i, v;
-            for (i in o) {
-                if (!useHasOwn || o.hasOwnProperty(i)) {
-                    v = o[i];
-                    switch (typeof v) {
-                        case "undefined":
-                        case "unknown":
-                            break;
-                        default:
-                            if (b) {
-                                a.push(',');
-                            }
-                            a.push(BI.jsonEncode(i), ":",
-                                v === null ? "null" : BI.jsonEncode(v));
-                            b = true;
-                    }
-                }
-            }
-            a.push("}");
-            return a.join("");
-        }
-    };
-
-    BI.jsonDecode = function (text) {
-
-        try {
-            // 注意0啊
-            //var jo = $.parseJSON(text) || {};
-            var jo = $.parseJSON(text);
-            if (jo == null) {
-                jo = {};
-            }
-        } catch (e) {
-            /*
-             * richie:浏览器只支持标准的JSON字符串转换,而jQuery会默认调用浏览器的window.JSON.parse()函数进行解析
-             * 比如:var str = "{'a':'b'}",这种形式的字符串转换为JSON就会抛异常
-             */
-            try {
-                jo = new Function("return " + text)() || {};
-            } catch (e) {
-                //do nothing
-            }
-            if (jo == null) {
-                jo = [];
-            }
-        }
-        if (!_hasDateInJson(text)) {
-            return jo;
-        }
-
-        function _hasDateInJson(json) {
-            if (!json || typeof json !== "string") {
-                return false;
-            }
-            return json.indexOf("__time__") != -1;
-        }
-
-        return (function (o) {
-            if (typeof o === "string") {
-                return o;
+            var isNegative = text < 0;
+            if (isNegative) {
+                text = text.substr(1);
             }
-            if (o && o.__time__ != null) {
-                return new Date(o.__time__);
+            var elvl = (eleft.split('.')[0] || '').length;
+            var point = text.indexOf(".");
+            if (point < 0) {
+                point = text.length;
             }
-            for (var a in o) {
-                if (o[a] == o || typeof o[a] == 'object' || $.isFunction(o[a])) {
+            var i = 0; //第一个不为0的数的位置
+            text = text.replace('.', '');
+            for (var len = text.length; i < len; i++) {
+                var ech = text.charAt(i);
+                if (ech <= '9' && ech >= '1') {
                     break;
                 }
-                o[a] = arguments.callee(o[a]);
             }
-
-            return o;
-        })(jo);
-    }
-
-    BI.contentFormat = function (cv, fmt) {
-        if (isEmpty(cv)) {
-            //原值为空,返回空字符
-            return '';
-        }
-        var text = cv.toString();
-        if (isEmpty(fmt)) {
-            //格式为空,返回原字符
-            return text;
-        }
-        if (fmt.match(/^T/)) {
-            //T - 文本格式
-            return text;
-        } else if (fmt.match(/^D/)) {
-            //D - 日期(时间)格式
-            if (!(cv instanceof Date)) {
-                if (typeof cv === 'number') {
-                    //毫秒数类型
-                    cv = new Date(cv);
-                } else {
-                    //字符串类型,如yyyyMMdd、MMddyyyy等这样无分隔符的结构
-                    cv = Date.parseDate(cv + "", Date.patterns.ISO8601Long);
+            var right = point - i - elvl;
+            var left = text.substr(i, elvl);
+            var dis = i + elvl - text.length;
+            if (dis > 0) {
+                //末位补全0
+                for (var k = 0; k < dis; k++) {
+                    left += '0';
                 }
+            } else {
+                left += '.' + text.substr(i + elvl);
             }
-            if (!BI.isNull(cv)) {
-                var needTrim = fmt.match(/^DT/);
-                text = BI.date2Str(cv, fmt.substring(needTrim ? 2 : 1));
+            left = left.replace(/^[0]+/, '');
+            if (right < 0 && eright.indexOf('-') < 0) {
+                eright += ';-' + eright;
+            }
+            text = BI._numberFormat(left, eleft) + 'E' + BI._numberFormat(right, eright);
+            if (isNegative) {
+                text = '-' + text;
             }
-        } else if (fmt.match(/E/)) {
-            //科学计数格式
-            text = BI._eFormat(text, fmt);
-        } else {
-            //数字格式
-            text = BI._numberFormat(text, fmt);
         }
-        //¤ - 货币格式
-        text = text.replace(/¤/g, '¥');
         return text;
-    };
+    }
 
     /**
      * 把日期对象按照指定格式转化成字符串
@@ -242,7 +71,7 @@
      * @param format 日期格式
      * @returns {String}
      */
-    date2Str = function (date, format) {
+    function date2Str(date, format) {
         if (!date) {
             return '';
         }
@@ -351,7 +180,7 @@
     /**
      * 数字格式
      */
-    BI._numberFormat = function (text, format) {
+    function _numberFormat(text, format) {
         var text = text + '';
         //数字格式,区分正负数
         var numMod = format.indexOf(';');
@@ -373,7 +202,7 @@
             tleft = tleft.replace(/^0+/gi, '');
             tright = tright.substr(paddingZero.length).replace(/0+$/gi, '');
         }
-        var right = BI._dealWithRight(tright, fright);
+        var right = _dealWithRight(tright, fright);
         if (right.leftPlus) {
             //小数点后有进位
             tleft = parseInt(tleft) + 1 + '';
@@ -381,7 +210,7 @@
             tleft = isNaN(tleft) ? '1' : tleft;
         }
         right = right.num;
-        var left = BI._dealWithLeft(tleft, fleft);
+        var left = _dealWithLeft(tleft, fleft);
         if (!(/[0-9]/.test(left))) {
             left = left + '0';
         }
@@ -398,7 +227,7 @@
      * @returns {JSON} 返回处理结果和整数部分是否需要进位
      * @private
      */
-    BI._dealWithRight = function (tright, fright) {
+    function _dealWithRight(tright, fright) {
         var right = '', j = 0, i = 0;
         for (var len = fright.length; i < len; i++) {
             var ch = fright.charAt(i);
@@ -429,7 +258,7 @@
             if (numReg) {
                 var num = numReg[0];
                 var orilen = num.length;
-                var newnum = BI.parseINT(num) + 1 + '';
+                var newnum = BI.parseInt(num) + 1 + '';
                 //进位到整数部分
                 if (newnum.length > orilen) {
                     newnum = newnum.substr(1);
@@ -442,22 +271,7 @@
         }
         result.num = right;
         return result;
-    };
-
-    BI.parseINT = function (str) {
-        return parseInt(str, 10);
-    };
-
-    BI.leftPad = function (val, size, ch) {
-        var result = String(val);
-        if (!ch) {
-            ch = " ";
-        }
-        while (result.length < size) {
-            result = ch + result;
-        }
-        return result.toString();
-    };
+    }
 
     /**
      * 处理小数点左边整数部分
@@ -466,7 +280,7 @@
      * @returns {string} 返回处理结果
      * @private
      */
-    BI._dealWithLeft = function (tleft, fleft) {
+    function _dealWithLeft(tleft, fleft) {
         var left = '';
         var j = tleft.length - 1;
         var combo = -1, last = -1;
@@ -525,6 +339,242 @@
             left = left.replace(/[0-9]+,/, newstr);
         }
         return left;
+    }
+
+    BI.cjkEncode = function (text) {
+        // alex:如果非字符串,返回其本身(cjkEncode(234) 返回 ""是不对的)
+        if (typeof text !== 'string') {
+            return text;
+        }
+
+        var newText = "";
+        for (var i = 0; i < text.length; i++) {
+            var code = text.charCodeAt(i);
+            if (code >= 128 || code === 91 || code === 93) {//91 is "[", 93 is "]".
+                newText += "[" + code.toString(16) + "]";
+            } else {
+                newText += text.charAt(i);
+            }
+        }
+
+        return newText
+    };
+
+    BI.cjkEncodeDO = function (o) {
+        if (BI.isPlainObject(o)) {
+            var result = {};
+            $.each(o, function (k, v) {
+                if (!(typeof v == "string")) {
+                    v = BI.jsonEncode(v);
+                }
+                //wei:bug 43338,如果key是中文,cjkencode后o的长度就加了1,ie9以下版本死循环,所以新建对象result。
+                k = BI.cjkEncode(k);
+                result[k] = BI.cjkEncode(v);
+            });
+            return result;
+        }
+        return o;
+    };
+
+    BI.jsonEncode = function (o) {
+        //james:这个Encode是抄的EXT的
+        var useHasOwn = {}.hasOwnProperty ? true : false;
+
+        // crashes Safari in some instances
+        //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
+
+        var m = {
+            "\b": '\\b',
+            "\t": '\\t',
+            "\n": '\\n',
+            "\f": '\\f',
+            "\r": '\\r',
+            '"': '\\"',
+            "\\": '\\\\'
+        };
+
+        var encodeString = function (s) {
+            if (/["\\\x00-\x1f]/.test(s)) {
+                return '"' + s.replace(/([\x00-\x1f\\"])/g, function (a, b) {
+                        var c = m[b];
+                        if (c) {
+                            return c;
+                        }
+                        c = b.charCodeAt();
+                        return "\\u00" +
+                            Math.floor(c / 16).toString(16) +
+                            (c % 16).toString(16);
+                    }) + '"';
+            }
+            return '"' + s + '"';
+        };
+
+        var encodeArray = function (o) {
+            var a = ["["], b, i, l = o.length, v;
+            for (i = 0; i < l; i += 1) {
+                v = o[i];
+                switch (typeof v) {
+                    case "undefined":
+                    case "function":
+                    case "unknown":
+                        break;
+                    default:
+                        if (b) {
+                            a.push(',');
+                        }
+                        a.push(v === null ? "null" : BI.jsonEncode(v));
+                        b = true;
+                }
+            }
+            a.push("]");
+            return a.join("");
+        };
+
+        if (typeof o == "undefined" || o === null) {
+            return "null";
+        } else if (BI.isArray(o)) {
+            return encodeArray(o);
+        } else if (o instanceof Date) {
+            /*
+             * alex:原来只是把年月日时分秒简单地拼成一个String,无法decode
+             * 现在这么处理就可以decode了,但是JS.jsonDecode和Java.JSONObject也要跟着改一下
+             */
+            return BI.jsonEncode({
+                __time__: o.getTime()
+            })
+        } else if (typeof o == "string") {
+            return encodeString(o);
+        } else if (typeof o == "number") {
+            return isFinite(o) ? String(o) : "null";
+        } else if (typeof o == "boolean") {
+            return String(o);
+        } else if (BI.isFunction(o)) {
+            return String(o);
+        } else {
+            var a = ["{"], b, i, v;
+            for (i in o) {
+                if (!useHasOwn || o.hasOwnProperty(i)) {
+                    v = o[i];
+                    switch (typeof v) {
+                        case "undefined":
+                        case "unknown":
+                            break;
+                        default:
+                            if (b) {
+                                a.push(',');
+                            }
+                            a.push(BI.jsonEncode(i), ":",
+                                v === null ? "null" : BI.jsonEncode(v));
+                            b = true;
+                    }
+                }
+            }
+            a.push("}");
+            return a.join("");
+        }
+    };
+
+    BI.jsonDecode = function (text) {
+
+        try {
+            // 注意0啊
+            //var jo = $.parseJSON(text) || {};
+            var jo = $.parseJSON(text);
+            if (jo == null) {
+                jo = {};
+            }
+        } catch (e) {
+            /*
+             * richie:浏览器只支持标准的JSON字符串转换,而jQuery会默认调用浏览器的window.JSON.parse()函数进行解析
+             * 比如:var str = "{'a':'b'}",这种形式的字符串转换为JSON就会抛异常
+             */
+            try {
+                jo = new Function("return " + text)() || {};
+            } catch (e) {
+                //do nothing
+            }
+            if (jo == null) {
+                jo = [];
+            }
+        }
+        if (!_hasDateInJson(text)) {
+            return jo;
+        }
+
+        function _hasDateInJson(json) {
+            if (!json || typeof json !== "string") {
+                return false;
+            }
+            return json.indexOf("__time__") != -1;
+        }
+
+        return (function (o) {
+            if (typeof o === "string") {
+                return o;
+            }
+            if (o && o.__time__ != null) {
+                return new Date(o.__time__);
+            }
+            for (var a in o) {
+                if (o[a] == o || typeof o[a] == 'object' || $.isFunction(o[a])) {
+                    break;
+                }
+                o[a] = arguments.callee(o[a]);
+            }
+
+            return o;
+        })(jo);
+    }
+
+    BI.contentFormat = function (cv, fmt) {
+        if (isEmpty(cv)) {
+            //原值为空,返回空字符
+            return '';
+        }
+        var text = cv.toString();
+        if (isEmpty(fmt)) {
+            //格式为空,返回原字符
+            return text;
+        }
+        if (fmt.match(/^T/)) {
+            //T - 文本格式
+            return text;
+        } else if (fmt.match(/^D/)) {
+            //D - 日期(时间)格式
+            if (!(cv instanceof Date)) {
+                if (typeof cv === 'number') {
+                    //毫秒数类型
+                    cv = new Date(cv);
+                } else {
+                    //字符串类型,如yyyyMMdd、MMddyyyy等这样无分隔符的结构
+                    cv = Date.parseDate(cv + "", Date.patterns.ISO8601Long);
+                }
+            }
+            if (!BI.isNull(cv)) {
+                var needTrim = fmt.match(/^DT/);
+                text = BI.date2Str(cv, fmt.substring(needTrim ? 2 : 1));
+            }
+        } else if (fmt.match(/E/)) {
+            //科学计数格式
+            text = _eFormat(text, fmt);
+        } else {
+            //数字格式
+            text = _numberFormat(text, fmt);
+        }
+        //¤ - 货币格式
+        text = text.replace(/¤/g, '¥');
+        return text;
+    };
+
+    BI.leftPad = function (val, size, ch) {
+        var result = String(val);
+        if (!ch) {
+            ch = " ";
+        }
+        while (result.length < size) {
+            result = ch + result;
+        }
+        return result.toString();
     };
 
     BI.object2Number = function (value) {
@@ -555,7 +605,7 @@
             var str = obj + "";
             str = str.replace(/-/g, '/');
             var dt = new Date(str);
-            if (!BI.isInvalidDate(dt)) {
+            if (!isInvalidDate(dt)) {
                 return dt;
             }
 
@@ -563,10 +613,6 @@
         }
     };
 
-    BI.isArray = function (a) {
-        return Object.prototype.toString.call(a) == '[object Array]';
-    };
-
     BI.object2Time = function (obj) {
         if (obj == null) {
             return new Date();
@@ -577,75 +623,20 @@
             var str = obj + "";
             str = str.replace(/-/g, '/');
             var dt = new Date(str);
-            if (!BI.isInvalidDate(dt)) {
+            if (!isInvalidDate(dt)) {
                 return dt;
             }
             if (str.indexOf('/') === -1 && str.indexOf(':') !== -1) {
                 dt = new Date("1970/01/01 " + str);
-                if (!BI.isInvalidDate(dt)) {
+                if (!isInvalidDate(dt)) {
                     return dt;
                 }
             }
             dt = BI.str2Date(str, "HH:mm:ss");
-            if (!BI.isInvalidDate(dt)) {
+            if (!isInvalidDate(dt)) {
                 return dt;
             }
             return new Date();
         }
     };
-
-// 判断是否是无效的日期
-    BI.isInvalidDate = function (date) {
-        return date == "Invalid Date" || date == "NaN";
-    };
-
-
-    /**
-     * 科学计数格式
-     */
-    BI._eFormat = function (text, fmt) {
-        var e = fmt.indexOf("E");
-        var eleft = fmt.substr(0, e), eright = fmt.substr(e + 1);
-        if (/^[0\.-]+$/.test(text)) {
-            text = BI._numberFormat(0.0, eleft) + 'E' + BI._numberFormat(0, eright)
-        } else {
-            var isNegative = text < 0;
-            if (isNegative) {
-                text = text.substr(1);
-            }
-            var elvl = (eleft.split('.')[0] || '').length;
-            var point = text.indexOf(".");
-            if (point < 0) {
-                point = text.length;
-            }
-            var i = 0; //第一个不为0的数的位置
-            text = text.replace('.', '');
-            for (var len = text.length; i < len; i++) {
-                var ech = text.charAt(i);
-                if (ech <= '9' && ech >= '1') {
-                    break;
-                }
-            }
-            var right = point - i - elvl;
-            var left = text.substr(i, elvl);
-            var dis = i + elvl - text.length;
-            if (dis > 0) {
-                //末位补全0
-                for (var k = 0; k < dis; k++) {
-                    left += '0';
-                }
-            } else {
-                left += '.' + text.substr(i + elvl);
-            }
-            left = left.replace(/^[0]+/, '');
-            if (right < 0 && eright.indexOf('-') < 0) {
-                eright += ';-' + eright;
-            }
-            text = BI._numberFormat(left, eleft) + 'E' + BI._numberFormat(right, eright);
-            if (isNegative) {
-                text = '-' + text;
-            }
-        }
-        return text;
-    };
 })();

From 5db561f57a9b6e2a9d3357806675175523406ea5 Mon Sep 17 00:00:00 2001
From: guy <guy@finereport.com>
Date: Thu, 30 Mar 2017 16:30:36 +0800
Subject: [PATCH 14/19] add

---
 bi/base.js                    | 4 ++--
 dist/base.js                  | 4 ++--
 src/base/single/input/file.js | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/bi/base.js b/bi/base.js
index 8f157d02a5..41d9f2b6f2 100644
--- a/bi/base.js
+++ b/bi/base.js
@@ -18259,7 +18259,7 @@ BI.shortcut("bi.checkbox", BI.Checkbox);/**
                     },
                     false
                 );
-                xhr.open("post", handler.url + '&filename=' + BI.cjkEncode(handler.file.fileName), true);
+                xhr.open("post", handler.url + '&filename=' + window.encodeURIComponent(handler.file.fileName), true);
                 if (!xhr.upload) {
                     var rpe = {loaded: 0, total: handler.file.fileSize || handler.file.size, simulation: true};
                     rpe.interval = setInterval(function () {
@@ -18708,7 +18708,7 @@ BI.shortcut("bi.checkbox", BI.Checkbox);/**
         },
 
         setEnable: function (enable) {
-            BI.MultiFile.superclass.setEnable.apply(this, arguments);
+            BI.File.superclass.setEnable.apply(this, arguments);
             if (enable === true) {
                 this.element.attr("disabled", "disabled");
             } else {
diff --git a/dist/base.js b/dist/base.js
index 8f157d02a5..41d9f2b6f2 100644
--- a/dist/base.js
+++ b/dist/base.js
@@ -18259,7 +18259,7 @@ BI.shortcut("bi.checkbox", BI.Checkbox);/**
                     },
                     false
                 );
-                xhr.open("post", handler.url + '&filename=' + BI.cjkEncode(handler.file.fileName), true);
+                xhr.open("post", handler.url + '&filename=' + window.encodeURIComponent(handler.file.fileName), true);
                 if (!xhr.upload) {
                     var rpe = {loaded: 0, total: handler.file.fileSize || handler.file.size, simulation: true};
                     rpe.interval = setInterval(function () {
@@ -18708,7 +18708,7 @@ BI.shortcut("bi.checkbox", BI.Checkbox);/**
         },
 
         setEnable: function (enable) {
-            BI.MultiFile.superclass.setEnable.apply(this, arguments);
+            BI.File.superclass.setEnable.apply(this, arguments);
             if (enable === true) {
                 this.element.attr("disabled", "disabled");
             } else {
diff --git a/src/base/single/input/file.js b/src/base/single/input/file.js
index ea592bb9d2..001770c554 100644
--- a/src/base/single/input/file.js
+++ b/src/base/single/input/file.js
@@ -153,7 +153,7 @@
                     },
                     false
                 );
-                xhr.open("post", handler.url + '&filename=' + BI.cjkEncode(handler.file.fileName), true);
+                xhr.open("post", handler.url + '&filename=' + window.encodeURIComponent(handler.file.fileName), true);
                 if (!xhr.upload) {
                     var rpe = {loaded: 0, total: handler.file.fileSize || handler.file.size, simulation: true};
                     rpe.interval = setInterval(function () {
@@ -602,7 +602,7 @@
         },
 
         setEnable: function (enable) {
-            BI.MultiFile.superclass.setEnable.apply(this, arguments);
+            BI.File.superclass.setEnable.apply(this, arguments);
             if (enable === true) {
                 this.element.attr("disabled", "disabled");
             } else {

From 4b326d912a2441bb8705b3100e704c785d2bdbda Mon Sep 17 00:00:00 2001
From: guy <guy@finereport.com>
Date: Thu, 30 Mar 2017 16:40:40 +0800
Subject: [PATCH 15/19] add

---
 bi/widget.js                        | 4 +---
 dist/widget.js                      | 4 +---
 src/widget/exceltable/exceltable.js | 4 +---
 3 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/bi/widget.js b/bi/widget.js
index 75b27e101c..0b4b685469 100644
--- a/bi/widget.js
+++ b/bi/widget.js
@@ -6157,7 +6157,7 @@ BI.ExcelTable = BI.inherit(BI.Widget, {
         return BI.extend(BI.ExcelTable.superclass._defaultConfig.apply(this, arguments), {
             baseCls: "bi-excel-table",
             el: {
-                type: "bi.adaptive_table"
+                type: "bi.responsive_table"
             },
 
             isNeedResize: false,
@@ -6191,8 +6191,6 @@ BI.ExcelTable = BI.inherit(BI.Widget, {
         this.table = BI.createWidget(o.el, {
             type: "bi.table_view",
             element: this,
-            isNeedResize: o.isNeedResize,
-            isResizeAdapt: o.isResizeAdapt,
 
             isNeedFreeze: false,
 
diff --git a/dist/widget.js b/dist/widget.js
index 75b27e101c..0b4b685469 100644
--- a/dist/widget.js
+++ b/dist/widget.js
@@ -6157,7 +6157,7 @@ BI.ExcelTable = BI.inherit(BI.Widget, {
         return BI.extend(BI.ExcelTable.superclass._defaultConfig.apply(this, arguments), {
             baseCls: "bi-excel-table",
             el: {
-                type: "bi.adaptive_table"
+                type: "bi.responsive_table"
             },
 
             isNeedResize: false,
@@ -6191,8 +6191,6 @@ BI.ExcelTable = BI.inherit(BI.Widget, {
         this.table = BI.createWidget(o.el, {
             type: "bi.table_view",
             element: this,
-            isNeedResize: o.isNeedResize,
-            isResizeAdapt: o.isResizeAdapt,
 
             isNeedFreeze: false,
 
diff --git a/src/widget/exceltable/exceltable.js b/src/widget/exceltable/exceltable.js
index 6a4becdc23..91d034a31c 100644
--- a/src/widget/exceltable/exceltable.js
+++ b/src/widget/exceltable/exceltable.js
@@ -11,7 +11,7 @@ BI.ExcelTable = BI.inherit(BI.Widget, {
         return BI.extend(BI.ExcelTable.superclass._defaultConfig.apply(this, arguments), {
             baseCls: "bi-excel-table",
             el: {
-                type: "bi.adaptive_table"
+                type: "bi.responsive_table"
             },
 
             isNeedResize: false,
@@ -45,8 +45,6 @@ BI.ExcelTable = BI.inherit(BI.Widget, {
         this.table = BI.createWidget(o.el, {
             type: "bi.table_view",
             element: this,
-            isNeedResize: o.isNeedResize,
-            isResizeAdapt: o.isResizeAdapt,
 
             isNeedFreeze: false,
 

From 600a2a55fef271605576f473e4841ce2852ff157 Mon Sep 17 00:00:00 2001
From: guy <guy@finereport.com>
Date: Thu, 30 Mar 2017 20:28:17 +0800
Subject: [PATCH 16/19] add

---
 bi/base.css                               | 3 ---
 dist/base.css                             | 3 ---
 src/css/base/table/table.grid.quick.css   | 3 ---
 src/less/base/table/table.grid.quick.less | 4 ----
 4 files changed, 13 deletions(-)
 delete mode 100644 src/css/base/table/table.grid.quick.css
 delete mode 100644 src/less/base/table/table.grid.quick.less

diff --git a/bi/base.css b/bi/base.css
index 542cd75be5..d9a49fee4a 100644
--- a/bi/base.css
+++ b/bi/base.css
@@ -1197,9 +1197,6 @@ li.CodeMirror-hint-active {
 .bi-grid-table-cell.first-col {
   border-left: 1px solid #eaeaea;
 }
-/****添加计算宽度的--运算符直接需要space****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
 .scrollbar-layout-main {
   box-sizing: border-box;
   outline: none;
diff --git a/dist/base.css b/dist/base.css
index 542cd75be5..d9a49fee4a 100644
--- a/dist/base.css
+++ b/dist/base.css
@@ -1197,9 +1197,6 @@ li.CodeMirror-hint-active {
 .bi-grid-table-cell.first-col {
   border-left: 1px solid #eaeaea;
 }
-/****添加计算宽度的--运算符直接需要space****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
 .scrollbar-layout-main {
   box-sizing: border-box;
   outline: none;
diff --git a/src/css/base/table/table.grid.quick.css b/src/css/base/table/table.grid.quick.css
deleted file mode 100644
index 2f6491e13f..0000000000
--- a/src/css/base/table/table.grid.quick.css
+++ /dev/null
@@ -1,3 +0,0 @@
-/****添加计算宽度的--运算符直接需要space****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
diff --git a/src/less/base/table/table.grid.quick.less b/src/less/base/table/table.grid.quick.less
deleted file mode 100644
index a5355da479..0000000000
--- a/src/less/base/table/table.grid.quick.less
+++ /dev/null
@@ -1,4 +0,0 @@
-@import "../../bibase";
-
-.bi-quick-grid-table {
-}
\ No newline at end of file

From 8f0e527980cc632103189f7dc49a675e3eb683dc Mon Sep 17 00:00:00 2001
From: guy <guy@finereport.com>
Date: Fri, 31 Mar 2017 10:55:12 +0800
Subject: [PATCH 17/19] add

---
 bi/core.js                                 | 50 ++++++++++++----------
 dist/core.js                               | 50 ++++++++++++----------
 src/core/controller/controller.floatbox.js | 50 ++++++++++++----------
 3 files changed, 81 insertions(+), 69 deletions(-)

diff --git a/bi/core.js b/bi/core.js
index 5e5a78631c..05d821f9b1 100644
--- a/bi/core.js
+++ b/bi/core.js
@@ -15684,28 +15684,30 @@ BI.FloatBoxController = BI.inherit(BI.Controller, {
         if (!this._check(name)) {
             return this;
         }
-        var container = this.floatContainer[name];
-        container.element.css("zIndex", this.zindex++);
-        this.modal && container.element.__hasZIndexMask__(this.zindexMap[name]) && container.element.__releaseZIndexMask__(this.zindexMap[name]);
-        this.zindexMap[name] = this.zindex;
-        this.modal && container.element.__buildZIndexMask__(this.zindex++);
-        this.get(name).setZindex(this.zindex++);
-        this.floatContainer[name].visible();
-        var floatbox = this.get(name);
-        floatbox.show();
-        var W = $(this.options.render).width(), H = $(this.options.render).height();
-        var w = floatbox.element.width(), h = floatbox.element.height();
-        var left = (W - w) / 2, top = (H - h) / 2;
-        if (left < 0) {
-            left = 0;
-        }
-        if (top < 0) {
-            top = 0;
+        if (!this.floatContainer[name].isVisible()) {
+            var container = this.floatContainer[name];
+            container.element.css("zIndex", this.zindex++);
+            this.modal && container.element.__hasZIndexMask__(this.zindexMap[name]) && container.element.__releaseZIndexMask__(this.zindexMap[name]);
+            this.zindexMap[name] = this.zindex;
+            this.modal && container.element.__buildZIndexMask__(this.zindex++);
+            this.get(name).setZindex(this.zindex++);
+            this.floatContainer[name].visible();
+            var floatbox = this.get(name);
+            floatbox.show();
+            var W = $(this.options.render).width(), H = $(this.options.render).height();
+            var w = floatbox.element.width(), h = floatbox.element.height();
+            var left = (W - w) / 2, top = (H - h) / 2;
+            if (left < 0) {
+                left = 0;
+            }
+            if (top < 0) {
+                top = 0;
+            }
+            floatbox.element.css({
+                left: left + "px",
+                top: top + "px"
+            });
         }
-        floatbox.element.css({
-            left: left + "px",
-            top: top + "px"
-        });
         return this;
     },
 
@@ -15713,8 +15715,10 @@ BI.FloatBoxController = BI.inherit(BI.Controller, {
         if (!this._check(name)) {
             return this;
         }
-        this.floatContainer[name].invisible();
-        this.modal && this.floatContainer[name].element.__releaseZIndexMask__(this.zindexMap[name]);
+        if (this.floatContainer[name].isVisible()) {
+            this.floatContainer[name].invisible();
+            this.modal && this.floatContainer[name].element.__releaseZIndexMask__(this.zindexMap[name]);
+        }
         return this;
     },
 
diff --git a/dist/core.js b/dist/core.js
index 34490f02e5..ee87da9609 100644
--- a/dist/core.js
+++ b/dist/core.js
@@ -20757,28 +20757,30 @@ BI.FloatBoxController = BI.inherit(BI.Controller, {
         if (!this._check(name)) {
             return this;
         }
-        var container = this.floatContainer[name];
-        container.element.css("zIndex", this.zindex++);
-        this.modal && container.element.__hasZIndexMask__(this.zindexMap[name]) && container.element.__releaseZIndexMask__(this.zindexMap[name]);
-        this.zindexMap[name] = this.zindex;
-        this.modal && container.element.__buildZIndexMask__(this.zindex++);
-        this.get(name).setZindex(this.zindex++);
-        this.floatContainer[name].visible();
-        var floatbox = this.get(name);
-        floatbox.show();
-        var W = $(this.options.render).width(), H = $(this.options.render).height();
-        var w = floatbox.element.width(), h = floatbox.element.height();
-        var left = (W - w) / 2, top = (H - h) / 2;
-        if (left < 0) {
-            left = 0;
-        }
-        if (top < 0) {
-            top = 0;
+        if (!this.floatContainer[name].isVisible()) {
+            var container = this.floatContainer[name];
+            container.element.css("zIndex", this.zindex++);
+            this.modal && container.element.__hasZIndexMask__(this.zindexMap[name]) && container.element.__releaseZIndexMask__(this.zindexMap[name]);
+            this.zindexMap[name] = this.zindex;
+            this.modal && container.element.__buildZIndexMask__(this.zindex++);
+            this.get(name).setZindex(this.zindex++);
+            this.floatContainer[name].visible();
+            var floatbox = this.get(name);
+            floatbox.show();
+            var W = $(this.options.render).width(), H = $(this.options.render).height();
+            var w = floatbox.element.width(), h = floatbox.element.height();
+            var left = (W - w) / 2, top = (H - h) / 2;
+            if (left < 0) {
+                left = 0;
+            }
+            if (top < 0) {
+                top = 0;
+            }
+            floatbox.element.css({
+                left: left + "px",
+                top: top + "px"
+            });
         }
-        floatbox.element.css({
-            left: left + "px",
-            top: top + "px"
-        });
         return this;
     },
 
@@ -20786,8 +20788,10 @@ BI.FloatBoxController = BI.inherit(BI.Controller, {
         if (!this._check(name)) {
             return this;
         }
-        this.floatContainer[name].invisible();
-        this.modal && this.floatContainer[name].element.__releaseZIndexMask__(this.zindexMap[name]);
+        if (this.floatContainer[name].isVisible()) {
+            this.floatContainer[name].invisible();
+            this.modal && this.floatContainer[name].element.__releaseZIndexMask__(this.zindexMap[name]);
+        }
         return this;
     },
 
diff --git a/src/core/controller/controller.floatbox.js b/src/core/controller/controller.floatbox.js
index 3179694817..b06e9723b0 100644
--- a/src/core/controller/controller.floatbox.js
+++ b/src/core/controller/controller.floatbox.js
@@ -82,28 +82,30 @@ BI.FloatBoxController = BI.inherit(BI.Controller, {
         if (!this._check(name)) {
             return this;
         }
-        var container = this.floatContainer[name];
-        container.element.css("zIndex", this.zindex++);
-        this.modal && container.element.__hasZIndexMask__(this.zindexMap[name]) && container.element.__releaseZIndexMask__(this.zindexMap[name]);
-        this.zindexMap[name] = this.zindex;
-        this.modal && container.element.__buildZIndexMask__(this.zindex++);
-        this.get(name).setZindex(this.zindex++);
-        this.floatContainer[name].visible();
-        var floatbox = this.get(name);
-        floatbox.show();
-        var W = $(this.options.render).width(), H = $(this.options.render).height();
-        var w = floatbox.element.width(), h = floatbox.element.height();
-        var left = (W - w) / 2, top = (H - h) / 2;
-        if (left < 0) {
-            left = 0;
+        if (!this.floatContainer[name].isVisible()) {
+            var container = this.floatContainer[name];
+            container.element.css("zIndex", this.zindex++);
+            this.modal && container.element.__hasZIndexMask__(this.zindexMap[name]) && container.element.__releaseZIndexMask__(this.zindexMap[name]);
+            this.zindexMap[name] = this.zindex;
+            this.modal && container.element.__buildZIndexMask__(this.zindex++);
+            this.get(name).setZindex(this.zindex++);
+            this.floatContainer[name].visible();
+            var floatbox = this.get(name);
+            floatbox.show();
+            var W = $(this.options.render).width(), H = $(this.options.render).height();
+            var w = floatbox.element.width(), h = floatbox.element.height();
+            var left = (W - w) / 2, top = (H - h) / 2;
+            if (left < 0) {
+                left = 0;
+            }
+            if (top < 0) {
+                top = 0;
+            }
+            floatbox.element.css({
+                left: left + "px",
+                top: top + "px"
+            });
         }
-        if (top < 0) {
-            top = 0;
-        }
-        floatbox.element.css({
-            left: left + "px",
-            top: top + "px"
-        });
         return this;
     },
 
@@ -111,8 +113,10 @@ BI.FloatBoxController = BI.inherit(BI.Controller, {
         if (!this._check(name)) {
             return this;
         }
-        this.floatContainer[name].invisible();
-        this.modal && this.floatContainer[name].element.__releaseZIndexMask__(this.zindexMap[name]);
+        if (this.floatContainer[name].isVisible()) {
+            this.floatContainer[name].invisible();
+            this.modal && this.floatContainer[name].element.__releaseZIndexMask__(this.zindexMap[name]);
+        }
         return this;
     },
 

From 8f9c70f5428141526fc3b2f4eaf4d38b6d76e70e Mon Sep 17 00:00:00 2001
From: guy <guy@finereport.com>
Date: Fri, 31 Mar 2017 12:59:45 +0800
Subject: [PATCH 18/19] add

---
 bi/core.js                                  | 14 ++++++++++----
 dist/core.js                                | 14 ++++++++++----
 src/core/alias.js                           |  4 ++--
 src/core/controller/controller.broadcast.js |  5 ++++-
 src/core/controller/controller.resizer.js   |  5 ++++-
 5 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/bi/core.js b/bi/core.js
index 05d821f9b1..e47cc4482b 100644
--- a/bi/core.js
+++ b/bi/core.js
@@ -3198,9 +3198,9 @@ if (!window.BI) {
         var numMod = format.indexOf(';');
         if (numMod > -1) {
             if (text >= 0) {
-                return BI._numberFormat(text + "", format.substring(0, numMod));
+                return _numberFormat(text + "", format.substring(0, numMod));
             } else {
-                return BI._numberFormat((-text) + "", format.substr(numMod + 1));
+                return _numberFormat((-text) + "", format.substr(numMod + 1));
             }
         }
         var tp = text.split('.'), fp = format.split('.'),
@@ -15368,7 +15368,7 @@ BI.BroadcastController = BI.inherit(BI.Controller, {
         }
         this._broadcasts[name].push(fn);
         return function () {
-            self._broadcasts[name].remove(fn);
+            self.remove(name, fn);
         }
     },
 
@@ -15382,6 +15382,9 @@ BI.BroadcastController = BI.inherit(BI.Controller, {
     remove: function (name, fn) {
         if (fn) {
             this._broadcasts[name].remove(fn);
+            if (this._broadcasts[name].length === 0) {
+                delete this._broadcasts[name];
+            }
         } else {
             delete this._broadcasts[name];
         }
@@ -15968,11 +15971,14 @@ BI.ResizeController = BI.inherit(BI.Controller, {
     },
 
     add: function (name, resizer) {
+        var self = this;
         if (this.has(name)) {
             return this;
         }
         this.resizerManger[name] = resizer;
-        return this;
+        return function () {
+            self.remove(name);
+        };
     },
 
     get: function (name) {
diff --git a/dist/core.js b/dist/core.js
index ee87da9609..9c8a9f4bfe 100644
--- a/dist/core.js
+++ b/dist/core.js
@@ -19876,9 +19876,9 @@ BI.PopoverSection.EVENT_CLOSE = "EVENT_CLOSE";;(function () {
         var numMod = format.indexOf(';');
         if (numMod > -1) {
             if (text >= 0) {
-                return BI._numberFormat(text + "", format.substring(0, numMod));
+                return _numberFormat(text + "", format.substring(0, numMod));
             } else {
-                return BI._numberFormat((-text) + "", format.substr(numMod + 1));
+                return _numberFormat((-text) + "", format.substr(numMod + 1));
             }
         }
         var tp = text.split('.'), fp = format.split('.'),
@@ -20441,7 +20441,7 @@ BI.BroadcastController = BI.inherit(BI.Controller, {
         }
         this._broadcasts[name].push(fn);
         return function () {
-            self._broadcasts[name].remove(fn);
+            self.remove(name, fn);
         }
     },
 
@@ -20455,6 +20455,9 @@ BI.BroadcastController = BI.inherit(BI.Controller, {
     remove: function (name, fn) {
         if (fn) {
             this._broadcasts[name].remove(fn);
+            if (this._broadcasts[name].length === 0) {
+                delete this._broadcasts[name];
+            }
         } else {
             delete this._broadcasts[name];
         }
@@ -21041,11 +21044,14 @@ BI.ResizeController = BI.inherit(BI.Controller, {
     },
 
     add: function (name, resizer) {
+        var self = this;
         if (this.has(name)) {
             return this;
         }
         this.resizerManger[name] = resizer;
-        return this;
+        return function () {
+            self.remove(name);
+        };
     },
 
     get: function (name) {
diff --git a/src/core/alias.js b/src/core/alias.js
index d86d76af8b..0abe30e403 100644
--- a/src/core/alias.js
+++ b/src/core/alias.js
@@ -186,9 +186,9 @@
         var numMod = format.indexOf(';');
         if (numMod > -1) {
             if (text >= 0) {
-                return BI._numberFormat(text + "", format.substring(0, numMod));
+                return _numberFormat(text + "", format.substring(0, numMod));
             } else {
-                return BI._numberFormat((-text) + "", format.substr(numMod + 1));
+                return _numberFormat((-text) + "", format.substr(numMod + 1));
             }
         }
         var tp = text.split('.'), fp = format.split('.'),
diff --git a/src/core/controller/controller.broadcast.js b/src/core/controller/controller.broadcast.js
index 7b7c43984f..202f2432e5 100644
--- a/src/core/controller/controller.broadcast.js
+++ b/src/core/controller/controller.broadcast.js
@@ -21,7 +21,7 @@ BI.BroadcastController = BI.inherit(BI.Controller, {
         }
         this._broadcasts[name].push(fn);
         return function () {
-            self._broadcasts[name].remove(fn);
+            self.remove(name, fn);
         }
     },
 
@@ -35,6 +35,9 @@ BI.BroadcastController = BI.inherit(BI.Controller, {
     remove: function (name, fn) {
         if (fn) {
             this._broadcasts[name].remove(fn);
+            if (this._broadcasts[name].length === 0) {
+                delete this._broadcasts[name];
+            }
         } else {
             delete this._broadcasts[name];
         }
diff --git a/src/core/controller/controller.resizer.js b/src/core/controller/controller.resizer.js
index 04ad57869b..d45b13bc9c 100644
--- a/src/core/controller/controller.resizer.js
+++ b/src/core/controller/controller.resizer.js
@@ -41,11 +41,14 @@ BI.ResizeController = BI.inherit(BI.Controller, {
     },
 
     add: function (name, resizer) {
+        var self = this;
         if (this.has(name)) {
             return this;
         }
         this.resizerManger[name] = resizer;
-        return this;
+        return function () {
+            self.remove(name);
+        };
     },
 
     get: function (name) {

From 10c8300f34008693321eba812fa074f2fa1f3243 Mon Sep 17 00:00:00 2001
From: guy <guy@finereport.com>
Date: Fri, 31 Mar 2017 14:25:50 +0800
Subject: [PATCH 19/19] add

---
 bi/case.js                        | 2 +-
 bi/widget.js                      | 2 +-
 dist/case.js                      | 2 +-
 dist/widget.js                    | 2 +-
 src/case/pager/pager.all.count.js | 2 +-
 src/widget/year/trigger.year.js   | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/bi/case.js b/bi/case.js
index e4215d7248..af310f6c84 100644
--- a/bi/case.js
+++ b/bi/case.js
@@ -8520,7 +8520,7 @@ BI.AllCountPager = BI.inherit(BI.Widget, {
             hgap: 4,
             vgap: 0,
             value: o.curr,
-            errorText: BI.i18nText("BI-Please_Input_Integer"),
+            errorText: BI.i18nText("BI-Please_Input_Positive_Integer"),
             width: 30,
             height: 20
         });
diff --git a/bi/widget.js b/bi/widget.js
index 0b4b685469..b375c5c3a6 100644
--- a/bi/widget.js
+++ b/bi/widget.js
@@ -16788,7 +16788,7 @@ BI.YearTrigger = BI.inherit(BI.Trigger, {
         hgap: 4,
         vgap: 2,
         triggerWidth: 25,
-        errorText: BI.i18nText("BI-Please_Input_Integer"),
+        errorText: BI.i18nText("BI-Please_Input_Positive_Integer"),
         errorTextInvalid: BI.i18nText("BI-Year_Trigger_Invalid_Text")
     },
 
diff --git a/dist/case.js b/dist/case.js
index e4215d7248..af310f6c84 100644
--- a/dist/case.js
+++ b/dist/case.js
@@ -8520,7 +8520,7 @@ BI.AllCountPager = BI.inherit(BI.Widget, {
             hgap: 4,
             vgap: 0,
             value: o.curr,
-            errorText: BI.i18nText("BI-Please_Input_Integer"),
+            errorText: BI.i18nText("BI-Please_Input_Positive_Integer"),
             width: 30,
             height: 20
         });
diff --git a/dist/widget.js b/dist/widget.js
index 0b4b685469..b375c5c3a6 100644
--- a/dist/widget.js
+++ b/dist/widget.js
@@ -16788,7 +16788,7 @@ BI.YearTrigger = BI.inherit(BI.Trigger, {
         hgap: 4,
         vgap: 2,
         triggerWidth: 25,
-        errorText: BI.i18nText("BI-Please_Input_Integer"),
+        errorText: BI.i18nText("BI-Please_Input_Positive_Integer"),
         errorTextInvalid: BI.i18nText("BI-Year_Trigger_Invalid_Text")
     },
 
diff --git a/src/case/pager/pager.all.count.js b/src/case/pager/pager.all.count.js
index 42ab6eaca6..f15903fecb 100644
--- a/src/case/pager/pager.all.count.js
+++ b/src/case/pager/pager.all.count.js
@@ -25,7 +25,7 @@ BI.AllCountPager = BI.inherit(BI.Widget, {
             hgap: 4,
             vgap: 0,
             value: o.curr,
-            errorText: BI.i18nText("BI-Please_Input_Integer"),
+            errorText: BI.i18nText("BI-Please_Input_Positive_Integer"),
             width: 30,
             height: 20
         });
diff --git a/src/widget/year/trigger.year.js b/src/widget/year/trigger.year.js
index 093dcfdde4..f87b1614a2 100644
--- a/src/widget/year/trigger.year.js
+++ b/src/widget/year/trigger.year.js
@@ -10,7 +10,7 @@ BI.YearTrigger = BI.inherit(BI.Trigger, {
         hgap: 4,
         vgap: 2,
         triggerWidth: 25,
-        errorText: BI.i18nText("BI-Please_Input_Integer"),
+        errorText: BI.i18nText("BI-Please_Input_Positive_Integer"),
         errorTextInvalid: BI.i18nText("BI-Year_Trigger_Invalid_Text")
     },