").width(50).height(50).css({
+ position: "absolute",
+ top: "-9999px",
+ overflow: "scroll"
+ }).appendTo($("body"));
+ this._scrollWidth = ul[0].offsetWidth - ul[0].clientWidth;
+ ul.destroy();
+ }
+ return this._scrollWidth;
+ }
+});/**
+ * guy
+ * 检测某个Widget的EventChange事件然后去show某个card
+ * @type {*|void|Object}
+ * @class BI.ShowListener
+ * @extends BI.OB
+ */
+BI.ShowListener = BI.inherit(BI.OB, {
+ _defaultConfig: function () {
+ return BI.extend(BI.ShowListener.superclass._defaultConfig.apply(this, arguments), {
+ eventObj: BI.createWidget(),
+ cardLayout: null,
+ cardNameCreator: function (v) {
+ return v;
+ },
+ cardCreator: BI.emptyFn,
+ afterCardCreated: BI.emptyFn,
+ afterCardShow: BI.emptyFn
+ });
+ },
+
+ _init: function () {
+ BI.ShowListener.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ o.eventObj.on(BI.Controller.EVENT_CHANGE, function (type, v, ob) {
+ if (type === BI.Events.CLICK) {
+ v = v || o.eventObj.getValue();
+ v = BI.isArray(v) ? (v.length > 1 ? v.toString() : v[0]) : v;
+ if (BI.isNull(v)) {
+ throw new Error("value cannot be null");
+ }
+ var cardName = o.cardNameCreator(v);
+ if (!o.cardLayout.isCardExisted(cardName)) {
+ var card = o.cardCreator(cardName);
+ o.cardLayout.addCardByName(cardName, card);
+ o.afterCardCreated(cardName);
+ }
+ o.cardLayout.showCardByName(cardName);
+ BI.nextTick(function () {
+ o.afterCardShow(cardName);
+ self.fireEvent(BI.ShowListener.EVENT_CHANGE, cardName);
+ });
+ }
+ })
+ }
+});
+BI.ShowListener.EVENT_CHANGE = "ShowListener.EVENT_CHANGE";/**
+ * style加载管理器
+ *
+ * Created by GUY on 2015/9/7.
+ * @class
+ */
+BI.StyleLoaderManager = BI.inherit(BI.OB, {
+ _defaultConfig: function () {
+ return BI.extend(BI.StyleLoaderManager.superclass._defaultConfig.apply(this, arguments), {});
+ },
+
+ _init: function () {
+ BI.StyleLoaderManager.superclass._init.apply(this, arguments);
+ this.stylesManager = {};
+ },
+
+ loadStyle: function (name, styleString) {
+ var d = document, styles = d.createElement('style');
+ d.getElementsByTagName('head')[0].appendChild(styles);
+ styles.setAttribute('type', 'text/css');
+ if (styles.styleSheet) {
+ styles.styleSheet.cssText = styleString;
+ } else {
+ styles.appendChild(document.createTextNode(styleString));
+ }
+ this.stylesManager[name] = styles;
+
+ return this;
+ },
+
+ get: function (name) {
+ return this.stylesManager[name];
+ },
+
+ has: function (name) {
+ return this.stylesManager[name] != null;
+ },
+
+ removeStyle: function (name) {
+ if (!this.has(name)) {
+ return this;
+ }
+ this.stylesManager[name].parentNode.removeChild(this.stylesManager[name]);
+ delete this.stylesManager[name];
+ return this;
+ }
+});/**
+ * @class BI.Logic
+ * @extends BI.OB
+ */
+BI.Logic = BI.inherit(BI.OB, {
+ createLogic: function () {
+ return this.options || {};
+ }
+});
+
+BI.LogicFactory = {
+ Type: {
+ Vertical: "vertical",
+ Horizontal: "horizontal",
+ Table: "table",
+ HorizontalFill: "horizontal_fill"
+ },
+ createLogic: function (key, options) {
+ var logic;
+ switch (key) {
+ case BI.LogicFactory.Type.Vertical:
+ logic = BI.VerticalLayoutLogic;
+ break;
+ case BI.LogicFactory.Type.Horizontal:
+ logic = BI.HorizontalLayoutLogic;
+ break;
+ case BI.LogicFactory.Type.Table:
+ logic = BI.TableLayoutLogic;
+ break;
+ case BI.LogicFactory.Type.HorizontalFill:
+ logic = BI.HorizontalFillLayoutLogic;
+ break;
+ default :
+ logic = BI.Logic;
+ break;
+ }
+ return new logic(options).createLogic();
+ },
+
+ createLogicTypeByDirection: function (direction) {
+ switch (direction) {
+ case BI.Direction.Top:
+ case BI.Direction.Bottom:
+ case BI.Direction.Custom:
+ return BI.LogicFactory.Type.Vertical;
+ break;
+ case BI.Direction.Left:
+ case BI.Direction.Right:
+ return BI.LogicFactory.Type.Horizontal;
+ }
+ },
+
+ createLogicItemsByDirection: function (direction) {
+ var layout;
+ var items = Array.prototype.slice.call(arguments, 1);
+ items = BI.map(items, function (i, item) {
+ if (BI.isWidget(item)) {
+ return {
+ el: item,
+ width: item.options.width,
+ height: item.options.height
+ }
+ }
+ return item;
+ });
+ switch (direction) {
+ case BI.Direction.Bottom:
+ layout = BI.LogicFactory.Type.Vertical;
+ items.reverse();
+ break;
+ case BI.Direction.Right:
+ layout = BI.LogicFactory.Type.Horizontal;
+ items.reverse();
+ break;
+ case BI.Direction.Custom:
+ items = items.slice(1);
+ break;
+ }
+ return items;
+ }
+};/**
+ * guy
+ * 上下布局逻辑
+ * 上下布局的时候要考虑到是动态布局还是静态布局
+ *
+ * @class BI.VerticalLayoutLogic
+ * @extends BI.Logic
+ */
+BI.VerticalLayoutLogic = BI.inherit(BI.Logic, {
+ _defaultConfig: function () {
+ return BI.extend(BI.VerticalLayoutLogic.superclass._defaultConfig.apply(this, arguments), {
+ dynamic: false,
+ scrollable: null,
+ scrolly: false,
+ scrollx: false,
+ items: [],
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+
+ createLogic: function () {
+ var layout, o = this.options;
+ if (o.dynamic) {
+ layout = "bi.vertical";
+ } else {
+ layout = "bi.vtape";
+ }
+ return {
+ type: layout,
+ scrollable: o.scrollable,
+ scrolly: o.scrolly,
+ scrollx: o.scrollx,
+ hgap: o.hgap,
+ vgap: o.vgap,
+ lgap: o.lgap,
+ rgap: o.rgap,
+ tgap: o.tgap,
+ bgap: o.bgap,
+ items: o.items
+ }
+ },
+
+ _init: function () {
+ BI.VerticalLayoutLogic.superclass._init.apply(this, arguments);
+ }
+});
+
+
+/**
+ * guy
+ * 左右布局逻辑
+ * 左右布局的时候要考虑到是动态布局还是静态布局
+ *
+ * @class BI.HorizontalLayoutLogic
+ * @extends BI.Logic
+ */
+BI.HorizontalLayoutLogic = BI.inherit(BI.Logic, {
+ _defaultConfig: function () {
+ return BI.extend(BI.HorizontalLayoutLogic.superclass._defaultConfig.apply(this, arguments), {
+ dynamic: false,
+ scrollable: null,
+ scrolly: false,
+ scrollx: false,
+ items: [],
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+
+ createLogic: function () {
+ var layout, o = this.options;
+ if (o.dynamic) {
+ layout = "bi.horizontal";
+ } else {
+ layout = "bi.htape";
+ }
+ return {
+ type: layout,
+ scrollable: o.scrollable,
+ scrolly: o.scrolly,
+ scrollx: o.scrollx,
+ hgap: o.hgap,
+ vgap: o.vgap,
+ lgap: o.lgap,
+ rgap: o.rgap,
+ tgap: o.tgap,
+ bgap: o.bgap,
+ items: o.items
+ }
+ },
+
+ _init: function () {
+ BI.HorizontalLayoutLogic.superclass._init.apply(this, arguments);
+ }
+});
+
+/**
+ * guy
+ * 表格布局逻辑
+ * 表格布局的时候要考虑到是动态布局还是静态布局
+ *
+ * @class BI.TableLayoutLogic
+ * @extends BI.OB
+ */
+BI.TableLayoutLogic = BI.inherit(BI.Logic, {
+ _defaultConfig: function () {
+ return BI.extend(BI.TableLayoutLogic.superclass._defaultConfig.apply(this, arguments), {
+ dynamic: false,
+ scrollable: null,
+ scrolly: false,
+ scrollx: false,
+ columns: 0,
+ rows: 0,
+ columnSize: [],
+ rowSize: [],
+ hgap: 0,
+ vgap: 0,
+ items: []
+ });
+ },
+
+ createLogic: function () {
+ var layout, o = this.options;
+ if (o.dynamic) {
+ layout = "bi.table";
+ } else {
+ layout = "bi.window";
+ }
+ return {
+ type: layout,
+ scrollable: o.scrollable,
+ scrolly: o.scrolly,
+ scrollx: o.scrollx,
+ columns: o.columns,
+ rows: o.rows,
+ columnSize: o.columnSize,
+ rowSize: o.rowSize,
+ hgap: o.hgap,
+ vgap: o.vgap,
+ items: o.items
+ }
+ },
+
+ _init: function () {
+ BI.TableLayoutLogic.superclass._init.apply(this, arguments);
+ }
+});
+
+/**
+ * guy
+ * 左右充满布局逻辑
+ *
+ * @class BI.HorizontalFillLayoutLogic
+ * @extends BI.Logic
+ */
+BI.HorizontalFillLayoutLogic = BI.inherit(BI.Logic, {
+ _defaultConfig: function () {
+ return BI.extend(BI.HorizontalFillLayoutLogic.superclass._defaultConfig.apply(this, arguments), {
+ dynamic: false,
+ scrollable: null,
+ scrolly: false,
+ scrollx: false,
+ items: [],
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+
+ createLogic: function () {
+ var layout, o = this.options;
+ var columnSize = [];
+ BI.each(o.items, function (i, item) {
+ columnSize.push(item.width || 0);
+ });
+ if (o.dynamic) {
+ layout = "bi.horizontal_adapt";
+ } else {
+ layout = "bi.htape";
+ }
+ return {
+ type: layout,
+ columnSize: columnSize,
+ scrollable: o.scrollable,
+ scrolly: o.scrolly,
+ scrollx: o.scrollx,
+ hgap: o.hgap,
+ vgap: o.vgap,
+ lgap: o.lgap,
+ rgap: o.rgap,
+ tgap: o.tgap,
+ bgap: o.bgap,
+ items: o.items
+ }
+ },
+
+ _init: function () {
+ BI.HorizontalFillLayoutLogic.superclass._init.apply(this, arguments);
+ }
+});/**
+ * 保存数据,将js里面用到的常量数据都分离
+ *
+ */
+BI.Data = Data = {};
+
+/**
+ * 存放bi里面通用的一些常量
+ * @type {{}}
+ */
+Data.Constant = BI.Constant = BICst = {};
+/**
+ * 缓冲池
+ * @type {{Buffer: {}}}
+ */
+;
+(function () {
+ var Buffer = {};
+ var MODE = false;//设置缓存模式为关闭
+
+ Data.BufferPool = {
+ put: function (name, cache) {
+ if (BI.isNotNull(Buffer[name])) {
+ throw new Error("Buffer Pool has the key already!");
+ }
+ Buffer[name] = cache;
+ },
+
+ get: function (name) {
+ return Buffer[name];
+ },
+ };
+})();/**
+ * 共享池
+ * @type {{Shared: {}}}
+ */
+;
+(function () {
+ var _Shared = {};
+ Data.SharingPool = {
+ _Shared: _Shared,
+ put: function (name, shared) {
+ _Shared[name] = shared;
+ },
+
+ cat: function () {
+ var args = Array.prototype.slice.call(arguments, 0),
+ copy = _Shared;
+ for (var i = 0; i < args.length; i++) {
+ copy = copy[args[i]];
+ }
+ return copy;
+ },
+
+ get: function () {
+ return BI.deepClone(this.cat.apply(this, arguments));
+ },
+
+ remove: function (key) {
+ delete _Shared[key];
+ }
+ };
+})();Data.Req = {
+
+};
+Data.Source = BISource = {
+
+};//工程配置
+$(function () {
+ //注册布局
+ var isSupportFlex = BI.isSupportCss3("flex");
+ BI.Plugin.registerWidget("bi.horizontal", function (ob) {
+ if (isSupportFlex) {
+ return BI.extend(ob, {type: "bi.flex_horizontal"});
+ } else {
+ return ob;
+ }
+ });
+ BI.Plugin.registerWidget("bi.center_adapt", function (ob) {
+ if (isSupportFlex && ob.items && ob.items.length <= 1) {
+ //有滚动条的情况下需要用到flex_wrapper_center布局
+ if (ob.scrollable === true || ob.scrollx === true || ob.scrolly === true) {
+ //不是IE用flex_wrapper_center布局
+ if (!BI.isIE()) {
+ return BI.extend(ob, {type: "bi.flex_wrapper_center"});
+ }
+ return ob;
+ }
+ return BI.extend(ob, {type: "bi.flex_center"});
+ } else {
+ return ob;
+ }
+ });
+ BI.Plugin.registerWidget("bi.vertical_adapt", function (ob) {
+ if (isSupportFlex) {
+ //有滚动条的情况下需要用到flex_wrapper_center布局
+ if (ob.scrollable === true || ob.scrollx === true || ob.scrolly === true) {
+ //不是IE用flex_wrapper_center布局
+ if (!BI.isIE()) {
+ return BI.extend({}, ob, {type: "bi.flex_wrapper_vertical_center"});
+ }
+ return ob;
+ }
+ return BI.extend(ob, {type: "bi.flex_vertical_center"});
+ } else {
+ return ob;
+ }
+ });
+ BI.Plugin.registerWidget("bi.float_center_adapt", function (ob) {
+ if (isSupportFlex) {
+ //有滚动条的情况下需要用到flex_wrapper_center布局
+ if (ob.scrollable === true || ob.scrollx === true || ob.scrolly === true) {
+ //不是IE用flex_wrapper_center布局
+ if (!BI.isIE()) {
+ return BI.extend({}, ob, {type: "bi.flex_wrapper_center"});
+ }
+ return ob;
+ }
+ return BI.extend(ob, {type: "bi.flex_center"});
+ } else {
+ return ob;
+ }
+ });
+ //注册滚动条
+ BI.Plugin.registerWidget("bi.grid_table_scrollbar", function (ob) {
+ if (BI.isIE9Below()) {
+ return BI.extend(ob, {type: "bi.native_table_scrollbar"});
+ } else {
+ return ob;
+ }
+ });
+ BI.Plugin.registerWidget("bi.grid_table_horizontal_scrollbar", function (ob) {
+ if (BI.isIE9Below()) {
+ return BI.extend(ob, {type: "bi.native_table_horizontal_scrollbar"});
+ } else {
+ return ob;
+ }
+ });
+
+ //注册控件
+ BI.Plugin.registerWidget("bi.grid_table", function (ob) {
+ //非chrome下滚动条滑动效果不好,禁止掉
+ if (!(BI.isChrome() && BI.isWindows() && !BI.isEdge())) {
+ return BI.extend(ob, {type: "bi.quick_grid_table"});
+ } else {
+ return ob;
+ }
+ });
+ BI.Plugin.registerWidget("bi.collection_table", function (ob) {
+ //非chrome下滚动条滑动效果不好,禁止掉
+ if (!(BI.isChrome() && BI.isWindows() && !BI.isEdge())) {
+ return BI.extend(ob, {type: "bi.quick_collection_table"});
+ } else {
+ return ob;
+ }
+ });
+ //IE8下滚动条用原生的
+ if (BI.isIE9Below()) {
+ BI.GridTableScrollbar.SIZE = 18;
+ }
});
\ No newline at end of file
diff --git a/bi/widget.css b/bi/widget.css
index d07adc5bf..0d58f4cd4 100644
--- a/bi/widget.css
+++ b/bi/widget.css
@@ -1,416 +1,416 @@
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-arrangement .arrangement-helper {
- background: #3f8ce8;
- z-index: 1000000000;
-}
-.bi-arrangement .arrangement-block {
- z-index: 1000000000;
-}
-.bi-arrangement .arrangement-drop-container {
- z-index: 1000000000;
-}
-.bi-arrangement .arrangement-drop-container .arrangement-drop-region {
- overflow: hidden;
-}
-.bi-arrangement .arrangement-drop-container .drop-devider {
- z-index: 1000000001;
- background: #3f8ce8;
-}
-.bi-arrangement .arrangement-drop-container .top-left,
-.bi-arrangement .arrangement-drop-container .top-right,
-.bi-arrangement .arrangement-drop-container .bottom-left,
-.bi-arrangement .arrangement-drop-container .bottom-right,
-.bi-arrangement .arrangement-drop-container .top-left-second,
-.bi-arrangement .arrangement-drop-container .top-right-second,
-.bi-arrangement .arrangement-drop-container .bottom-left-second,
-.bi-arrangement .arrangement-drop-container .bottom-right-second,
-.bi-arrangement .arrangement-drop-container .top-center,
-.bi-arrangement .arrangement-drop-container .bottom-center,
-.bi-arrangement .arrangement-drop-container .left-center,
-.bi-arrangement .arrangement-drop-container .right-center,
-.bi-arrangement .arrangement-drop-container .top-center-second,
-.bi-arrangement .arrangement-drop-container .bottom-center-second,
-.bi-arrangement .arrangement-drop-container .left-center-second,
-.bi-arrangement .arrangement-drop-container .right-center-second {
- z-index: 1000000001;
- background: #3f8ce8;
-}
-.bi-arrangement-droppable {
- z-index: 100000;
-}
-/****添加计算宽度的--运算符直接需要space****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-adapt-editor .adapt-editor-text {
- font-size: 14px;
-}
-/****添加计算宽度的--运算符直接需要space****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-/*************BI.SearchEditor******************/
-.bi-search-editor {
- border: 1px solid #d4dadd;
-}
-.bi-search-editor .close-font {
- font-size: 20px;
-}
-.bi-search-editor .search-font {
- font-size: 20px;
-}
-/****添加计算宽度的--运算符直接需要space****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-/*************BI.SearchEditor******************/
-.bi-small-search-editor .bi-editor {
- font-size: 12px;
-}
-.bi-small-search-editor .bi-editor .bi-input {
- font-size: 12px;
-}
-.bi-small-search-editor .bi-editor .bi-label {
- font-size: 12px;
-}
-.bi-small-search-editor .close-font {
- font-size: 18px;
-}
-.bi-small-search-editor .search-font {
- font-size: 18px;
-}
-/****添加计算宽度的--运算符直接需要space****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-sign-initial-editor .sign-initial-editor-text {
- font-size: 14px;
-}
-/****添加计算宽度的--运算符直接需要space****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-sign-style-editor .sign-style-editor-text {
- max-width: 100%;
- font-size: 12px;
-}
-.bi-sign-style-editor .sign-style-editor-tip {
- max-width: 100%;
- font-size: 12px;
- color: #808080;
-}
-/****添加计算宽度的--运算符直接需要space****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-text-editor {
- border: 1px solid #d4dadd;
-}
-/****添加计算宽度的--运算符直接需要space****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-/*************BI.SearchEditor******************/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-date-trigger {
- -webkit-border-radius: 2px;
- -moz-border-radius: 2px;
- border-radius: 2px;
-}
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-down-list-popup .bi-down-list-item .list-item-text {
- max-width: 203px;
-}
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-excel-table > div.bottom-right > div > div > table {
- border-right: 1px solid #d4dadd;
-}
-.bi-theme-dark .bi-excel-table > div.bottom-right > div > div > table {
- border-right: 1px solid #525466;
-}
-.bi-excel-table-header-cell {
- font-weight: bold;
-}
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-file-manager-nav-button .file-manager-nav-button-text {
- max-width: 200px;
-}
-.bi-file-manager-nav-button .file-manager-nav-button-text.active {
- background-color: #eff1f4;
- color: #999999;
-}
-.bi-file-manager-nav-button .file-manager-nav-button-triangle {
- z-index: 1;
-}
-.bi-theme-dark .bi-file-manager-nav-button .file-manager-nav-button-text.active {
- background-color: #191b2b;
- color: #999999;
-}
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-fine-tuning-number-editor {
- -webkit-border-radius: 2px;
- -moz-border-radius: 2px;
- border-radius: 2px;
-}
-.bi-interactive-arrangement .interactive-arrangement-dragtag-line {
- z-index: 1000000000;
- background-color: #f07d0a;
-}
-.bi-interactive-arrangement .interactive-arrangement-dragtag-icon {
- z-index: 1000000000;
-}
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-month-trigger {
- -webkit-border-radius: 2px;
- -moz-border-radius: 2px;
- border-radius: 2px;
-}
-.bi-multi-select-check-pane .multi-select-check-selected {
- text-decoration: underline;
-}
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-multi-select-combo .multi-select-trigger-icon-button {
- font-size: 16px;
-}
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-multi-select-trigger {
- -webkit-border-radius: 2px 2px 2px 2px;
- -moz-border-radius: 2px 2px 2px 2px;
- border-radius: 2px 2px 2px 2px;
-}
-.bi-multi-select-search-pane .multi-select-toolbar {
- color: #e85050;
-}
-.bi-multi-select-check-selected-button {
- z-index: 1;
-}
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-multi-tree-check-pane .multi-tree-check-selected {
- color: #3f8ce8;
-}
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-multi-tree-combo .multi-select-trigger-icon-button {
- font-size: 16px;
-}
-.bi-multi-tree-popup .popup-view-tree {
- min-height: 170px;
-}
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-multi-tree-check-selected-button .trigger-check-selected {
- color: #3f8ce8;
- z-index: 1;
-}
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-numerical-interval .numerical-interval-small-editor {
- -moz-border-radius-topleft: 2px;
- -webkit-border-top-left-radius: 2px;
- -moz-border-radius-bottomleft: 2px;
- -webkit-border-bottom-left-radius: 2px;
- border-top-left-radius: 2px;
- border-bottom-left-radius: 2px;
-}
-.bi-numerical-interval .numerical-interval-big-editor {
- -moz-border-radius-topright: 2px;
- -webkit-border-top-right-radius: 2px;
- -moz-border-radius-bottomright: 2px;
- -webkit-border-bottom-right-radius: 2px;
- border-top-right-radius: 2px;
- border-bottom-right-radius: 2px;
-}
-.bi-numerical-interval .numerical-interval-big-combo {
- -moz-border-radius-topleft: 2px;
- -webkit-border-top-left-radius: 2px;
- -moz-border-radius-bottomleft: 2px;
- -webkit-border-bottom-left-radius: 2px;
- border-top-left-radius: 2px;
- border-bottom-left-radius: 2px;
-}
-.bi-numerical-interval .numerical-interval-big-combo .bi-icon-combo-trigger .icon-combo-trigger-icon {
- font-size: 14px;
-}
-.bi-numerical-interval .numerical-interval-small-combo {
- -moz-border-radius-topright: 2px;
- -webkit-border-top-right-radius: 2px;
- -moz-border-radius-bottomright: 2px;
- -webkit-border-bottom-right-radius: 2px;
- border-top-right-radius: 2px;
- border-bottom-right-radius: 2px;
-}
-.bi-numerical-interval .numerical-interval-small-combo .bi-icon-combo-trigger .icon-combo-trigger-icon {
- font-size: 14px;
-}
-.bi-numerical-interval.number-error .bi-input {
- color: #e85050;
-}
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-page-table-cell {
- -webkit-user-select: initial;
- -khtml-user-select: initial;
- -moz-user-select: initial;
- -ms-user-select: initial;
- -o-user-select: initial;
- user-select: initial;
-}
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-path-chooser .path-chooser-radio {
- z-index: 1;
-}
-.bi-path-region .path-region-label {
- z-index: 1;
-}
-.bi-preview-table-cell {
- min-height: 25px;
- min-width: 80px;
- max-width: 220px;
-}
-.bi-preview-table {
- -webkit-user-select: initial;
- -khtml-user-select: initial;
- -moz-user-select: initial;
- -ms-user-select: initial;
- -o-user-select: initial;
- user-select: initial;
-}
-.bi-preview-table > div > table > thead > tr.odd,
-.bi-preview-table > div > div > div > table > thead > tr.odd {
- background-color: #eff1f4;
-}
-.bi-theme-dark .bi-preview-table > div > table > thead > tr.odd,
-.bi-theme-dark .bi-preview-table > div > div > div > table > thead > tr.odd {
- background-color: #191b2b;
-}
-.bi-preview-table-header-cell {
- font-weight: bold;
- min-height: 25px;
- min-width: 80px;
- max-width: 220px;
-}
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-quarter-trigger {
- -webkit-border-radius: 2px;
- -moz-border-radius: 2px;
- border-radius: 2px;
-}
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-relation-view-region .relation-view-region-container {
- z-index: 1;
- -webkit-border-radius: 2px;
- -moz-border-radius: 2px;
- border-radius: 2px;
-}
-.bi-relation-view-region .relation-view-region-container.other-package {
- border-style: dashed;
-}
-.bi-sequence-table-dynamic-number .sequence-table-title-cell {
- overflow: hidden;
- overflow-x: hidden;
- overflow-y: hidden;
- -webkit-box-sizing: border-box;
- /*Safari3.2+*/
- -moz-box-sizing: border-box;
- /*Firefox3.5+*/
- -ms-box-sizing: border-box;
- /*IE8*/
- box-sizing: border-box;
- /*W3C标准(IE9+,Safari5.1+,Chrome10.0+,Opera10.6+都符合box-sizing的w3c标准语法)*/
-}
-.bi-sequence-table-dynamic-number .sequence-table-number-cell {
- -webkit-box-sizing: border-box;
- /*Safari3.2+*/
- -moz-box-sizing: border-box;
- /*Firefox3.5+*/
- -ms-box-sizing: border-box;
- /*IE8*/
- box-sizing: border-box;
- /*W3C标准(IE9+,Safari5.1+,Chrome10.0+,Opera10.6+都符合box-sizing的w3c标准语法)*/
-}
-.bi-sequence-table-list-number .sequence-table-title-cell {
- overflow: hidden;
- overflow-x: hidden;
- overflow-y: hidden;
- -webkit-box-sizing: border-box;
- /*Safari3.2+*/
- -moz-box-sizing: border-box;
- /*Firefox3.5+*/
- -ms-box-sizing: border-box;
- /*IE8*/
- box-sizing: border-box;
- /*W3C标准(IE9+,Safari5.1+,Chrome10.0+,Opera10.6+都符合box-sizing的w3c标准语法)*/
-}
-.bi-sequence-table-list-number .sequence-table-number-cell {
- -webkit-box-sizing: border-box;
- /*Safari3.2+*/
- -moz-box-sizing: border-box;
- /*Firefox3.5+*/
- -ms-box-sizing: border-box;
- /*IE8*/
- box-sizing: border-box;
- /*W3C标准(IE9+,Safari5.1+,Chrome10.0+,Opera10.6+都符合box-sizing的w3c标准语法)*/
-}
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-sequence-table-tree-number .sequence-table-title-cell {
- overflow: hidden;
- overflow-x: hidden;
- overflow-y: hidden;
- -webkit-box-sizing: border-box;
- /*Safari3.2+*/
- -moz-box-sizing: border-box;
- /*Firefox3.5+*/
- -ms-box-sizing: border-box;
- /*IE8*/
- box-sizing: border-box;
- /*W3C标准(IE9+,Safari5.1+,Chrome10.0+,Opera10.6+都符合box-sizing的w3c标准语法)*/
-}
-.bi-sequence-table-tree-number .sequence-table-number-cell {
- -webkit-box-sizing: border-box;
- /*Safari3.2+*/
- -moz-box-sizing: border-box;
- /*Firefox3.5+*/
- -ms-box-sizing: border-box;
- /*IE8*/
- box-sizing: border-box;
- /*W3C标准(IE9+,Safari5.1+,Chrome10.0+,Opera10.6+都符合box-sizing的w3c标准语法)*/
-}
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-/****** common color(常用颜色,可用于普遍场景) *****/
-/**** custom color(自定义颜色,用于特定场景) ****/
-.bi-year-popup .year-popup-navigation {
- line-height: 30px;
-}
-.bi-year-popup .year-popup-navigation > .center-element {
- border-left: 1px solid #d4dadd;
-}
-.bi-year-popup .year-popup-navigation > .first-element {
- border-left: none;
-}
-.bi-theme-dark .bi-year-popup .year-popup-navigation > .center-element {
- border-left: 1px solid #525466;
-}
-.bi-theme-dark .bi-year-popup .year-popup-navigation > .first-element {
- border-left: none;
-}
-.bi-year-trigger {
- -webkit-border-radius: 2px;
- -moz-border-radius: 2px;
- border-radius: 2px;
-}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-arrangement .arrangement-helper {
+ background: #3f8ce8;
+ z-index: 1000000000;
+}
+.bi-arrangement .arrangement-block {
+ z-index: 1000000000;
+}
+.bi-arrangement .arrangement-drop-container {
+ z-index: 1000000000;
+}
+.bi-arrangement .arrangement-drop-container .arrangement-drop-region {
+ overflow: hidden;
+}
+.bi-arrangement .arrangement-drop-container .drop-devider {
+ z-index: 1000000001;
+ background: #3f8ce8;
+}
+.bi-arrangement .arrangement-drop-container .top-left,
+.bi-arrangement .arrangement-drop-container .top-right,
+.bi-arrangement .arrangement-drop-container .bottom-left,
+.bi-arrangement .arrangement-drop-container .bottom-right,
+.bi-arrangement .arrangement-drop-container .top-left-second,
+.bi-arrangement .arrangement-drop-container .top-right-second,
+.bi-arrangement .arrangement-drop-container .bottom-left-second,
+.bi-arrangement .arrangement-drop-container .bottom-right-second,
+.bi-arrangement .arrangement-drop-container .top-center,
+.bi-arrangement .arrangement-drop-container .bottom-center,
+.bi-arrangement .arrangement-drop-container .left-center,
+.bi-arrangement .arrangement-drop-container .right-center,
+.bi-arrangement .arrangement-drop-container .top-center-second,
+.bi-arrangement .arrangement-drop-container .bottom-center-second,
+.bi-arrangement .arrangement-drop-container .left-center-second,
+.bi-arrangement .arrangement-drop-container .right-center-second {
+ z-index: 1000000001;
+ background: #3f8ce8;
+}
+.bi-arrangement-droppable {
+ z-index: 100000;
+}
+/****添加计算宽度的--运算符直接需要space****/
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-adapt-editor .adapt-editor-text {
+ font-size: 14px;
+}
+/****添加计算宽度的--运算符直接需要space****/
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+/*************BI.SearchEditor******************/
+.bi-search-editor {
+ border: 1px solid #d4dadd;
+}
+.bi-search-editor .close-font {
+ font-size: 20px;
+}
+.bi-search-editor .search-font {
+ font-size: 20px;
+}
+/****添加计算宽度的--运算符直接需要space****/
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+/*************BI.SearchEditor******************/
+.bi-small-search-editor .bi-editor {
+ font-size: 12px;
+}
+.bi-small-search-editor .bi-editor .bi-input {
+ font-size: 12px;
+}
+.bi-small-search-editor .bi-editor .bi-label {
+ font-size: 12px;
+}
+.bi-small-search-editor .close-font {
+ font-size: 18px;
+}
+.bi-small-search-editor .search-font {
+ font-size: 18px;
+}
+/****添加计算宽度的--运算符直接需要space****/
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-sign-initial-editor .sign-initial-editor-text {
+ font-size: 14px;
+}
+/****添加计算宽度的--运算符直接需要space****/
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-sign-style-editor .sign-style-editor-text {
+ max-width: 100%;
+ font-size: 12px;
+}
+.bi-sign-style-editor .sign-style-editor-tip {
+ max-width: 100%;
+ font-size: 12px;
+ color: #808080;
+}
+/****添加计算宽度的--运算符直接需要space****/
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-text-editor {
+ border: 1px solid #d4dadd;
+}
+/****添加计算宽度的--运算符直接需要space****/
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+/*************BI.SearchEditor******************/
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-date-trigger {
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-down-list-popup .bi-down-list-item .list-item-text {
+ max-width: 203px;
+}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-excel-table > div.bottom-right > div > div > table {
+ border-right: 1px solid #d4dadd;
+}
+.bi-theme-dark .bi-excel-table > div.bottom-right > div > div > table {
+ border-right: 1px solid #525466;
+}
+.bi-excel-table-header-cell {
+ font-weight: bold;
+}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-file-manager-nav-button .file-manager-nav-button-text {
+ max-width: 200px;
+}
+.bi-file-manager-nav-button .file-manager-nav-button-text.active {
+ background-color: #eff1f4;
+ color: #999999;
+}
+.bi-file-manager-nav-button .file-manager-nav-button-triangle {
+ z-index: 1;
+}
+.bi-theme-dark .bi-file-manager-nav-button .file-manager-nav-button-text.active {
+ background-color: #191b2b;
+ color: #999999;
+}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-fine-tuning-number-editor {
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+}
+.bi-interactive-arrangement .interactive-arrangement-dragtag-line {
+ z-index: 1000000000;
+ background-color: #f07d0a;
+}
+.bi-interactive-arrangement .interactive-arrangement-dragtag-icon {
+ z-index: 1000000000;
+}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-month-trigger {
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+}
+.bi-multi-select-check-pane .multi-select-check-selected {
+ text-decoration: underline;
+}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-multi-select-combo .multi-select-trigger-icon-button {
+ font-size: 16px;
+}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-multi-select-trigger {
+ -webkit-border-radius: 2px 2px 2px 2px;
+ -moz-border-radius: 2px 2px 2px 2px;
+ border-radius: 2px 2px 2px 2px;
+}
+.bi-multi-select-search-pane .multi-select-toolbar {
+ color: #e85050;
+}
+.bi-multi-select-check-selected-button {
+ z-index: 1;
+}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-multi-tree-check-pane .multi-tree-check-selected {
+ color: #3f8ce8;
+}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-multi-tree-combo .multi-select-trigger-icon-button {
+ font-size: 16px;
+}
+.bi-multi-tree-popup .popup-view-tree {
+ min-height: 170px;
+}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-multi-tree-check-selected-button .trigger-check-selected {
+ color: #3f8ce8;
+ z-index: 1;
+}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-numerical-interval .numerical-interval-small-editor {
+ -moz-border-radius-topleft: 2px;
+ -webkit-border-top-left-radius: 2px;
+ -moz-border-radius-bottomleft: 2px;
+ -webkit-border-bottom-left-radius: 2px;
+ border-top-left-radius: 2px;
+ border-bottom-left-radius: 2px;
+}
+.bi-numerical-interval .numerical-interval-big-editor {
+ -moz-border-radius-topright: 2px;
+ -webkit-border-top-right-radius: 2px;
+ -moz-border-radius-bottomright: 2px;
+ -webkit-border-bottom-right-radius: 2px;
+ border-top-right-radius: 2px;
+ border-bottom-right-radius: 2px;
+}
+.bi-numerical-interval .numerical-interval-big-combo {
+ -moz-border-radius-topleft: 2px;
+ -webkit-border-top-left-radius: 2px;
+ -moz-border-radius-bottomleft: 2px;
+ -webkit-border-bottom-left-radius: 2px;
+ border-top-left-radius: 2px;
+ border-bottom-left-radius: 2px;
+}
+.bi-numerical-interval .numerical-interval-big-combo .bi-icon-combo-trigger .icon-combo-trigger-icon {
+ font-size: 14px;
+}
+.bi-numerical-interval .numerical-interval-small-combo {
+ -moz-border-radius-topright: 2px;
+ -webkit-border-top-right-radius: 2px;
+ -moz-border-radius-bottomright: 2px;
+ -webkit-border-bottom-right-radius: 2px;
+ border-top-right-radius: 2px;
+ border-bottom-right-radius: 2px;
+}
+.bi-numerical-interval .numerical-interval-small-combo .bi-icon-combo-trigger .icon-combo-trigger-icon {
+ font-size: 14px;
+}
+.bi-numerical-interval.number-error .bi-input {
+ color: #e85050;
+}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-page-table-cell {
+ -webkit-user-select: initial;
+ -khtml-user-select: initial;
+ -moz-user-select: initial;
+ -ms-user-select: initial;
+ -o-user-select: initial;
+ user-select: initial;
+}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-path-chooser .path-chooser-radio {
+ z-index: 1;
+}
+.bi-path-region .path-region-label {
+ z-index: 1;
+}
+.bi-preview-table-cell {
+ min-height: 25px;
+ min-width: 80px;
+ max-width: 220px;
+}
+.bi-preview-table {
+ -webkit-user-select: initial;
+ -khtml-user-select: initial;
+ -moz-user-select: initial;
+ -ms-user-select: initial;
+ -o-user-select: initial;
+ user-select: initial;
+}
+.bi-preview-table > div > table > thead > tr.odd,
+.bi-preview-table > div > div > div > table > thead > tr.odd {
+ background-color: #eff1f4;
+}
+.bi-theme-dark .bi-preview-table > div > table > thead > tr.odd,
+.bi-theme-dark .bi-preview-table > div > div > div > table > thead > tr.odd {
+ background-color: #191b2b;
+}
+.bi-preview-table-header-cell {
+ font-weight: bold;
+ min-height: 25px;
+ min-width: 80px;
+ max-width: 220px;
+}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-quarter-trigger {
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-relation-view-region .relation-view-region-container {
+ z-index: 1;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+}
+.bi-relation-view-region .relation-view-region-container.other-package {
+ border-style: dashed;
+}
+.bi-sequence-table-dynamic-number .sequence-table-title-cell {
+ overflow: hidden;
+ overflow-x: hidden;
+ overflow-y: hidden;
+ -webkit-box-sizing: border-box;
+ /*Safari3.2+*/
+ -moz-box-sizing: border-box;
+ /*Firefox3.5+*/
+ -ms-box-sizing: border-box;
+ /*IE8*/
+ box-sizing: border-box;
+ /*W3C标准(IE9+,Safari5.1+,Chrome10.0+,Opera10.6+都符合box-sizing的w3c标准语法)*/
+}
+.bi-sequence-table-dynamic-number .sequence-table-number-cell {
+ -webkit-box-sizing: border-box;
+ /*Safari3.2+*/
+ -moz-box-sizing: border-box;
+ /*Firefox3.5+*/
+ -ms-box-sizing: border-box;
+ /*IE8*/
+ box-sizing: border-box;
+ /*W3C标准(IE9+,Safari5.1+,Chrome10.0+,Opera10.6+都符合box-sizing的w3c标准语法)*/
+}
+.bi-sequence-table-list-number .sequence-table-title-cell {
+ overflow: hidden;
+ overflow-x: hidden;
+ overflow-y: hidden;
+ -webkit-box-sizing: border-box;
+ /*Safari3.2+*/
+ -moz-box-sizing: border-box;
+ /*Firefox3.5+*/
+ -ms-box-sizing: border-box;
+ /*IE8*/
+ box-sizing: border-box;
+ /*W3C标准(IE9+,Safari5.1+,Chrome10.0+,Opera10.6+都符合box-sizing的w3c标准语法)*/
+}
+.bi-sequence-table-list-number .sequence-table-number-cell {
+ -webkit-box-sizing: border-box;
+ /*Safari3.2+*/
+ -moz-box-sizing: border-box;
+ /*Firefox3.5+*/
+ -ms-box-sizing: border-box;
+ /*IE8*/
+ box-sizing: border-box;
+ /*W3C标准(IE9+,Safari5.1+,Chrome10.0+,Opera10.6+都符合box-sizing的w3c标准语法)*/
+}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-sequence-table-tree-number .sequence-table-title-cell {
+ overflow: hidden;
+ overflow-x: hidden;
+ overflow-y: hidden;
+ -webkit-box-sizing: border-box;
+ /*Safari3.2+*/
+ -moz-box-sizing: border-box;
+ /*Firefox3.5+*/
+ -ms-box-sizing: border-box;
+ /*IE8*/
+ box-sizing: border-box;
+ /*W3C标准(IE9+,Safari5.1+,Chrome10.0+,Opera10.6+都符合box-sizing的w3c标准语法)*/
+}
+.bi-sequence-table-tree-number .sequence-table-number-cell {
+ -webkit-box-sizing: border-box;
+ /*Safari3.2+*/
+ -moz-box-sizing: border-box;
+ /*Firefox3.5+*/
+ -ms-box-sizing: border-box;
+ /*IE8*/
+ box-sizing: border-box;
+ /*W3C标准(IE9+,Safari5.1+,Chrome10.0+,Opera10.6+都符合box-sizing的w3c标准语法)*/
+}
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+/****** common color(常用颜色,可用于普遍场景) *****/
+/**** custom color(自定义颜色,用于特定场景) ****/
+.bi-year-popup .year-popup-navigation {
+ line-height: 30px;
+}
+.bi-year-popup .year-popup-navigation > .center-element {
+ border-left: 1px solid #d4dadd;
+}
+.bi-year-popup .year-popup-navigation > .first-element {
+ border-left: none;
+}
+.bi-theme-dark .bi-year-popup .year-popup-navigation > .center-element {
+ border-left: 1px solid #525466;
+}
+.bi-theme-dark .bi-year-popup .year-popup-navigation > .first-element {
+ border-left: none;
+}
+.bi-year-trigger {
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+}
diff --git a/docs/base.js b/docs/base.js
index 7fd86def7..e478a6fa4 100644
--- a/docs/base.js
+++ b/docs/base.js
@@ -18335,7 +18335,7 @@ BI.TextAreaEditor = BI.inherit(BI.Single, {
tagName: "textarea",
width: "100%",
height: "100%",
- cls: "textarea-editor-content display-block"
+ cls: "bi-textarea textarea-editor-content display-block"
});
this.content.element.css({"resize": "none"});
BI.createWidget({
@@ -18523,6 +18523,15 @@ BI.Iframe = BI.inherit(BI.Single, {
return this.options.src;
},
+ setName: function (name) {
+ this.options.name = name;
+ this.element.attr("name", name);
+ },
+
+ getName: function () {
+ return this.options.name;
+ },
+
getWidth: function () {
return this.options.width
},
diff --git a/docs/chart.js b/docs/chart.js
index b095fe2bb..ad0ce9696 100644
--- a/docs/chart.js
+++ b/docs/chart.js
@@ -1,7602 +1,7602 @@
-/**
- * 图表控件
- * @class BI.Chart
- * @extends BI.Widget
- */
-BI.Chart = BI.inherit(BI.Pane, {
-
- _defaultConfig: function () {
- return BI.extend(BI.Chart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-chart"
- })
- },
-
- _init: function () {
- BI.Chart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
-
- this.isSetOptions = false;
- this.vanCharts = VanCharts.init(self.element[0]);
-
- this._resizer = BI.debounce(function () {
- if (self.element.width() > 0 && self.element.height() > 0) {
- self.vanCharts.resize();
- }
- }, 30);
- BI.ResizeDetector.addResizeListener(this, function (e) {
- self._resizer();
- });
- },
-
- resize: function () {
- if (this.isSetOptions === true) {
- this._resizer();
- }
- },
-
- magnify: function () {
- this.vanCharts.refreshRestore()
- },
-
- populate: function (items, options) {
- var self = this, o = this.options;
- o.items = items;
- this.config = options || {};
- this.config.series = o.items;
-
- var setOptions = function () {
- self.vanCharts.setOptions(self.config);
- self.isSetOptions = true;
- };
- BI.nextTick(setOptions);
- }
-});
-BI.Chart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.chart', BI.Chart);/**
- * 图表控件
- * @class BI.CombineChart
- * @extends BI.Widget
- */
-BI.CombineChart = BI.inherit(BI.Widget, {
-
- _defaultConfig: function () {
- return BI.extend(BI.CombineChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-combine-chart",
- items: [],
- xAxis: [{type: "category"}],
- yAxis: [{type: "value"}],
- types: [[], []],
- popupItemsGetter: BI.emptyFn,
- formatConfig: BI.emptyFn
- })
- },
-
- _init: function () {
- BI.CombineChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
-
- //图可配置属性
- this.CombineChart = BI.createWidget({
- type: "bi.chart",
- element: this.element
- });
- this.CombineChart.on(BI.Chart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.CombineChart.EVENT_CHANGE, obj);
- });
-
- if (BI.isNotEmptyArray(o.items)) {
- this.populate(o.items);
- }
- },
-
- _formatItems: function (items) {
- var result = [], self = this, o = this.options;
- var yAxisIndex = 0;
- BI.each(items, function (i, belongAxisItems) {
- var combineItems = BI.ChartCombineFormatItemFactory.combineItems(o.types[i], belongAxisItems);
- BI.each(combineItems, function (j, axisItems) {
- if (BI.isArray(axisItems)) {
- result = BI.concat(result, axisItems);
- } else {
- result.push(BI.extend(axisItems, {"yAxis": yAxisIndex}));
- }
- });
- if (BI.isNotEmptyArray(combineItems)) {
- yAxisIndex++;
- }
- });
- var config = BI.ChartCombineFormatItemFactory.combineConfig();
- config.plotOptions.click = function () {
- var data = BI.clone(this.options);
- data.toolTipRect = this.getTooltipRect();
- var items = o.popupItemsGetter(data);
- if (items && items.length === 1) {
- self.fireEvent(BI.CombineChart.EVENT_ITEM_CLICK, BI.extend({}, items[0], data));
- }
- if (items && items.length > 1) {
- self._createPopup(items, data.toolTipRect, data);
- }
- self.fireEvent(BI.CombineChart.EVENT_CHANGE, data);
- };
- return [result, config];
- },
-
- _createPopup: function (items, rect, opt) {
- var self = this;
- if (this.combo) {
- this.combo.destroy();
- }
- this._doDestroy = true;
- this.combo = BI.createWidget({
- type: "bi.combo",
- direction: "bottom",
- isNeedAdjustWidth: false,
- popup: {
- el: BI.createWidget({
- type: "bi.vertical",
- cls: "bi-linkage-list",
- items: BI.map(items, function (i, item) {
- return {
- el: BI.extend({
- type: "bi.text_button",
- cls: "bi-linkage-list-item",
- height: 30,
- handler: function () {
- self.fireEvent(BI.CombineChart.EVENT_ITEM_CLICK, BI.extend({}, item, opt));
- self.combo.destroy();
- },
- hgap: 10
- }, item)
- }
- })
- })
- },
- width: 0
- });
- BI.createWidget({
- type: "bi.absolute",
- element: this.element,
- items: [{
- el: this.combo,
- top: rect.y,
- left: rect.x
- }]
- });
- this.combo.element.hover(function () {
- self._doDestroy = false;
- }, function () {
- self._doDestroy = true;
- self._debounce2Destroy();
- });
- this._debounce2Destroy = BI.debounce(BI.bind(destroyCombo, this.combo), 3000);
- this.combo.showView();
- this._debounce2Destroy();
-
- function destroyCombo() {
- if (self._doDestroy) {
- this.destroy();
- }
- }
- },
-
- setTypes: function (types) {
- this.options.types = types || [[]];
- },
-
- populate: function (items, types) {
- var o = this.options;
- if (BI.isNotNull(types)) {
- this.setTypes(types);
- }
- var opts = this._formatItems(items);
- BI.extend(opts[1], {
- xAxis: o.xAxis,
- yAxis: o.yAxis
- });
- var result = o.formatConfig(opts[1], opts[0]) || opts;
- this.CombineChart.populate(result[0], result[1]);
- },
-
- resize: function () {
- this.CombineChart.resize();
- },
-
- magnify: function () {
- this.CombineChart.magnify();
- }
-});
-BI.CombineChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.CombineChart.EVENT_ITEM_CLICK = "EVENT_ITEM_CLICK";
-BI.shortcut('bi.combine_chart', BI.CombineChart);BI.ChartCombineFormatItemFactory = {
- combineItems: function (types, items) {
- var calItems = BI.values(items);
- return BI.map(calItems, function (idx, item) {
- return BI.ChartCombineFormatItemFactory.formatItems(types[idx], item);
- });
- },
-
- formatItems: function (type, items) {
- var item = {};
- switch (type) {
- case BICst.WIDGET.BAR:
- case BICst.WIDGET.ACCUMULATE_BAR:
- case BICst.WIDGET.COMPARE_BAR:
- item = BI.extend({"type": "bar"}, items);
- break;
- case BICst.WIDGET.BUBBLE:
- item = BI.extend({"type": "bubble"}, items);
- break;
- case BICst.WIDGET.FORCE_BUBBLE:
- item = BI.extend({"type": "forceBubble"}, items);
- break;
- case BICst.WIDGET.SCATTER:
- item = BI.extend({"type": "scatter"}, items);
- break;
- case BICst.WIDGET.AXIS:
- case BICst.WIDGET.ACCUMULATE_AXIS:
- case BICst.WIDGET.PERCENT_ACCUMULATE_AXIS:
- case BICst.WIDGET.COMPARE_AXIS:
- case BICst.WIDGET.FALL_AXIS:
- item = BI.extend({"type": "column"}, items);
- break;
- case BICst.WIDGET.LINE:
- item = BI.extend({"type": "line"}, items);
- break;
- case BICst.WIDGET.AREA:
- case BICst.WIDGET.ACCUMULATE_AREA:
- case BICst.WIDGET.COMPARE_AREA:
- case BICst.WIDGET.RANGE_AREA:
- case BICst.WIDGET.PERCENT_ACCUMULATE_AREA:
- item = BI.extend({"type": "area"}, items);
- break;
- case BICst.WIDGET.DONUT:
- item = BI.extend({"type": "pie"}, items);
- break;
- case BICst.WIDGET.RADAR:
- case BICst.WIDGET.ACCUMULATE_RADAR:
- item = BI.extend({"type": "radar"}, items);
- break;
- case BICst.WIDGET.PIE:
- item = BI.extend({"type": "pie"}, items);
- break;
- case BICst.WIDGET.DASHBOARD:
- item = BI.extend({"type": "gauge"}, items);
- break;
- case BICst.WIDGET.MAP:
- item = BI.extend({"type": "areaMap"}, items);
- break;
- case BICst.WIDGET.GIS_MAP:
- item = BI.extend({"type": "pointMap"}, items);
- break;
- default:
- item = BI.extend({"type": "column"}, items);
- break;
- }
- return item;
- },
-
- combineConfig: function () {
- return {
- "title": "",
- "chartType": "column",
- "plotOptions": {
- "rotatable": false,
- "startAngle": 0,
- "borderRadius": 0,
- "endAngle": 360,
- "innerRadius": "0.0%",
- "layout": "horizontal",
- "hinge": "rgb(101,107,109)",
- "dataLabels": {
- "autoAdjust": true,
- "style": {"fontFamily": "inherit", "color": "inherit", "fontSize": "12px"},
- "formatter": {
- "identifier": "${VALUE}",
- "valueFormat": this._contentFormat2Decimal,
- "seriesFormat": this._contentFormat,
- "percentFormat": this._contentFormatPercentage,
- "categoryFormat": this._contentFormat,
- "XFormat": this._contentFormat2Decimal,
- "YFormat": this._contentFormat2Decimal,
- "sizeFormat": this._contentFormat2Decimal
- },
- "align": "outside",
- "enabled": false
- },
- "percentageLabel": {
- "formatter": {
- "identifier": "${PERCENT}",
- "valueFormat": this._contentFormat2Decimal,
- "seriesFormat": this._contentFormat,
- "percentFormat": this._contentFormatPercentage,
- "categoryFormat": this._contentFormat
- },
- "style": {
- "fontFamily": "inherit", "color": "inherit", "fontSize": "12px"
- },
- "align": "bottom",
- "enabled": true
- },
- "valueLabel": {
- "formatter": {
- "identifier": "${SERIES}${VALUE}",
- "valueFormat": this._contentFormat2Decimal,
- "seriesFormat": this._contentFormat,
- "percentFormat": this._contentFormatPercentage,
- "categoryFormat": this._contentFormat
- },
- "backgroundColor": "rgb(255,255,0)",
- "style": {
- "fontFamily": "inherit", "color": "inherit", "fontSize": "12px"
- },
- "align": "inside",
- "enabled": true
- },
- "hingeBackgroundColor": "rgb(220,242,249)",
- "seriesLabel": {
- "formatter": {
- "identifier": "${CATEGORY}",
- "valueFormat": this._contentFormat2Decimal,
- "seriesFormat": this._contentFormat,
- "percentFormat": this._contentFormatPercentage,
- "categoryFormat": this._contentFormat
- },
- "style": {
- "fontFamily": "inherit", "color": "inherit", "fontSize": "12px"
- },
- "align": "bottom",
- "enabled": true
- },
- "paneBackgroundColor": "rgb(252,252,252)",
- "needle": "rgb(229,113,90)",
- "large": false,
- "connectNulls": false,
- "shadow": true,
- "curve": false,
- "sizeBy": "area",
- "tooltip": {
- "formatter": {
- "identifier": "${SERIES}${X}${Y}${SIZE}{CATEGORY}${SERIES}${VALUE}",
- "valueFormat": this._contentFormat2Decimal,
- "seriesFormat": this._contentFormat,
- "percentFormat": this._contentFormatPercentage,
- "categoryFormat": this._contentFormat,
- "XFormat": this._contentFormat2Decimal,
- "sizeFormat": this._contentFormat2Decimal,
- "YFormat": this._contentFormat2Decimal
- },
- "shared": false,
- "padding": 5,
- "backgroundColor": "rgba(0,0,0,0.4980392156862745)",
- "borderColor": "rgb(0,0,0)",
- "shadow": false,
- "borderRadius": 2,
- "borderWidth": 0,
- "follow": false,
- "enabled": true,
- "animation": true,
- "style": {
- "fontFamily": "Microsoft YaHei, Hiragino Sans GB W3",
- "color": "#c4c6c6",
- "fontSize": "12px",
- "fontWeight": ""
- }
- },
- "maxSize": 80,
- "fillColorOpacity": 0.5,
- "step": false,
- "force": false,
- "minSize": 15,
- "displayNegative": true,
- "categoryGap": "16.0%",
- "borderColor": "rgb(255,255,255)",
- "borderWidth": 1,
- "gap": "22.0%",
- "animation": true,
- "lineWidth": 2,
- "bubble": {
- "large": false,
- "connectNulls": false,
- "shadow": true,
- "curve": false,
- "sizeBy": "area",
- "maxSize": 80,
- "minSize": 15,
- "lineWidth": 0,
- "animation": true,
- "fillColorOpacity": 0.699999988079071,
- "marker": {
- "symbol": "circle",
- "radius": 28.39695010101295,
- "enabled": true
- }
- }
- },
- "dTools": {
- "enabled": false,
- "style": {
- "fontFamily": "Microsoft YaHei, Hiragino Sans GB W3",
- "color": "#1a1a1a",
- "fontSize": "12px"
- },
- "backgroundColor": 'white'
- },
- "dataSheet": {
- "enabled": false,
- "borderColor": "rgb(0,0,0)",
- "borderWidth": 1,
- "formatter": this._contentFormat2Decimal,
- "style": {
- "fontFamily": "inherit", "color": "inherit", "fontSize": "12px"
- }
- },
- "borderColor": "rgb(238,238,238)",
- "shadow": false,
- "legend": {
- "borderColor": "rgb(204,204,204)",
- "borderRadius": 0,
- "shadow": false,
- "borderWidth": 0,
- "visible": true,
- "style": {
- "fontFamily": "inherit", "color": "inherit", "fontSize": "12px"
- },
- "position": "right",
- "enabled": false
- },
- "rangeLegend": {
- "range": {
- "min": 0,
- "color": [
- [
- 0,
- "rgb(182,226,255)"
- ],
- [
- 0.5,
- "rgb(109,196,255)"
- ],
- [
- 1,
- "rgb(36,167,255)"
- ]
- ],
- "max": 266393
- },
- "enabled": false
- },
- "zoom": {"zoomType": "xy", "zoomTool": {"visible": false, "resize": true, "from": "", "to": ""}},
- "plotBorderColor": "rgba(255,255,255,0)",
- "tools": {
- "hidden": false,
- "toImage": {"enabled": false},
- "sort": {"enabled": false},
- "fullScreen": {"enabled": false},
- "refresh": {
- "enabled": false
- }
- },
- "plotBorderWidth": 0,
- "style": "normal",
- "colors": ["rgb(99,178,238)", "rgb(118,218,145)"],
- "borderRadius": 0,
- "borderWidth": 0,
- "plotShadow": false,
- "plotBorderRadius": 0
- };
- },
-
- _contentFormat: function () {
- return BI.contentFormat(arguments[0], '')
- },
-
- _contentFormat2Decimal: function () {
- return BI.contentFormat(arguments[0], '#.##;-#.##')
- },
-
- _contentFormatPercentage: function () {
- return BI.contentFormat(arguments[0], '#.##%;-#.##%')
- }
-};/**
- * 图表控件
- * @class BI.AbstractChart
- * @extends BI.Widget
- */
-BI.AbstractChart = BI.inherit(BI.Widget, {
-
- constants: {
- LEFT_AXIS: 0,
- RIGHT_AXIS: 1,
- RIGHT_AXIS_SECOND: 2,
- X_AXIS: 3,
- ROTATION: -90,
- NORMAL: 1,
- LEGEND_BOTTOM: 4,
- ZERO2POINT: 2,
- ONE2POINT: 3,
- TWO2POINT: 4,
- MINLIMIT: 1e-5,
- LEGEND_HEIGHT: 80,
- LEGEND_WIDTH: "30.0%",
- FIX_COUNT: 6,
- STYLE_NORMAL: 21,
- NO_PROJECT: 16,
- DASHBOARD_AXIS: 4,
- ONE_POINTER: 1,
- MULTI_POINTER: 2,
- HALF_DASHBOARD: 9,
- PERCENT_DASHBOARD: 10,
- PERCENT_SCALE_SLOT: 11,
- VERTICAL_TUBE: 12,
- HORIZONTAL_TUBE: 13,
- LNG_FIRST: 3,
- LAT_FIRST: 4,
- themeColor: "#65bce7",
- autoCustom: 1,
- POLYGON: 7,
- AUTO_CUSTOM: 1,
- AUTO: 1,
- NOT_SHOW: 2,
- LINE_WIDTH: 1,
- NUM_SEPARATORS: false,
- FONT_STYLE: {
- "fontFamily": "inherit",
- "color": "inherit",
- "fontSize": "12px"
- }
- },
-
- _defaultConfig: function () {
- return BI.extend(BI.AbstractChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-abstract-chart",
- popupItemsGetter: BI.emptyFn
- })
- },
-
- _init: function () {
- BI.AbstractChart.superclass._init.apply(this, arguments);
- },
-
- /**
- * 格式化坐标轴数量级及其所影响的系列的各项属性
- * @param config 配置信息
- * @param items 系列数据
- * @param type 坐标轴数量级
- * @param position 坐标轴位置
- * @param formatter 系列tooltip格式化内容
- */
- formatNumberLevelInYaxis: function (config, items, type, position, formatter, isPercentChart) {
- var magnify = this.calcMagnify(type);
- BI.each(items, function (idx, item) {
- BI.each(item.data, function (id, da) {
- if (position === item.yAxis) {
- if (BI.isNotNull(da.y) && !BI.isNumber(da.y)) {
- da.y = BI.parseFloat(da.y);
- }
- if (BI.isNotNull(da.y)) {
- da.y = BI.contentFormat(BI.parseFloat(da.y.div(magnify).toFixed(4)), "#.####;-#.####");
- }
- }
- });
- if (position === item.yAxis) {
- item.tooltip = BI.deepClone(config.plotOptions.tooltip);
- item.tooltip.formatter.valueFormat = formatter;
- if(isPercentChart) {
- item.tooltip.formatter.percentFormat = formatter;
- item.tooltip.formatter.identifier = "${CATEGORY}${SERIES}${PERCENT}";
- }
- }
- });
- },
-
- formatNumberLevelInXaxis: function (items, type) {
- var magnify = this.calcMagnify(type);
- BI.each(items, function (idx, item) {
- BI.each(item.data, function (id, da) {
- if (BI.isNotNull(da.x) && !BI.isNumber(da.x)) {
- da.x = BI.parseFloat(da.x);
- }
- if (BI.isNotNull(da.x)) {
- da.x = BI.contentFormat(BI.parseFloat(da.x.div(magnify).toFixed(4)), "#.####;-#.####");
- }
- });
- })
- },
-
- formatXYDataWithMagnify: function (number, magnify) {
- if (BI.isNull(number)) {
- return null
- }
- if (!BI.isNumber(number)) {
- number = BI.parseFloat(number);
- }
- return BI.contentFormat(BI.parseFloat(number.div(magnify).toFixed(4)), "#.####;-#.####");
- },
-
- calcMagnify: function (type) {
- var magnify = 1;
- switch (type) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- case BICst.TARGET_STYLE.NUM_LEVEL.PERCENT:
- magnify = 1;
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- magnify = 10000;
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- magnify = 1000000;
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- magnify = 100000000;
- break;
- }
- return magnify;
- },
-
- formatChartLegend: function (config, chartLegend) {
- switch (chartLegend) {
- case BICst.CHART_LEGENDS.BOTTOM:
- config.legend.enabled = true;
- config.legend.position = "bottom";
- config.legend.maxHeight = this.constants.LEGEND_HEIGHT;
- break;
- case BICst.CHART_LEGENDS.RIGHT:
- config.legend.enabled = true;
- config.legend.position = "right";
- config.legend.maxWidth = this.constants.LEGEND_WIDTH;
- break;
- case BICst.CHART_LEGENDS.NOT_SHOW:
- default:
- config.legend.enabled = false;
- break;
- }
- },
-
- getXYAxisUnit: function (numberLevelType, axis_unit) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- return (BI.isEmptyString(unit) && BI.isEmptyString(axis_unit)) ? unit : "(" + unit + axis_unit + ")";
- },
-
- formatTickInXYaxis: function (type, number_level, separators, isCompareBar) {
- var formatter = '#.##';
- switch (type) {
- case this.constants.NORMAL:
- formatter = '#.##';
- if (separators) {
- formatter = '#,###.##'
- }
- break;
- case this.constants.ZERO2POINT:
- formatter = '#0';
- if (separators) {
- formatter = '#,###';
- }
- break;
- case this.constants.ONE2POINT:
- formatter = '#0.0';
- if (separators) {
- formatter = '#,###.0';
- }
- break;
- case this.constants.TWO2POINT:
- formatter = '#0.00';
- if (separators) {
- formatter = '#,###.00';
- }
- break;
- }
- if (number_level === BICst.TARGET_STYLE.NUM_LEVEL.PERCENT) {
- formatter += '%';
- }
- formatter += ";-" + formatter;
- if(isCompareBar) {
- return function () {
- arguments[0] = arguments[0] > 0 ? arguments[0] : (-1) * arguments[0];
- return BI.contentFormat(arguments[0], formatter);
- }
- }
- return function () {
- return BI.contentFormat(arguments[0], formatter)
- }
- },
-
- formatDataLabel: function (state, items, config, style) {
- var self = this;
- if (state === true) {
- BI.each(items, function (idx, item) {
- item.dataLabels = {
- "align": "outside",
- "autoAdjust": true,
- style: style,
- enabled: true,
- formatter: {
- identifier: "${VALUE}",
- valueFormat: config.yAxis[item.yAxis].formatter
- }
- };
- });
- }
- },
-
- formatDataLabelForAxis: function (state, items, format, style, isPercentChart) {
- var self = this;
- if (state === true) {
- BI.each(items, function (idx, item) {
- item.dataLabels = {
- "align": "outside",
- "autoAdjust": true,
- style: style,
- enabled: true,
- formatter: {
- identifier: "${VALUE}",
- valueFormat: format,
- }
- };
- if(isPercentChart) {
- item.dataLabels.formatter.identifier = "${PERCENT}";
- item.dataLabels.formatter.percentFormat = format;
- }
- });
- }
- },
-
- setFontStyle: function (fontStyle, config) {
- if (config.dataSheet) {
- config.dataSheet.style = fontStyle;
- }
- config.xAxis[0].title.style = fontStyle;
- config.xAxis[0].labelStyle = fontStyle;
- config.legend.style = fontStyle;
- BI.each(config.yAxis, function (idx, axis) {
- axis.labelStyle = fontStyle;
- axis.title.style = fontStyle;
- })
- },
-
- _formatItems: function (items) {
- return items;
- },
-
- populate: function (items, options) {
- },
-
- resize: function () {
- },
-
- magnify: function () {
- }
-});
-
-BI.AbstractChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.AbstractChart.EVENT_ITEM_CLICK = "EVENT_ITEM_CLICK";
-/**
- * 图表控件
- * @class BI.AccumulateAreaChart
- * @extends BI.Widget
- */
-BI.AccumulateAreaChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.AccumulateAreaChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-accumulate-area-chart"
- })
- },
-
- _init: function () {
- BI.AccumulateAreaChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
-
- this.xAxis = [{
- type: "category",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE
- }];
- this.yAxis = [];
-
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.AccumulateAreaChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this;
-
- config.colors = this.config.chartColor;
- config.style = formatChartStyle(this.config.chartStyle);
- formatChartLineStyle(this.config.chartLineType);
- formatCordon(this.config.cordon);
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.plotOptions.connectNulls = this.config.nullContinue;
- config.dataSheet.enabled = this.config.showDataTable;
- config.xAxis[0].showLabel = !config.dataSheet.enabled;
- config.zoom.zoomTool.enabled = this.config.showZoom;
- if (this.config.showZoom === true) {
- delete config.dataSheet;
- delete config.zoom.zoomType;
- }
-
- config.yAxis = this.yAxis;
- BI.each(config.yAxis, function (idx, axis) {
- var unit = "";
- switch (axis.axisIndex) {
- case self.constants.LEFT_AXIS:
- unit = self.getXYAxisUnit(self.config.leftYAxisNumberLevel, self.config.leftYAxisUnit);
- axis.title.text = self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + unit : unit;
- axis.title.rotation = self.constants.ROTATION;
- BI.extend(axis, {
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- reversed: self.config.leftYAxisReversed,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)
- });
- self.formatNumberLevelInYaxis(config, items, self.config.leftYAxisNumberLevel, idx, axis.formatter, self.config.numSeparators);
-
- break;
- case self.constants.RIGHT_AXIS:
- unit = self.getXYAxisUnit(self.config.rightYAxisNumberLevel, self.config.rightYAxisUnit);
- axis.title.text = self.config.showRightYAxisTitle === true ? self.config.rightYAxisTitle + unit : unit;
- axis.title.rotation = self.constants.ROTATION;
- BI.extend(axis, {
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- reversed: self.config.rightYAxisReversed,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators)
- });
- self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisNumberLevel, idx, axis.formatter, self.config.rightNumSeparators);
- break;
- }
- });
-
- config.xAxis[0].title.align = "center";
- config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
- BI.extend(config.xAxis[0], {
- lineWidth: this.config.lineWidth,
- enableTick: this.config.enableTick,
- labelRotation: this.config.textDirection,
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- maxHeight: '40%'
- });
-
- config.chartType = "area";
-
- //为了给数据标签加个%,还要遍历所有的系列,唉
- this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
-
- //全局样式的图表文字
- this.setFontStyle(this.config.chartFont, config);
-
- return [items, config];
-
- function formatChartStyle(v) {
- switch (v) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatChartLineStyle(v) {
- switch (v) {
- case BICst.CHART_SHAPE.RIGHT_ANGLE:
- config.plotOptions.curve = false;
- config.plotOptions.step = true;
- break;
- case BICst.CHART_SHAPE.CURVE:
- config.plotOptions.curve = true;
- config.plotOptions.step = false;
- break;
- case BICst.CHART_SHAPE.NORMAL:
- default:
- config.plotOptions.curve = false;
- config.plotOptions.step = false;
- break;
- }
- }
-
- function formatCordon(cordon) {
- BI.each(cordon, function (idx, cor) {
- if (idx === 0 && self.xAxis.length > 0) {
- var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if (idx > 0 && self.yAxis.length >= idx) {
- var magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- }
- },
-
- _formatItems: function (items) {
- return BI.map(items, function (idx, item) {
- var i = BI.UUID();
- return BI.map(item, function (id, it) {
- return BI.extend({}, it, {stack: i});
- });
- });
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- rightYAxisTitle: options.rightYAxisTitle || "",
- chartColor: options.chartColor || [],
- chartStyle: options.chartStyle || c.STYLE_NORMAL,
- chartLineType: options.chartLineType || c.NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- showRightYAxisTitle: options.showRightYAxisTitle || false,
- leftYAxisReversed: options.leftYAxisReversed || false,
- rightYAxisReversed: options.rightYAxisReversed || false,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- rightYAxisUnit: options.rightYAxisUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showDataTable: options.showDataTable || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- showZoom: options.showZoom || false,
- textDirection: options.textDirection || 0,
- cordon: options.cordon || [],
- lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
- showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
- enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
- enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
- numSeparators: options.numSeparators || false,
- rightNumSeparators: options.rightNumSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE,
- nullContinue: options.nullContinue || false
- };
- this.options.items = items;
- this.yAxis = [];
- var types = [];
- BI.each(items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function (id, item) {
- type.push(BICst.WIDGET.AREA);
- });
- types.push(type);
- });
- BI.each(types, function (idx, type) {
- if (BI.isEmptyArray(type)) {
- return;
- }
- var newYAxis = {
- type: "value",
- title: {
- style: self.constants.FONT_STYLE
- },
- labelStyle: self.constants.FONT_STYLE,
- position: idx > 0 ? "right" : "left",
- lineWidth: 1,
- axisIndex: idx,
- gridLineWidth: 0
- };
- self.yAxis.push(newYAxis);
- });
- this.combineChart.populate(this._formatItems(items), types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.AccumulateAreaChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.accumulate_area_chart', BI.AccumulateAreaChart);/**
- * 图表控件
- * @class BI.AccumulateAxisChart
- * @extends BI.Widget
- */
-BI.AccumulateAxisChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.AccumulateAxisChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-accumulate-axis-chart"
- })
- },
-
- _init: function () {
- BI.AccumulateAxisChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.xAxis = [{
- type: "category",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE
- }];
- this.yAxis = [];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.AccumulateAxisChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this, o = this.options;
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- formatCordon();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.dataSheet.enabled = this.config.showDataTable;
- config.xAxis[0].showLabel = !config.dataSheet.enabled;
- config.zoom.zoomTool.enabled = this.config.showZoom;
- if (this.config.showZoom === true) {
- delete config.dataSheet;
- delete config.zoom.zoomType;
- }
-
- config.yAxis = this.yAxis;
- BI.each(config.yAxis, function (idx, axis) {
- switch (axis.axisIndex) {
- case self.constants.LEFT_AXIS:
- axis.title.text = getTitleText(self.config.leftYAxisNumberLevel, self.constants.LEFT_AXIS, self.config.showLeftYAxisTitle, self.config.leftYAxisTitle);
- axis.title.rotation = self.constants.ROTATION;
- BI.extend(axis, {
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- reversed: self.config.leftYAxisReversed,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)
- });
- self.formatNumberLevelInYaxis(config, items, self.config.leftYAxisNumberLevel, idx, axis.formatter);
- break;
- case self.constants.RIGHT_AXIS:
- axis.title.text = getTitleText(self.config.rightYAxisNumberLevel, self.constants.RIGHT_AXIS, self.config.showRightYAxisTitle, self.config.rightYAxisTitle);
- axis.title.rotation = self.constants.ROTATION;
- BI.extend(axis, {
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- reversed: self.config.rightYAxisReversed,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators)
- });
- self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisNumberLevel, idx, axis.formatter);
- break;
- }
- });
-
- config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
- config.xAxis[0].title.align = "center";
- BI.extend(config.xAxis[0], {
- lineWidth: self.config.lineWidth,
- enableTick: self.config.enableTick,
- labelRotation: this.config.textDirection,
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- maxHeight: '40%'
- });
-
- config.chartType = "column";
-
- //为了给数据标签加个%,还要遍历所有的系列,唉
- this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
-
- //全局样式的图表文字
- this.setFontStyle(this.config.chartFont, config);
-
- return [items, config];
-
- function formatCordon() {
- BI.each(self.config.cordon, function (idx, cor) {
- if (idx === 0 && self.xAxis.length > 0) {
- var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if (idx > 0 && self.yAxis.length >= idx) {
- var magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- }
-
- function formatChartStyle() {
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function getTitleText(numberLevelType, position, show, title) {
- var unit = "";
-
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if (position === self.constants.X_AXIS) {
- self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
- }
- if (position === self.constants.LEFT_AXIS) {
- self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
- }
- if (position === self.constants.RIGHT_AXIS) {
- self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
- }
-
- unit = unit === "" ? unit : "(" + unit + ")";
-
- return show === true ? title + unit : unit;
- }
- },
-
- _formatItems: function (items) {
- return BI.map(items, function (idx, item) {
- var i = BI.UUID();
- return BI.map(item, function (id, it) {
- return BI.extend({}, it, {stack: i});
- });
- });
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- rightYAxisTitle: options.rightYAxisTitle || "",
- chartColor: options.chartColor || [],
- chartStyle: options.chartStyle || c.STYLE_NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- showRightYAxisTitle: options.showRightYAxisTitle || false,
- leftYAxisReversed: options.leftYAxisReversed || false,
- rightYAxisReversed: options.rightYAxisReversed || false,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- rightYAxisUnit: options.rightYAxisUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showDataTable: options.showDataTable || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- showZoom: options.showZoom || false,
- textDirection: options.textDirection || 0,
- cordon: options.cordon || [],
- lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
- showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
- enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
- enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
- numSeparators: options.numSeparators || false,
- rightNumSeparators: options.rightNumSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE
- };
- this.options.items = items;
- this.yAxis = [];
- var types = [];
- BI.each(items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function (id, item) {
- type.push(BICst.WIDGET.AXIS);
- });
- types.push(type);
- });
- BI.each(types, function (idx, type) {
- if (BI.isEmptyArray(type)) {
- return;
- }
- var newYAxis = {
- type: "value",
- title: {
- style: self.constants.FONT_STYLE
- },
- labelStyle: self.constants.FONT_STYLE,
- position: idx > 0 ? "right" : "left",
- lineWidth: 1,
- axisIndex: idx,
- gridLineWidth: 0
- };
- self.yAxis.push(newYAxis);
- });
- this.combineChart.populate(this._formatItems(items), types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.AccumulateAxisChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.accumulate_axis_chart', BI.AccumulateAxisChart);/**
- * 图表控件
- * @class BI.AccumulateBarChart
- * @extends BI.Widget
- */
-BI.AccumulateBarChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.AccumulateBarChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-accumulate-bar-chart"
- })
- },
-
- _init: function () {
- BI.AccumulateBarChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.xAxis = [{
- type: "value",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- formatter: function () {
- return this > 0 ? this : (-1) * this
- },
- gridLineWidth: 0
- }];
- this.yAxis = [{
- type: "category",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- gridLineWidth: 0,
- position: "left"
- }];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.AccumulateBarChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this;
- var unit = getXYAxisUnit(this.config.xAxisNumberLevel, this.constants.LEFT_AXIS);
- var xTitle = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.X_AXIS);
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- formatCordon();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
-
- config.yAxis = this.yAxis;
- config.yAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle + unit : unit;
- config.yAxis[0].title.rotation = this.constants.ROTATION;
- BI.extend(config.yAxis[0], {
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- labelRotation: this.config.textDirection,
- lineWidth: this.config.lineWidth,
- enableTick: this.config.enableTick,
- maxWidth: '40%'
- });
-
- self.formatNumberLevelInXaxis(items, this.config.leftYAxisNumberLevel);
- config.xAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + xTitle : xTitle;
- config.xAxis[0].title.align = "center";
- BI.extend(config.xAxis[0], {
- formatter: self.formatTickInXYaxis(this.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators),
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- showLabel: this.config.showLabel,
- enableTick: this.config.enableTick,
- lineWidth: this.config.lineWidth,
- enableMinorTick: this.config.enableMinorTick
- });
- config.chartType = "bar";
- //为了给数据标签加个%,还要遍历所有的系列,唉
- this.formatDataLabelForAxis(config.plotOptions.dataLabels.enabled, items, config.xAxis[0].formatter, this.config.chartFont);
-
- config.plotOptions.tooltip.formatter.valueFormat = config.xAxis[0].formatter;
-
- //全局样式的图表文字
- this.setFontStyle(this.config.chartFont, config);
-
- return [items, config];
-
- function formatChartStyle() {
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatCordon() {
- BI.each(self.config.cordon, function (idx, cor) {
- if (idx === 0 && self.xAxis.length > 0) {
- var magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if (idx > 0 && self.yAxis.length >= idx) {
- var magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.xAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- }
-
- function getXYAxisUnit(numberLevelType, position) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if (position === self.constants.X_AXIS) {
- self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
- }
- if (position === self.constants.LEFT_AXIS) {
- self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
- }
- if (position === self.constants.RIGHT_AXIS) {
- self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
- }
- return unit === "" ? unit : "(" + unit + ")";
- }
- },
-
- _formatItems: function (items) {
- BI.each(items, function (idx, item) {
- var stackId = BI.UUID();
- BI.each(item, function (id, it) {
- it.stack = stackId;
- BI.each(it.data, function (i, t) {
- var tmp = t.x;
- t.x = t.y;
- t.y = tmp;
- })
- });
- });
- return items;
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- chartColor: options.chartColor || [],
- chartStyle: options.chartStyle || c.STYLE_NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- xAxisStyle: options.xAxisStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- leftYAxisReversed: options.leftYAxisReversed || false,
- xAxisNumberLevel: options.xAxisNumberLevel || c.NORMAL,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showDataTable: options.showDataTable || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- showZoom: options.showZoom || false,
- textDirection: options.textDirection || 0,
- cordon: options.cordon || [],
- minimalist_model: options.minimalist_model || false,
- lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
- showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
- enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
- enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
- numSeparators: options.numSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE
- };
- this.options.items = items;
- var types = [];
- BI.each(items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function (id, item) {
- type.push(BICst.WIDGET.BAR);
- });
- types.push(type);
- });
- this.combineChart.populate(this._formatItems(items), types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.AccumulateBarChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.accumulate_bar_chart', BI.AccumulateBarChart);/**
- * 图表控件
- * @class BI.AccumulateRadarChart
- * @extends BI.Widget
- */
-BI.AccumulateRadarChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.AccumulateRadarChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-accumulate-radar-chart"
- })
- },
-
- _init: function () {
- BI.AccumulateRadarChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.radiusAxis = [{
- type: "value",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- formatter: function () {
- return this > 0 ? this : (-1) * this
- },
- gridLineWidth: 0,
- position: "bottom"
- }];
-
- this.angleAxis = [{
- type: "category",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE
- }];
-
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.AccumulateRadarChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatItems: function (items) {
- return BI.map(items, function (idx, item) {
- var i = BI.UUID();
- return BI.map(item, function (id, it) {
- return BI.extend({}, it, {stack: i});
- });
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this;
-
- delete config.zoom;
-
- var title = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- formatChartRadarStyle();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.plotOptions.connectNulls = this.config.nullContinue;
-
- config.radiusAxis = this.radiusAxis;
- config.angleAxis = this.angleAxis;
- config.radiusAxis[0].formatter = self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators);
- formatNumberLevelInYaxis(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS, config.radiusAxis[0].formatter);
- config.radiusAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + title : title;
- config.radiusAxis[0].gridLineWidth = this.config.showGridLine === true ? 1 : 0;
- config.chartType = "radar";
- config.plotOptions.columnType = true;
- delete config.xAxis;
- delete config.yAxis;
- //为了给数据标签加个%,还要遍历所有的系列,唉
- this.formatDataLabelForAxis(config.plotOptions.dataLabels.enabled, items, config.radiusAxis[0].formatter, this.config.chartFont);
-
- //全局样式的图表文字
- config.radiusAxis[0].labelStyle = config.radiusAxis[0].title.style = this.config.chartFont;
- config.angleAxis[0].labelStyle = config.angleAxis[0].title.style = this.config.chartFont;
- config.legend.style = this.config.chartFont;
-
- return [items, config];
-
- function formatChartStyle() {
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatChartRadarStyle() {
- switch (self.config.chartRadarType) {
- case BICst.CHART_SHAPE.POLYGON:
- config.plotOptions.shape = "polygon";
- break;
- case BICst.CHART_SHAPE.CIRCLE:
- config.plotOptions.shape = "circle";
- break;
- }
- }
-
- function formatNumberLevelInYaxis(type, position, formatter) {
- var magnify = self.calcMagnify(type);
- BI.each(items, function (idx, item) {
- BI.each(item.data, function (id, da) {
- if (position === item.yAxis) {
- da.y = self.formatXYDataWithMagnify(da.y, magnify);
- }
- })
- });
- config.plotOptions.tooltip.formatter.valueFormat = formatter;
- }
-
- function getXYAxisUnit(numberLevelType, position) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if (position === self.constants.X_AXIS) {
- self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
- }
- if (position === self.constants.LEFT_AXIS) {
- self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
- }
- if (position === self.constants.RIGHT_AXIS) {
- self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
- }
- return unit === "" ? unit : "(" + unit + ")";
- }
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- chartRadarType: options.chartRadarType || c.NORMAL,
- chartColor: options.chartColor || [],
- chartStyle: options.chartStyle || c.STYLE_NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- cordon: options.cordon || [],
- numSeparators: options.numSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE,
- nullContinue: options.nullContinue || false
- };
- this.options.items = items;
- var types = [];
- BI.each(items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function (id, item) {
- type.push(BICst.WIDGET.RADAR);
- });
- types.push(type);
- });
- this.combineChart.populate(this._formatItems(items), types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.AccumulateRadarChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.accumulate_radar_chart', BI.AccumulateRadarChart);/**
- * 图表控件
- * @class BI.AreaChart
- * @extends BI.Widget
- */
-BI.AreaChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.AreaChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-area-chart"
- })
- },
-
- _init: function () {
- BI.AreaChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.xAxis = [{
- type: "category",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- position: "bottom",
- gridLineWidth: 0
- }];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.AreaChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this;
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- formatChartLineStyle();
- formatCordon();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.plotOptions.connectNulls = this.config.nullContinue;
- config.dataSheet.enabled = this.config.showDataTable;
- config.xAxis[0].showLabel = !config.dataSheet.enabled;
- config.zoom.zoomTool.enabled = this.config.showZoom;
- if (this.config.showZoom === true) {
- delete config.dataSheet;
- delete config.zoom.zoomType;
- }
-
- config.yAxis = this.yAxis;
- BI.each(config.yAxis, function (idx, axis) {
- var title = "";
- switch (axis.axisIndex) {
- case self.constants.LEFT_AXIS:
- title = getXYAxisUnit(self.config.leftYAxisNumberLevel, self.constants.LEFT_AXIS);
- axis.title.text = self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + title : title;
- axis.title.rotation = self.constants.ROTATION;
- BI.extend(axis, {
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- reversed: self.config.leftYAxisReversed,
- enableMinorTick: self.config.enableMinorTick,
- formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators),
- gridLineWidth: self.config.showGridLine === true ? 1 : 0
- });
- self.formatNumberLevelInYaxis(config, items, self.config.leftYAxisNumberLevel, idx, axis.formatter);
- break;
- case self.constants.RIGHT_AXIS:
- title = getXYAxisUnit(self.config.rightYAxisNumberLevel, self.constants.RIGHT_AXIS);
- axis.title.text = self.config.showRightYAxisTitle === true ? self.config.rightYAxisTitle + title : title;
- axis.title.rotation = self.constants.ROTATION;
- BI.extend(axis, {
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- reversed: self.config.rightYAxisReversed,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators)
- });
- self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisNumberLevel, idx, axis.formatter);
- break;
- }
- });
-
- config.xAxis[0].title.align = "center";
- config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
- BI.extend(config.xAxis[0], {
- lineWidth: this.config.lineWidth,
- enableTick: this.config.enableTick,
- labelRotation: this.config.textDirection,
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- maxHeight: '40%'
- });
-
- config.chartType = "area";
-
- //为了给数据标签加个%,还要遍历所有的系列,唉
- this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
-
- //全局样式的图表文字
- this.setFontStyle(this.config.chartFont, config);
-
- return [items, config];
-
- function formatChartStyle() {
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatCordon() {
- BI.each(self.config.cordon, function (idx, cor) {
- if (idx === 0 && self.xAxis.length > 0) {
- var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if (idx > 0 && self.yAxis.length >= idx) {
- var magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- }
-
- function formatChartLineStyle() {
- switch (self.config.chartLineType) {
- case BICst.CHART_SHAPE.RIGHT_ANGLE:
- config.plotOptions.curve = false;
- config.plotOptions.step = true;
- break;
- case BICst.CHART_SHAPE.CURVE:
- config.plotOptions.curve = true;
- config.plotOptions.step = false;
- break;
- case BICst.CHART_SHAPE.NORMAL:
- default:
- config.plotOptions.curve = false;
- config.plotOptions.step = false;
- break;
- }
- }
-
- function getXYAxisUnit(numberLevelType, position) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if (position === self.constants.X_AXIS) {
- self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
- }
- if (position === self.constants.LEFT_AXIS) {
- self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
- }
- if (position === self.constants.RIGHT_AXIS) {
- self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
- }
- return unit === "" ? unit : "(" + unit + ")";
- }
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- rightYAxisTitle: options.rightYAxisTitle || "",
- rightYAxisSecondTitle: options.rightYAxisSecondTitle || "",
- chartLineType: options.chartLineType || c.NORMAL,
- chartColor: options.chartColor || [],
- chartStyle: options.chartStyle || c.NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
- rightYAxisSecondStyle: options.rightYAxisSecondStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- showRightYAxisTitle: options.showRightYAxisTitle || false,
- showRightYAxisSecondTitle: options.showRightYAxisSecondTitle || false,
- leftYAxisReversed: options.leftYAxisReversed || false,
- rightYAxisReversed: options.rightYAxisReversed || false,
- rightYAxisSecondReversed: options.rightYAxisSecondReversed || false,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
- rightYAxisSecondNumberLevel: options.rightYAxisSecondNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- rightYAxisUnit: options.rightYAxisUnit || "",
- rightYAxisSecondUnit: options.rightYAxisSecondUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showDataTable: options.showDataTable || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- showZoom: options.showZoom || false,
- textDirection: options.textDirection || 0,
- cordon: options.cordon || [],
- lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
- showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
- enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
- enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
- numSeparators: options.numSeparators || false,
- rightNumSeparators: options.rightNumSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE,
- nullContinue: options.nullContinue || false
- };
- this.options.items = items;
-
- var types = [];
- BI.each(items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function (id, item) {
- type.push(BICst.WIDGET.AREA);
- });
- types.push(type);
- });
-
- this.yAxis = [];
- BI.each(types, function (idx, type) {
- if (BI.isEmptyArray(type)) {
- return;
- }
- var newYAxis = {
- type: "value",
- title: {
- style: self.constants.FONT_STYLE
- },
- labelStyle: self.constants.FONT_STYLE,
- position: idx > 0 ? "right" : "left",
- lineWidth: 1,
- axisIndex: idx,
- gridLineWidth: 0
- };
- self.yAxis.push(newYAxis);
- });
-
- this.combineChart.populate(items, types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.AreaChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.area_chart', BI.AreaChart);/**
- * 图表控件 柱状
- * @class BI.AxisChart
- * @extends BI.Widget
- * leftYxis 左值轴属性
- * rightYxis 右值轴属性
- * xAxis 分类轴属性
- */
-BI.AxisChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.AxisChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-axis-chart"
- })
- },
-
- _init: function () {
- BI.AxisChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.xAxis = [{
- type: "category",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- position: "bottom",
- gridLineWidth: 0
- }];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.AxisChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this, o = this.options;
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- formatCordon();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.plotOptions.connectNulls = this.config.nullContinue;
- config.dataSheet.enabled = this.config.showDataTable;
- config.xAxis[0].showLabel = !config.dataSheet.enabled;
- config.zoom.zoomTool.enabled = this.config.showZoom;
- if (this.config.showZoom === true) {
- delete config.dataSheet;
- delete config.zoom.zoomType;
- }
-
- config.yAxis = this.yAxis;
- BI.each(config.yAxis, function (idx, axis) {
- var title;
- switch (axis.axisIndex) {
- case self.constants.LEFT_AXIS:
- title = getXYAxisUnit(self.config.leftYAxisNumberLevel, self.constants.LEFT_AXIS);
- axis.title.text = self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + title : title;
- axis.title.rotation = self.constants.ROTATION;
- BI.extend(axis, {
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- reversed: self.config.leftYAxisReversed,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)
- });
- self.formatNumberLevelInYaxis(config, items, self.config.leftYAxisNumberLevel, idx, axis.formatter);
- break;
- case self.constants.RIGHT_AXIS:
- title = getXYAxisUnit(self.config.rightYAxisNumberLevel, self.constants.RIGHT_AXIS);
- axis.title.text = self.config.showRightYAxisTitle === true ? self.config.rightYAxisTitle + title : title;
- axis.title.rotation = self.constants.ROTATION;
- BI.extend(axis, {
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- reversed: self.config.rightYAxisReversed,
- enableMinorTIck: self.config.enableMinorTick,
- formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators),
- gridLineWidth: self.config.showGridLine === true ? 1 : 0
- });
- self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisNumberLevel, idx, axis.formatter);
- break;
- }
- });
-
- config.xAxis[0].title.align = "center";
- config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
- BI.extend(config.xAxis[0], {
- lineWidth: this.config.lineWidth,
- enableTick: this.config.enableTick,
- labelRotation: this.config.textDirection,
- enableMinorTick: this.config.enableMinorTick,
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- maxHeight: '40%'
- });
-
- var lineItem = [];
- var otherItem = [];
- BI.each(items, function (idx, item) {
- if (item.type === "line") {
- lineItem.push(item);
- } else {
- otherItem.push(item);
- }
- });
-
- //为了给数据标签加个%,还要遍历所有的系列,唉
- this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
-
- //全局样式的图表文字
- this.setFontStyle(this.config.chartFont, config);
-
- return [BI.concat(otherItem, lineItem), config];
-
- function formatChartStyle() {
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatCordon() {
- BI.each(self.config.cordon, function (idx, cor) {
- if (idx === 0 && self.xAxis.length > 0) {
- var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if (idx > 0 && self.yAxis.length >= idx) {
- var magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- }
-
- function getXYAxisUnit(numberLevelType, position) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if (position === self.constants.X_AXIS) {
- self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
- }
- if (position === self.constants.LEFT_AXIS) {
- self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
- }
- if (position === self.constants.RIGHT_AXIS) {
- self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
- }
- return unit === "" ? unit : "(" + unit + ")";
- }
- },
-
- populate: function (items, options, types) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- rightYAxisTitle: options.rightYAxisTitle || "",
- chartColor: options.chartColor || [],
- chartStyle: options.chartStyle || c.NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- showRightYAxisTitle: options.showRightYAxisTitle || false,
- leftYAxisReversed: options.leftYAxisReversed || false,
- rightYAxisReversed: options.rightYAxisReversed || false,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- rightYAxisUnit: options.rightYAxisUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showDataTable: options.showDataTable || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- showZoom: options.showZoom || false,
- textDirection: options.textDirection || 0,
- cordon: options.cordon || [],
- lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
- showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
- enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
- enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
- numSeparators: options.numSeparators || false,
- rightNumSeparators: options.rightNumSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE,
- nullContinue: true
- };
- this.options.items = items;
-
- this.yAxis = [];
- BI.each(types, function (idx, type) {
- if (BI.isEmptyArray(type)) {
- return;
- }
- var newYAxis = {
- type: "value",
- title: {
- style: self.constants.FONT_STYLE
- },
- labelStyle: self.constants.FONT_STYLE,
- position: idx > 0 ? "right" : "left",
- lineWidth: 1,
- axisIndex: idx,
- gridLineWidth: 0
- };
- self.yAxis.push(newYAxis);
- });
-
- this.combineChart.populate(items, types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.AxisChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.axis_chart', BI.AxisChart);/**
- * 图表控件
- * @class BI.BarChart
- * @extends BI.Widget
- */
-BI.BarChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.BarChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-bar-chart"
- })
- },
-
- _init: function () {
- BI.BarChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.xAxis = [{
- type: "value",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- formatter: function () {
- return this > 0 ? this : (-1) * this
- },
- gridLineWidth: 0
- }];
- this.yAxis = [{
- type: "category",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- gridLineWidth: 0,
- position: "left"
- }];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- var tmp = obj.x;
- obj.x = obj.y;
- obj.y = tmp;
- self.fireEvent(BI.BarChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this;
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- formatCordon();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
-
- //分类轴
- config.yAxis = this.yAxis;
- config.yAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
- config.yAxis[0].title.rotation = this.constants.ROTATION;
- BI.extend(config.yAxis[0], {
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- labelRotation: this.config.textDirection,
- enableTick: this.config.enableTick,
- lineWidth: this.config.lineWidth,
- maxWidth: '40%'
- });
-
- //值轴
- self.formatNumberLevelInXaxis(items, this.config.leftYAxisNumberLevel);
- config.xAxis[0].title.text = getXAxisTitle(this.config.leftYAxisNumberLevel, this.constants.X_AXIS);
- config.xAxis[0].title.align = "center";
- BI.extend(config.xAxis[0], {
- formatter: self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators),
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- enableTick: this.config.enableTick,
- showLabel: this.config.showLabel,
- lineWidth: this.config.lineWidth,
- enableMinorTick: this.config.enableMinorTick
- });
- config.chartType = "bar";
-
- this.formatDataLabelForAxis(config.plotOptions.dataLabels.enabled, items, config.xAxis[0].formatter, this.config.chartFont);
-
- config.plotOptions.tooltip.formatter.valueFormat = config.xAxis[0].formatter;
-
- //全局样式的图表文字
- this.setFontStyle(this.config.chartFont, config);
-
- return [items, config];
-
- function formatChartStyle() {
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatCordon() {
- BI.each(self.config.cordon, function (idx, cor) {
- if (idx === 0 && self.xAxis.length > 0) {
- var magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if (idx > 0 && self.yAxis.length >= idx) {
- var magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.xAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- }
-
- function getXAxisTitle(numberLevelType, position) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if (position === self.constants.X_AXIS) {
- self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
- }
- if (position === self.constants.LEFT_AXIS) {
- self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
- }
- unit = unit === "" ? unit : "(" + unit + ")";
-
- return self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + unit : unit;
- }
- },
-
- _formatItems: function (items) {
- BI.each(items, function (idx, item) {
- BI.each(item, function (id, it) {
- BI.each(it.data, function (i, t) {
- var tmp = t.x;
- t.x = t.y;
- t.y = tmp;
- })
- });
- });
- return items;
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- chartColor: options.chartColor || [],
- chartStyle: options.chartStyle || c.STYLE_NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- xAxisStyle: options.xAxisStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- leftYAxisReversed: options.leftYAxisReversed || false,
- xAxisNumberLevel: options.xAxisNumberLevel || c.NORMAL,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- showZoom: options.showZoom || false,
- textDirection: options.textDirection || 0,
- cordon: options.cordon || [],
- lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
- showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
- enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
- enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
- numSeparators: options.numSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE
- };
- this.options.items = items;
- var types = [];
- BI.each(items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function (id, item) {
- type.push(BICst.WIDGET.BAR);
- });
- types.push(type);
- });
- this.combineChart.populate(this._formatItems(items), types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.BarChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.bar_chart', BI.BarChart);/**
- * 图表控件
- * @class BI.BubbleChart
- * @extends BI.Widget
- */
-BI.BubbleChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.BubbleChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-bubble-chart"
- })
- },
-
- _init: function () {
- BI.BubbleChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.xAxis = [{
- type: "value",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- position: "bottom",
- gridLineWidth: 0
- }];
- this.yAxis = [{
- type: "value",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- position: "left",
- gridLineWidth: 0
- }];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.BubbleChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this, o = this.options;
- delete config.zoom;
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- formatCordon();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.plotOptions.dataLabels.formatter.identifier = "${X}${Y}${SIZE}";
- config.plotOptions.shadow = this.config.bubbleStyle !== this.constants.NO_PROJECT;
- config.yAxis = this.yAxis;
-
- config.yAxis[0].formatter = self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators);
- formatNumberLevelInYaxis(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
- config.yAxis[0].title.text = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
- config.yAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + config.yAxis[0].title.text : config.yAxis[0].title.text;
- config.yAxis[0].gridLineWidth = this.config.showGridLine === true ? 1 : 0;
- config.yAxis[0].lineWidth = 1;
- config.yAxis[0].title.rotation = this.constants.ROTATION;
- config.yAxis[0].maxWidth = '40%';
-
- config.xAxis[0].formatter = self.formatTickInXYaxis(this.config.xAxisStyle, this.config.xAxisNumberLevel, this.config.rightNumSeparators);
- self.formatNumberLevelInXaxis(items, this.config.xAxisNumberLevel);
- config.xAxis[0].title.text = getXYAxisUnit(this.config.xAxisNumberLevel, this.constants.X_AXIS);
- config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle + config.xAxis[0].title.text : config.xAxis[0].title.text;
- config.xAxis[0].title.align = "center";
- config.xAxis[0].gridLineWidth = this.config.showGridLine === true ? 1 : 0;
- config.xAxis[0].maxHeith = '40%';
- config.chartType = "bubble";
-
- if (BI.isNotEmptyArray(this.config.tooltip)) {
- config.plotOptions.bubble.tooltip = {
- useHtml: true,
- style: {
- color: 'RGB(184, 184, 184)'
- },
- formatter: function () {
- var y = self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)(this.y);
- var x = self.formatTickInXYaxis(self.config.xAxisStyle, self.config.xAxisNumberLevel, self.config.rightNumSeparators)(this.x);
- return this.seriesName + '
(X)' + self.config.tooltip[0] + ':' + x + '
(Y)' + self.config.tooltip[1]
- + ':' + y + '
(' + BI.i18nText("BI-Size") + ')' + self.config.tooltip[2] + ':' + this.size + '
'}
- };
- }
-
- //为了给数据标签加个%,还要遍历所有的系列,唉
- if (config.plotOptions.dataLabels.enabled === true) {
- BI.each(items, function (idx, item) {
- item.dataLabels = {
- "style" : self.config.chartFont,
- "align": "outside",
- "autoAdjust": true,
- enabled: true,
- formatter: {
- identifier: "${X}${Y}${SIZE}",
- "XFormat": function () {
- return BI.contentFormat(arguments[0], '#.##;-#.##')
- },
- "YFormat": function () {
- return BI.contentFormat(arguments[0], '#.##;-#.##')
- },
- "sizeFormat": function () {
- return BI.contentFormat(arguments[0], '#.##;-#.##')
- }
- }
- };
- item.dataLabels.formatter.XFormat = config.xAxis[0].formatter;
- item.dataLabels.formatter.YFormat = config.yAxis[0].formatter;
- });
- }
-
- //全局样式图表文字
- config.yAxis[0].title.style = config.yAxis[0].labelStyle = this.config.chartFont;
- config.xAxis[0].title.style = config.xAxis[0].labelStyle = this.config.chartFont;
- config.legend.style = this.config.chartFont;
-
- return [items, config];
-
- function formatChartStyle() {
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatCordon() {
- BI.each(self.config.cordon, function (idx, cor) {
- if (idx === 0 && self.xAxis.length > 0) {
- var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if (idx > 0 && self.yAxis.length >= idx) {
- var magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- }
-
- function formatNumberLevelInYaxis(type, position) {
- var magnify = self.calcMagnify(type);
- BI.each(items, function (idx, item) {
- BI.each(item.data, function (id, da) {
- if (position === item.yAxis) {
- da.y = self.formatXYDataWithMagnify(da.y, magnify);
- }
- })
- });
- if (type === BICst.TARGET_STYLE.NUM_LEVEL.PERCENT) {
- //config.plotOptions.tooltip.formatter.valueFormat = "function(){return window.FR ? FR.contentFormat(arguments[0], '#0%') : arguments[0]}";
- }
- }
-
- function getXYAxisUnit(numberLevelType, position) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if (position === self.constants.X_AXIS) {
- self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
- }
- if (position === self.constants.LEFT_AXIS) {
- self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
- }
- if (position === self.constants.RIGHT_AXIS) {
- self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
- }
- return unit === "" ? unit : "(" + unit + ")";
- }
- },
-
- _formatItems: function (items) {
- BI.each(items, function (idx, item) {
- BI.each(item, function (id, it) {
- BI.each(it.data, function (i, da) {
- var data = da.size;
- da.size = BI.contentFormat(data, '#.##;-#.##')
- })
- })
- });
- return items;
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- chartColor: options.chartColor || [],
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- xAxisStyle: options.xAxisStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- xAxisNumberLevel: options.xAxisNumberLevel || c.NORMAL,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- cordon: options.cordon || [],
- tooltip: options.tooltip || [],
- bubbleStyle: options.bubbleStyle || c.NO_PROJECT,
- numSeparators: options.numSeparators || false,
- rightNumSeparators: options.rightNumSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE
- };
- this.options.items = items;
- var types = [];
- BI.each(items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function (id, item) {
- type.push(BICst.WIDGET.BUBBLE);
- });
- types.push(type);
- });
- this.combineChart.populate(this._formatItems(items), types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.BubbleChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.bubble_chart', BI.BubbleChart);
-/**
- * 图表控件
- * @class BI.CompareAreaChart
- * @extends BI.Widget
- */
-BI.CompareAreaChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.CompareAreaChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-compare-area-chart"
- })
- },
-
- _init: function () {
- BI.CompareAreaChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.xAxis = [{
- type: "category",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- position: "bottom",
- gridLineWidth: 0
- }];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.CompareAreaChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this;
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- formatChartLineStyle();
- formatCordon();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.plotOptions.connectNulls = this.config.nullContinue;
- config.dataSheet.enabled = this.config.showDataTable;
- config.xAxis[0].showLabel = !config.dataSheet.enabled;
- config.zoom.zoomTool.enabled = this.config.showZoom;
- if (this.config.showZoom === true) {
- delete config.dataSheet;
- delete config.zoom.zoomType;
- }
-
- config.yAxis = this.yAxis;
- BI.each(config.yAxis, function (idx, axis) {
- var title = "";
- switch (axis.axisIndex) {
- case self.constants.LEFT_AXIS:
- title = getXYAxisUnit(self.config.leftYAxisNumberLevel, self.constants.LEFT_AXIS);
- axis.title.rotation = self.constants.ROTATION;
- axis.title.text = self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + title : title;
- BI.extend(axis, {
- reversed: false,
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)
- });
- formatNumberLevelInYaxis(self.config.leftYAxisNumberLevel, idx, axis.formatter);
- break;
- case self.constants.RIGHT_AXIS:
- title = getXYAxisUnit(self.config.rightYAxisNumberLevel, self.constants.RIGHT_AXIS);
- axis.title.rotation = self.constants.ROTATION;
- axis.title.text = self.config.showRightYAxisTitle === true ? self.config.rightYAxisTitle + title : title;
- BI.extend(axis, {
- reversed: true,
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators)
- });
- formatNumberLevelInYaxis(self.config.rightYAxisNumberLevel, idx, axis.formatter);
- break;
- }
- var res = _calculateValueNiceDomain(0, self.maxes[idx]);
- axis.max = res[1].mul(2);
- axis.min = res[0].mul(2);
- axis.tickInterval = BI.parseFloat((BI.parseFloat(axis.max).sub(BI.parseFloat(axis.min)))).div(5);
- });
-
- config.xAxis[0].title.align = "center";
- config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
- BI.extend(config.xAxis[0], {
- lineWidth: this.config.lineWidth,
- enableTick: this.config.enableTick,
- labelRotation: this.config.textDirection,
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- maxHeight: '40%'
- });
-
- config.chartType = "area";
-
- //为了给数据标签加个%,还要遍历所有的系列,唉
- this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
-
- //全局样式的图表文字
- this.setFontStyle(this.config.chartFont, config);
-
- return [items, config];
-
- function _calculateValueNiceDomain(minValue, maxValue) {
-
- minValue = Math.min(0, minValue);
-
- var tickInterval = _linearTickInterval(minValue, maxValue);
-
- return _linearNiceDomain(minValue, maxValue, tickInterval);
- }
-
- function _linearTickInterval(minValue, maxValue, m) {
-
- m = m || 5;
- var span = maxValue - minValue;
- var step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10));
- var err = m / span * step;
-
- if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
-
- return step;
- }
-
- function _linearNiceDomain(minValue, maxValue, tickInterval) {
-
- minValue = VanUtils.accMul(Math.floor(minValue / tickInterval), tickInterval);
-
- maxValue = VanUtils.accMul(Math.ceil(maxValue / tickInterval), tickInterval);
-
- return [minValue, maxValue];
- }
-
- function formatChartStyle() {
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatCordon() {
- BI.each(self.config.cordon, function (idx, cor) {
- if (idx === 0 && self.xAxis.length > 0) {
- var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style": self.config.chartFont,
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if (idx > 0 && self.yAxis.length >= idx) {
- var magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style": self.config.chartFont,
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- }
-
- function formatChartLineStyle() {
- switch (self.config.chartLineType) {
- case BICst.CHART_SHAPE.RIGHT_ANGLE:
- config.plotOptions.area = {
- curve: false,
- step: true
- };
- break;
- case BICst.CHART_SHAPE.CURVE:
- config.plotOptions.area = {
- curve: true,
- step: false
- };
- break;
- case BICst.CHART_SHAPE.NORMAL:
- default:
- config.plotOptions.area = {
- curve: false,
- step: false
- };
- break;
- }
- }
-
- function formatNumberLevelInYaxis(type, position, formatter) {
- var magnify = self.calcMagnify(type);
- BI.each(items, function (idx, item) {
- var max = null;
- BI.each(item.data, function (id, da) {
- if (position === item.yAxis) {
- da.y = self.formatXYDataWithMagnify(da.y, magnify);
- if ((BI.isNull(max) || BI.parseFloat(da.y) > BI.parseFloat(max))) {
- max = da.y;
- }
- }
- });
- if (position === item.yAxis) {
- item.tooltip = BI.deepClone(config.plotOptions.tooltip);
- item.tooltip.formatter.valueFormat = formatter;
- }
- if (BI.isNotNull(max)) {
- self.maxes.push(max);
- }
- });
- }
-
- function getXYAxisUnit(numberLevelType, position) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if (position === self.constants.X_AXIS) {
- self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
- }
- if (position === self.constants.LEFT_AXIS) {
- self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
- }
- if (position === self.constants.RIGHT_AXIS) {
- self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
- }
- return unit === "" ? unit : "(" + unit + ")";
- }
- },
-
- _formatItems: function (items) {
- var self = this;
- this.maxes = [];
- BI.each(items, function (idx, item) {
- BI.each(item, function (id, it) {
- if (idx > 0) {
- BI.extend(it, {reversed: true, xAxis: 0});
- } else {
- BI.extend(it, {reversed: false, xAxis: 1});
- }
- });
- });
- return items;
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- rightYAxisTitle: options.rightYAxisTitle || "",
- chartColor: options.chartColor || [],
- chartStyle: options.chartStyle || c.NORMAL,
- chartLineType: options.chartLineType || c.NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- showRightYAxisTitle: options.showRightYAxisTitle || false,
- leftYAxisReversed: options.leftYAxisReversed || false,
- rightYAxisReversed: options.rightYAxisReversed || false,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- rightYAxisUnit: options.rightYAxisUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showDataTable: options.showDataTable || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- showZoom: options.showZoom || false,
- textDirection: options.textDirection || 0,
- cordon: options.cordon || [],
- lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
- showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
- enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
- enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
- numSeparators: options.numSeparators || false,
- rightNumSeparators: options.rightNumSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE,
- nullContinue: options.nullContinue || false
- };
- this.options.items = items;
-
- var types = [];
- BI.each(items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function (id, item) {
- type.push(BICst.WIDGET.AREA);
- });
- types.push(type);
- });
-
- this.yAxis = [];
- BI.each(types, function (idx, type) {
- if (BI.isEmptyArray(type)) {
- return;
- }
- var newYAxis = {
- type: "value",
- title: {
- style: self.constants.FONT_STYLE
- },
- labelStyle: self.constants.FONT_STYLE,
- position: idx > 0 ? "right" : "left",
- lineWidth: 1,
- axisIndex: idx,
- gridLineWidth: 0
- };
- self.yAxis.push(newYAxis);
- });
-
- this.combineChart.populate(this._formatItems(items), types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.CompareAreaChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.compare_area_chart', BI.CompareAreaChart);/**
- * 图表控件
- * @class BI.CompareAxisChart
- * @extends BI.Widget
- */
-BI.CompareAxisChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.CompareAxisChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-compare-axis-chart"
- })
- },
-
- _init: function () {
- BI.CompareAxisChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.xAxis = [{
- type: "category",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- position: "bottom",
- gridLineWidth: 0
- }, {
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- position: "top",
- gridLineWidth: 0,
- type: "category",
- showLabel: false
- }];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.CompareAxisChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function(config, items){
- var self = this, o = this.options;
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- formatChartLineStyle();
- formatCordon();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.dataSheet.enabled = this.config.showDataTable;
- config.xAxis[0].showLabel = !config.dataSheet.enabled;
- config.zoom.zoomTool.enabled = this.config.showZoom;
- if(this.config.showZoom === true){
- delete config.dataSheet;
- delete config.zoom.zoomType;
- }
-
- config.yAxis = this.yAxis;
- BI.each(config.yAxis, function(idx, axis){
- var unit = '';
- switch (axis.axisIndex){
- case self.constants.LEFT_AXIS:
- unit = getXYAxisUnit(self.config.leftYAxisNumberLevel, self.constants.LEFT_AXIS);
- axis.title.rotation = self.constants.ROTATION;
- axis.title.text = self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + unit : unit;
- BI.extend(axis, {
- reversed: false,
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)
- });
- formatNumberLevelInYaxis(self.config.leftYAxisNumberLevel, idx, axis.formatter);
- break;
- case self.constants.RIGHT_AXIS:
- unit = getXYAxisUnit(self.config.rightYAxisNumberLevel, self.constants.RIGHT_AXIS);
- axis.title.rotation = self.constants.ROTATION;
- axis.title.text = self.config.showRightYAxisTitle === true ? self.config.rightYAxisTitle + unit : unit;
- BI.extend(axis, {
- reversed: true,
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators)
- });
- formatNumberLevelInYaxis(self.config.rightYAxisNumberLevel, idx, axis.formatter);
- break;
- }
- var res = _calculateValueNiceDomain(0, self.maxes[idx]);
- axis.max = res[1].mul(2);
- axis.min = res[0].mul(2);
- axis.tickInterval = BI.parseFloat((BI.parseFloat(axis.max).sub(BI.parseFloat(axis.min)))).div(5);
- });
-
- config.xAxis[0].title.align = "center";
- config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
- BI.extend(config.xAxis[0], {
- lineWidth: this.config.lineWidth,
- enableTick: this.config.enableTick,
- labelRotation: this.config.textDirection,
- enableMinorTick: this.config.enableMinorTick,
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- maxHeight: '40%'
- });
-
- BI.extend(config.xAxis[1], {
- lineWidth: this.config.lineWidth,
- enableTick: this.config.enableTick,
- enableMinorTick: this.config.enableMinorTick
- });
-
- //为了给数据标签加个%,还要遍历所有的系列,唉
- this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
-
- //全局样式的图表文字
- this.setFontStyle(this.config.chartFont, config);
-
- return [items, config];
-
- function formatChartStyle(){
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatCordon(){
- BI.each(self.config.cordon, function(idx, cor){
- if(idx === 0 && self.xAxis.length > 0){
- var magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function(i, t){
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if(idx > 0 && self.yAxis.length >= idx){
- var magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function(i, t){
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- }
-
- function formatChartLineStyle(){
- switch (self.config.chartLineType) {
- case BICst.CHART_SHAPE.RIGHT_ANGLE:
- config.plotOptions.curve = false;
- config.plotOptions.step = true;
- break;
- case BICst.CHART_SHAPE.CURVE:
- config.plotOptions.curve = true;
- config.plotOptions.step = false;
- break;
- case BICst.CHART_SHAPE.NORMAL:
- default:
- config.plotOptions.curve = false;
- config.plotOptions.step = false;
- break;
- }
- }
-
- function formatNumberLevelInYaxis(type, position, formatter){
- var magnify = self.calcMagnify(type);
- BI.each(items, function (idx, item) {
- var max = null;
- BI.each(item.data, function (id, da) {
- if (position === item.yAxis) {
- da.y = self.formatXYDataWithMagnify(da.y, magnify);
- if((BI.isNull(max) || BI.parseFloat(da.y) > BI.parseFloat(max))){
- max = da.y;
- }
- }
- });
- if(position === item.yAxis){
- item.tooltip = BI.deepClone(config.plotOptions.tooltip);
- item.tooltip.formatter.valueFormat = formatter;
- }
- if(BI.isNotNull(max)){
- self.maxes.push(max);
- }
- });
- }
-
- function getXYAxisUnit(numberLevelType, position){
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if(position === self.constants.X_AXIS){
- self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
- }
- if(position === self.constants.LEFT_AXIS){
- self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
- }
- if(position === self.constants.RIGHT_AXIS){
- self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
- }
- return unit === "" ? unit : "(" + unit + ")";
- }
-
- function _calculateValueNiceDomain(minValue, maxValue){
-
- minValue = Math.min(0, minValue);
-
- var tickInterval = _linearTickInterval(minValue, maxValue);
-
- return _linearNiceDomain(minValue, maxValue, tickInterval);
- }
-
- function _linearTickInterval(minValue, maxValue, m){
-
- m = m || 5;
- var span = maxValue - minValue;
- var step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10));
- var err = m / span * step;
-
- if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
-
- return step;
- }
-
- function _linearNiceDomain(minValue, maxValue, tickInterval){
-
- minValue = VanUtils.accMul(Math.floor(minValue / tickInterval), tickInterval);
-
- maxValue = VanUtils.accMul(Math.ceil(maxValue / tickInterval), tickInterval);
-
- return [minValue, maxValue];
- }
- },
-
- _formatItems: function(items){
- var self = this;
- this.maxes = [];
- BI.each(items, function(idx, item){
- BI.each(item, function(id, it){
- if(idx > 0){
- BI.extend(it, {reversed: true, xAxis: 1});
- }else{
- BI.extend(it, {reversed: false, xAxis: 0});
- }
- });
- });
- return items;
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- rightYAxisTitle: options.rightYAxisTitle || "",
- chartColor: options.chartColor || [],
- chartStyle: options.chartStyle || c.NORMAL,
- chartLineType: options.chartLineType || c.NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- showRightYAxisTitle: options.showRightYAxisTitle || false,
- leftYAxisReversed: options.leftYAxisReversed || false,
- rightYAxisReversed: options.rightYAxisReversed || false,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- rightYAxisUnit: options.rightYAxisUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showDataTable: options.showDataTable || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- showZoom: options.showZoom || false,
- textDirection: options.textDirection || 0,
- cordon: options.cordon || [],
- lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
- showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
- enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
- enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
- numSeparators: options.numSeparators || false,
- rightNumSeparators: options.rightNumSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE
- };
- this.options.items = items;
-
- this.yAxis = [];
-
- var types = [];
- BI.each(items, function(idx, axisItems){
- var type = [];
- BI.each(axisItems, function(id, item){
- type.push(BICst.WIDGET.AXIS);
- });
- types.push(type);
- });
-
- BI.each(types, function(idx, type){
- if(BI.isEmptyArray(type)){
- return;
- }
- var newYAxis = {
- type: "value",
- title: {
- style: self.constants.FONT_STYLE
- },
- labelStyle: self.constants.FONT_STYLE,
- position: idx > 0 ? "right" : "left",
- lineWidth: 1,
- axisIndex: idx,
- gridLineWidth: 0,
- reversed: idx > 0
- };
- self.yAxis.push(newYAxis);
- });
-
- this.combineChart.populate(this._formatItems(items), types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function(){
- this.combineChart.magnify();
- }
-});
-BI.CompareAxisChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.compare_axis_chart', BI.CompareAxisChart);/**
- * 图表控件
- * @class BI.CompareBarChart
- * @extends BI.Widget
- */
-BI.CompareBarChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.CompareBarChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-compare-bar-chart"
- })
- },
-
- _init: function () {
- BI.CompareBarChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.xAxis = [{
- type: "value",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- formatter: function () {
- return this > 0 ? this : (-1) * this;
- },
- gridLineWidth: 0
- }];
- this.yAxis = [{
- type: "category",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- gridLineWidth: 0,
- position: "left"
- }];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.CompareBarChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this, o = this.options;
- var yTitle = getXYAxisUnit(this.config.xAxisNumberLevel, this.constants.LEFT_AXIS);
- var xTitle = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.X_AXIS);
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- formatCordon();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
-
- config.yAxis = this.yAxis;
- config.yAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle + yTitle : yTitle;
- config.yAxis[0].title.rotation = this.constants.ROTATION;
- BI.extend(config.yAxis[0], {
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- lineWidth: this.config.lineWidth,
- enableTick: this.config.enableTick,
- labelRotation: this.config.textDirection,
- maxWidth: '40%'
- });
-
- self.formatNumberLevelInXaxis(items, this.config.leftYAxisNumberLevel);
- config.xAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + xTitle : xTitle;
- config.xAxis[0].title.align = "center";
- BI.extend(config.xAxis[0], {
- formatter: self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators, true),
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- lineWidth: this.config.lineWidth,
- showLabel: this.config.showLabel,
- enableTick: this.config.enableTick,
- enableMinorTick: this.config.enableMinorTick
- });
-
- config.chartType = "bar";
- //为了给数据标签加个%,还要遍历所有的系列,唉
- this.formatDataLabelForAxis(config.plotOptions.dataLabels.enabled, items, config.xAxis[0].formatter, this.config.chartFont);
-
- config.plotOptions.tooltip.formatter.valueFormat = config.xAxis[0].formatter;
-
- //全局样式的图表文字
- this.setFontStyle(this.config.chartFont, config);
-
- return [items, config];
-
- function formatChartStyle() {
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatCordon() {
- BI.each(self.config.cordon, function (idx, cor) {
- if (idx === 0 && self.xAxis.length > 0) {
- var magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if (idx > 0 && self.yAxis.length >= idx) {
- var magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.xAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- }
-
- function getXYAxisUnit(numberLevelType, position) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if (position === self.constants.X_AXIS) {
- self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
- }
- if (position === self.constants.LEFT_AXIS) {
- self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
- }
- if (position === self.constants.RIGHT_AXIS) {
- self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
- }
- return unit === "" ? unit : "(" + unit + ")";
- }
- },
-
- _formatItems: function (items) {
- var result = [];
- var i = BI.UUID();
- BI.each(items, function (idx, item) {
- BI.each(item, function (id, it) {
- BI.each(it.data, function (i, t) {
- var tmp = t.x;
- t.x = t.y;
- t.y = tmp;
- if (idx === 0) {
- t.x = -t.x;
- }
- });
- it.stack = i;
- })
- });
- BI.each(items, function (idx, item) {
- result = BI.concat(result, item);
- });
- return [result];
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- chartColor: options.chartColor || [],
- chartStyle: options.chartStyle || c.STYLE_NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- xAxisStyle: options.xAxisStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- leftYAxisReversed: options.leftYAxisReversed || false,
- xAxisNumberLevel: options.xAxisNumberLevel || c.NORMAL,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showDataTable: options.showDataTable || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- showZoom: options.showZoom || false,
- textDirection: options.textDirection || 0,
- cordon: options.cordon || [],
- lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
- showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
- enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
- enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
- numSeparators: options.numSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE
- };
- this.options.items = this._formatItems(items);
- var types = [];
- BI.each(this.options.items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function (id, item) {
- type.push(BICst.WIDGET.BAR);
- });
- types.push(type);
- });
- this.combineChart.populate(this.options.items, types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.CompareBarChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.compare_bar_chart', BI.CompareBarChart);/**
- * 图表控件
- * @class BI.DashboardChart
- * @extends BI.Widget
- */
-BI.DashboardChart = BI.inherit(BI.AbstractChart, {
-
-
- _defaultConfig: function () {
- return BI.extend(BI.DashboardChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-dashboard-chart"
- })
- },
-
- _init: function () {
- BI.DashboardChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.gaugeAxis = [{
- "minorTickColor": "rgb(226,226,226)",
- "tickColor": "rgb(186,186,186)",
- labelStyle: this.constants.FONT_STYLE,
- "step": 0,
- "showLabel": true
- }];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.DashboardChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this, o = this.options;
- var isDashboard = BI.contains([self.constants.NORMAL, self.constants.HALF_DASHBOARD], self.config.chartDashboardType);
- var isMultiPointers = self.config.numberOfPointer === self.constants.MULTI_POINTER;
- formatChartDashboardStyle();
- config.chartType = "gauge";
- delete config.zoom;
- delete config.xAxis;
- delete config.yAxis;
- if (isDashboard && !isMultiPointers) {
- config.plotOptions.seriesLabel.enabled = false;
- if(BI.isNull(items[0].data[0].z)) {
- config.plotOptions.tooltip.formatter.identifier = "${SERIES}${X}${Y}${SIZE}${VALUE}"
- }
- }
- config.gaugeAxis[0].labelStyle = this.config.chartFont;
- return [items, config];
-
- function formatChartDashboardStyle() {
- var bands = getBandsStyles(self.config.bandsStyles, self.config.autoCustomStyle);
- var percentageLabel = BI.extend(config.plotOptions.percentageLabel, {
- enabled: self.config.showPercentage === BICst.PERCENTAGE.SHOW
- });
-
- config.gaugeAxis = self.gaugeAxis;
- var slotValueLAbel = {
- enabled: true,
- formatter: function () {
- var value = this.value;
- if (self.config.dashboardNumberLevel === BICst.TARGET_STYLE.NUM_LEVEL.PERCENT && self.config.numSeparators) {
- value = BI.contentFormat(this.value, "#,##0%;-#,##0%")
- } else if (self.config.dashboardNumberLevel === BICst.TARGET_STYLE.NUM_LEVEL.PERCENT && !self.config.numSeparators) {
- value = BI.contentFormat(this.value, "#0.00%");
- } else if (!(self.config.dashboardNumberLevel === BICst.TARGET_STYLE.NUM_LEVEL.PERCENT) && self.config.numSeparators) {
- value = BI.contentFormat(this.value, "#,###.##;-#,###.##")
- } else {
- value = BI.contentFormat(this.value, "#.##;-#.##");
- }
-
- var label = '
' + this.seriesName + '
' + '
' + value +
- getXYAxisUnit(self.config.dashboardNumberLevel, self.constants.DASHBOARD_AXIS) + '
';
-
- if (isDashboard && items[0].data.length > 1) {
- if (isMultiPointers) {
- return '
' + this.seriesName + ':' + value +
- getXYAxisUnit(self.config.dashboardNumberLevel, self.constants.DASHBOARD_AXIS) + '
';
- }
- return label
- } else if (isDashboard && BI.isNull(items[0].data[0].z)) {
- return label
- }
-
- return '
' + this.category + '
' + label;
- },
- style: self.config.chartFont,
- useHtml: true
- };
- switch (self.config.chartDashboardType) {
- case BICst.CHART_SHAPE.HALF_DASHBOARD:
- setPlotOptions("pointer_semi", bands, slotValueLAbel, percentageLabel);
- break;
- case BICst.CHART_SHAPE.PERCENT_DASHBOARD:
- setPlotOptions("ring", bands, slotValueLAbel, percentageLabel);
- break;
- case BICst.CHART_SHAPE.PERCENT_SCALE_SLOT:
- setPlotOptions("slot", bands, slotValueLAbel, percentageLabel);
- break;
- case BICst.CHART_SHAPE.HORIZONTAL_TUBE:
- BI.extend(slotValueLAbel, {
- align: "bottom"
- });
- BI.extend(percentageLabel, {
- align: "bottom"
- });
- setPlotOptions("thermometer", bands, slotValueLAbel, percentageLabel, "horizontal", "vertical");
- break;
- case BICst.CHART_SHAPE.VERTICAL_TUBE:
- BI.extend(slotValueLAbel, {
- align: "left"
- });
- BI.extend(percentageLabel, {
- align: "left"
- });
- setPlotOptions("thermometer", bands, slotValueLAbel, percentageLabel, "vertical", "horizontal");
- break;
- case BICst.CHART_SHAPE.NORMAL:
- default:
- setPlotOptions("pointer", bands, slotValueLAbel, percentageLabel);
- break;
- }
- changeMaxMinScale();
- formatNumberLevelInYaxis(self.config.dashboardNumberLevel, self.constants.LEFT_AXIS);
- if (self.config.dashboardNumberLevel === BICst.TARGET_STYLE.NUM_LEVEL.PERCENT) {
- config.gaugeAxis[0].formatter = function () {
- var scaleValue = this;
- if (self.config.numSeparators) {
- scaleValue = BI.contentFormat(scaleValue, '#,##0%;-#,##0%')
- } else {
- scaleValue = BI.contentFormat(scaleValue, '#0.00%')
- }
- return scaleValue + getXYAxisUnit(self.config.dashboardNumberLevel, self.constants.DASHBOARD_AXIS);
- };
- } else {
- config.gaugeAxis[0].formatter = function () {
- var value = this;
- if (self.config.numSeparators) {
- value = BI.contentFormat(value, "#,###;-#,###")
- }
- return value + getXYAxisUnit(self.config.dashboardNumberLevel, self.constants.DASHBOARD_AXIS);
- };
- }
- }
-
- function setPlotOptions(style, bands, slotValueLAbel, percentageLabel, thermometerLayout, layout) {
- config.style = style;
- config.plotOptions.bands = bands;
- config.plotOptions.valueLabel = slotValueLAbel;
- config.plotOptions.percentageLabel = percentageLabel;
- config.plotOptions.thermometerLayout = thermometerLayout;
- config.plotOptions.layout = layout;
- }
-
- function changeMaxMinScale() {
- self.gaugeAxis[0].min = BI.parseFloat(self.config.minScale) || null;
- self.gaugeAxis[0].max = BI.parseFloat(self.config.maxScale) || null;
- }
-
- function formatNumberLevelInYaxis(type, position) {
- var magnify = self.calcMagnify(type);
- BI.each(items, function (idx, item) {
- BI.each(item.data, function (id, da) {
- if (position === item.yAxis) {
- da.y = self.formatXYDataWithMagnify(da.y, magnify);
- }
- })
- });
-
- config.plotOptions.tooltip.formatter.valueFormat = function () {
- return BI.contentFormat(this, '#.##;-#.##') + getXYAxisUnit(type, position)
- };
-
- if (self.config.numSeparators) {
- config.plotOptions.tooltip.formatter.valueFormat = function () {
- return BI.contentFormat(arguments[0], '#,###.##;-#,###.##')
- };
- }
-
- if (type === BICst.TARGET_STYLE.NUM_LEVEL.PERCENT) {
- config.plotOptions.tooltip.formatter.valueFormat = function () {
- return BI.contentFormat(arguments[0], '#0.00%')
- };
- if (self.config.numSeparators) {
- config.plotOptions.tooltip.formatter.valueFormat = function () {
- return BI.contentFormat(arguments[0], '#,##0%;-#,##0%')
- };
- }
- }
- }
-
- function getXYAxisUnit(numberLevelType, position) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if (position === self.constants.DASHBOARD_AXIS) {
- self.config.dashboardUnit !== "" && (unit = unit + self.config.dashboardUnit)
- }
- return unit;
- }
-
- function getBandsStyles(styles, change) {
- var min = 0, bands = [], color = null, max = null, conditionMax = null;
-
- BI.each(items, function (idx, item) {
- var data = item.data[0];
- if ((BI.isNull(max) || data.y > max)) {
- max = data.y
- }
- });
-
- switch (change) {
-
- case BICst.SCALE_SETTING.AUTO:
- break;
- case BICst.SCALE_SETTING.CUSTOM:
- if (styles.length === 0) {
- return bands
- } else {
- var maxScale = _calculateValueNiceDomain(0, max)[1];
-
- BI.each(styles, function (idx, style) {
- if(BI.parseFloat(style.range.min) > BI.parseFloat(style.range.max)) {
- return bands.push({
- color: color,
- from: conditionMax,
- to: maxScale
- });
- }
- bands.push({
- color: style.color,
- from: style.range.min,
- to: style.range.max
- });
- color = style.color;
- conditionMax = style.range.max
- });
- min = BI.parseInt(styles[0].range.min);
- bands.push({
- color: "#808080",
- from: 0,
- to: min
- });
-
- bands.push({
- color: color,
- from: conditionMax,
- to: maxScale
- });
-
- return bands;
- }
- }
- }
-
- function _calculateValueNiceDomain(minValue, maxValue) {
- minValue = Math.min(0, minValue);
- var tickInterval = _linearTickInterval(minValue, maxValue);
-
- return _linearNiceDomain(minValue, maxValue, tickInterval);
- }
-
- function _linearTickInterval(minValue, maxValue, m) {
- m = m || 5;
- var span = maxValue - minValue;
- var step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10));
- var err = m / span * step;
- if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
-
- return step;
- }
-
- function _linearNiceDomain(minValue, maxValue, tickInterval) {
- minValue = VanUtils.accMul(Math.floor(minValue / tickInterval), tickInterval);
- maxValue = VanUtils.accMul(Math.ceil(maxValue / tickInterval), tickInterval);
-
- return [minValue, maxValue];
- }
- },
-
- _formatItems: function (items) {
- if (items.length === 0) {
- return [];
- }
- var c = this.constants;
- if (this.config.chartDashboardType === c.NORMAL || this.config.chartDashboardType === c.HALF_DASHBOARD) {
- var result = [];
- if (this.config.numberOfPointer === c.ONE_POINTER && items[0].length === 1) {//单个系列
- BI.each(items[0][0].data, function (idx, da) {
- result.push({
- data: [BI.extend({}, da, {
- x: items[0][0].name
- })],
- name: da.x
- })
- });
- return [result];
- } else if(this.config.numberOfPointer === c.ONE_POINTER && items[0].length > 1) {
- BI.each(items[0], function (idx, item) {
- result.push({
- data: [BI.extend(item.data[0], {
- x: item.name
- })],
- name: BI.UUID()
- })
- });
- return [result]
- }
- if (this.config.numberOfPointer === c.MULTI_POINTER && items[0].length > 1) {//多个系列
- BI.each(items, function (idx, item) {
- BI.each(item, function (id, it) {
- var data = it.data[0];
- data.x = it.name;
- result.push(data);
- })
- });
- return [[{
- data: result,
- name: ""
- }]];
- }
- } else {
- var others = [];
- if (BI.isNotNull(items[0][0].data[0].z)) {
- BI.each(items[0], function (idx, item) {
- BI.each(item.data, function (id, da) {
- others.push({
- data: [BI.extend({}, da, {
- x: item.name,
- y: da.y
- })],
- name: da.x
- })
- })
- });
- return [others];
- }
- }
- return items;
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants, o = this.options;
- this.config = {
- dashboardNumberLevel: options.dashboardNumberLevel || c.NORMAL,
- dashboardUnit: options.dashboardUnit || "",
- chartDashboardType: options.chartDashboardType || c.NORMAL,
- numberOfPointer: options.numberOfPointer || c.ONE_POINTER,
- bandsStyles: options.bandsStyles || [],
- autoCustomStyle: options.autoCustom || c.AUTO,
- minScale: options.minScale,
- maxScale: options.maxScale,
- showPercentage: options.showPercentage || c.NOT_SHOW,
- numSeparators: options.numSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE
- };
- o.items = this._formatItems(items);
- var types = [];
- BI.each(o.items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function (id, item) {
- type.push(BICst.WIDGET.DASHBOARD);
- });
- types.push(type);
- });
-
- this.combineChart.populate(o.items, types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.DashboardChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.dashboard_chart', BI.DashboardChart);/**
- * 图表控件
- * @class BI.DonutChart
- * @extends BI.Widget
- */
-BI.DonutChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.DonutChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-donut-chart"
- })
- },
-
- _init: function () {
- BI.DonutChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.DonutChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function(config, items){
- var self = this;
- delete config.zoom;
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
-
- this.formatChartLegend(config, this.config.chartLegend);
-
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
-
- config.plotOptions.innerRadius = "50.0%";
- config.chartType = "pie";
- config.plotOptions.dataLabels.align = "outside";
- config.plotOptions.dataLabels.connectorWidth = "outside";
- config.plotOptions.dataLabels.style = this.config.chartFont;
- config.plotOptions.dataLabels.formatter.identifier = "${VALUE}${PERCENT}";
- delete config.xAxis;
- delete config.yAxis;
- BI.each(items, function (idx, item) {
- BI.each(item.data, function (id, da) {
- da.y = self.formatXYDataWithMagnify(da.y, 1);
- })
- });
-
- config.legend.style = this.config.chartFont;
- return [items, config];
-
- function formatChartStyle(){
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- chartColor: options.chartColor || [],
- chartStyle: options.chartStyle || c.NORMAL,
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- chartFont: options.chartFont || c.FONT_STYLE
- };
- this.options.items = items;
-
- var types = [];
- BI.each(items, function(idx, axisItems){
- var type = [];
- BI.each(axisItems, function(id, item){
- type.push(BICst.WIDGET.DONUT);
- });
- types.push(type);
- });
-
- this.combineChart.populate(items, types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function(){
- this.combineChart.magnify();
- }
-});
-BI.DonutChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.donut_chart', BI.DonutChart);/**
- * 图表控件
- * @class BI.FallAxisChart
- * @extends BI.Widget
- */
-BI.FallAxisChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.FallAxisChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-fall-axis-chart"
- })
- },
-
- _init: function () {
- BI.FallAxisChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.xAxis = [{
- type: "category",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- position: "bottom",
- gridLineWidth: 0
- }];
- this.yAxis = [{
- type: "value",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- position: "left",
- gridLineWidth: 0
- }];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.FallAxisChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function(config, items){
- var self = this, o = this.options;
- var yTitle = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- formatCordon();
- config.legend.enabled = false;
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.dataSheet.enabled = this.config.showDataTable;
- if(config.dataSheet.enabled === true){
- config.xAxis[0].showLabel = false;
- }
- config.zoom.zoomTool.enabled = this.config.showZoom;
- if(this.config.showZoom === true){
- delete config.dataSheet;
- delete config.zoom.zoomType;
- }
-
- config.yAxis = this.yAxis;
- BI.extend(config.yAxis[0], {
- lineWidth: this.config.lineWidth,
- showLabel: this.config.showLabel,
- enableTick: this.config.enableTick,
- enableMinorTick: this.config.enableMinorTick,
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators)
- });
- formatNumberLevelInYaxis(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS, config.yAxis[0].formatter);
- config.yAxis[0].title.rotation = this.constants.ROTATION;
- config.yAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + yTitle : yTitle;
-
- config.xAxis[0].title.align = "center";
- config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
- BI.extend(config.xAxis[0], {
- lineWidth: this.config.lineWidth,
- enableTick: this.config.enableTick,
- enableMinorTick: this.config.enableMinorTick,
- labelRotation: this.config.textDirection,
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- maxHeight: '40%'
- });
-
- //为了给数据标签加个%,还要遍历所有的系列,唉
- if(config.plotOptions.dataLabels.enabled === true){
- BI.each(items, function(idx, item){
- if(idx === 0){
- item.dataLabels = {};
- return;
- }
- item.dataLabels = {
- "style": self.config.chartFont,
- "align": "outside",
- "autoAdjust": true,
- enabled: true,
- formatter: {
- identifier: "${VALUE}",
- valueFormat: config.yAxis[0].formatter
- }
- };
- });
- }
-
- //全局样式的图表文字
- this.setFontStyle(this.config.chartFont, config);
-
- return [items, config];
-
- function formatChartStyle(){
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatCordon(){
- BI.each(self.config.cordon, function(idx, cor){
- if(idx === 0 && self.xAxis.length > 0){
- var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function(i, t){
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style": self.config.chartFont,
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if(idx > 0 && self.yAxis.length >= idx){
- var magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function(i, t){
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style": self.config.chartFont,
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- }
-
- function formatNumberLevelInYaxis(type, position, formatter){
- var magnify = self.calcMagnify(type);
- BI.each(items, function (idx, item) {
- BI.each(item.data, function (id, da) {
- if (position === item.yAxis) {
- da.y = self.formatXYDataWithMagnify(da.y, magnify);
- }
- })
- });
- config.plotOptions.tooltip.formatter.valueFormat = formatter;
- }
-
- function getXYAxisUnit(numberLevelType, position){
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if(position === self.constants.X_AXIS){
- self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
- }
- if(position === self.constants.LEFT_AXIS){
- self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
- }
- if(position === self.constants.RIGHT_AXIS){
- self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
- }
- return unit === "" ? unit : "(" + unit + ")";
- }
- },
-
- _formatItems: function(items){
- var o = this.options;
- if(BI.isEmptyArray(items)){
- return [];
- }
- items = items[0];
- var tables = [], sum = 0;
- var colors = this.config.chartColor || [];
- if(BI.isEmptyArray(colors)){
- colors = ["rgb(152, 118, 170)", "rgb(0, 157, 227)"];
- }
- BI.each(items, function(idx, item){
- BI.each(item.data, function(i, t){
- if(t.y < 0){
- tables.push([t.x, t.y, sum + t.y, t]);
- }else{
- tables.push([t.x, t.y, sum, t]);
- }
- sum += t.y;
- });
- });
-
- return [BI.map(BI.makeArray(2, null), function(idx, item){
- return {
- "data": BI.map(tables, function(id, cell){
- var axis = BI.extend({}, cell[3], {
- x: cell[0],
- y: Math.abs(cell[2 - idx])
- });
- if(idx === 1){
- axis.color = cell[2 - idx] < 0 ? colors[1] : colors[0];
- }else{
- axis.color = "rgba(0,0,0,0)";
- axis.borderColor = "rgba(0,0,0,0)";
- axis.borderWidth = 0;
- axis.clickColor = "rgba(0,0,0,0)";
- axis.mouseOverColor = "rgba(0,0,0,0)";
- axis.tooltip = {
- enable: false
- }
- }
- return axis;
- }),
- stack: "stackedFall",
- name: idx === 1 ? items[0].name : BI.UUID()
- };
- })];
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- chartColor: options.chartColor || ["#5caae4", "#70cc7f", "#ebbb67", "#e97e7b", "#6ed3c9"],
- chartStyle: options.chartStyle || c.NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- showDataLabel: options.showDataLabel || false,
- showDataTable: options.showDataTable || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- showZoom: options.showZoom || false,
- textDirection: options.textDirection || 0,
- cordon: options.cordon || [],
- lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
- showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
- enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
- enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
- numSeparators: options.numSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE
- };
- this.options.items = items;
- var types = [];
- BI.each(items, function(idx, axisItems){
- var type = [];
- BI.each(axisItems, function(id, item){
- type.push(BICst.WIDGET.AXIS);
- });
- types.push(type);
- });
-
- this.combineChart.populate(this._formatItems(items), types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function(){
- this.combineChart.magnify();
- }
-});
-BI.FallAxisChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.fall_axis_chart', BI.FallAxisChart);/**
- * 图表控件
- * @class BI.ForceBubbleChart
- * @extends BI.Widget
- */
-BI.ForceBubbleChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.ForceBubbleChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-force-bubble-chart"
- })
- },
-
- _init: function () {
- BI.ForceBubbleChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.ForceBubbleChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this, o = this.options;
- config.chartType = 'forceBubble';
- config.colors = this.config.chartColor;
- this.formatChartLegend(config, this.config.chartLegend);
-
- config.plotOptions.force = true;
- config.plotOptions.shadow = this.config.bubbleStyle !== this.constants.NO_PROJECT;
- config.plotOptions.dataLabels.enabled = true;
- config.plotOptions.dataLabels.align = "inside";
- config.plotOptions.dataLabels.style = this.config.chartFont;
- config.plotOptions.dataLabels.formatter.identifier = "${CATEGORY}${VALUE}";
- delete config.xAxis;
- delete config.yAxis;
- delete config.zoom;
- BI.each(items, function (idx, item) {
- BI.each(item.data, function (id, da) {
- da.y = self.formatXYDataWithMagnify(da.y, 1);
- })
- });
- config.legend.style = this.config.chartFont;
- return [items, config];
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- chartColor: options.chartColor || [],
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- bubbleStyle: options.bubbleStyle || c.NO_PROJECT,
- chartFont: options.chartFont || c.FONT_STYLE
- };
- this.options.items = items;
-
- var types = [];
- BI.each(items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function (id, item) {
- type.push(BICst.WIDGET.FORCE_BUBBLE);
- });
- types.push(type);
- });
-
- this.combineChart.populate(items, types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.ForceBubbleChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.force_bubble_chart', BI.ForceBubbleChart);/**
- * 图表控件
- * @class BI.GISMapChart
- * @extends BI.Widget
- */
-BI.GISMapChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.GISMapChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-gis-map-chart"
- })
- },
-
- _init: function () {
- BI.GISMapChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.GISMapChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- delete config.dataSheet;
- delete config.legend;
- delete config.zoom;
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.plotOptions.dataLabels.useHtml = true;
- config.plotOptions.dataLabels.style = this.config.chartFont;
- config.plotOptions.dataLabels.formatter = function () {
- var name = (BI.isArray(this.name) ? '' : this.name + ',') + BI.contentFormat(this.value, '#.##;-#.##') ;
- var style = "padding: 5px; background-color: rgba(0,0,0,0.4980392156862745);border-color: rgb(0,0,0); border-radius:2px; border-width:0px;";
- var a = '
' + name + '
';
- return a;
- };
- config.plotOptions.tooltip.shared = true;
- config.plotOptions.tooltip.formatter = function () {
- var tip = BI.isArray(this.name) ? '' : this.name;
- BI.each(this.points, function (idx, point) {
- tip += ('
' + point.seriesName + ':' + BI.contentFormat((point.size || point.y), '#.##;-#.##') + '
');
- });
- return tip;
- };
- config.geo = {
- "tileLayer": "http://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
- "attribution": "
© 2016 AutoNavi"
- };
- if (this.config.showBackgroundLayer === true && BI.isNotNull(this.config.backgroundLayerInfo)) {
- config.geo = {};
- if (this.config.backgroundLayerInfo.type === BICst.WMS_SERVER) {
- config.geo.tileLayer = false;
- config.geo.wmsUrl = this.config.backgroundLayerInfo.url;
- config.geo.wmsLayer = this.config.backgroundLayerInfo.wmsLayer
- } else {
- config.geo.tileLayer = this.config.backgroundLayerInfo.url;
- }
- }
- config.chartType = "pointMap";
- config.plotOptions.icon = {
- iconUrl: BICst.GIS_ICON_PATH,
- iconSize: [24, 24]
- };
-
- config.plotOptions.marker = {
- symbol: BICst.GIS_ICON_PATH,
- width: 24,
- height: 24,
- enable: true
- };
- delete config.xAxis;
- delete config.yAxis;
- return [items, config];
-
- },
-
- _checkLngLatValid: function (lnglat) {
- if (lnglat.length < 2) {
- return false;
- }
- return lnglat[0] <= 180 && lnglat[0] >= -180 && lnglat[1] <= 90 && lnglat[1] >= -90;
- },
-
- _formatItems: function (items) {
- var self = this;
- var results = [];
- BI.each(items, function (idx, item) {
- var result = [];
- BI.each(item, function (id, it) {
- var res = [];
- BI.each(it.data, function (i, da) {
- da.y = self.formatXYDataWithMagnify(da.y, 1);
- var lnglat = da.x.split(",");
- if (self.config.lnglat === self.constants.LAT_FIRST) {
- var lng = lnglat[1];
- lnglat[1] = lnglat[0];
- lnglat[0] = lng;
- }
- da.lnglat = lnglat;
- da.value = da.y;
- da.name = BI.isNotNull(da.z) ? da.z : da.lnglat;
- if (self._checkLngLatValid(da.lnglat)) {
- res.push(da);
- }
- });
- if (BI.isNotEmptyArray(res)) {
- result.push(BI.extend(it, {
- data: res
- }));
- }
- });
- if (BI.isNotEmptyArray(result)) {
- results.push(result);
- }
- });
- return results;
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- lnglat: options.lnglat || c.LNG_FIRST,
- chartFont: options.chartFont || c.FONT_STYLE,
- showBackgroundLayer: options.showBackgroundLayer || false,
- backgroundLayerInfo: options.backgroundLayerInfo
- };
- this.options.items = items;
-
- var types = [];
- BI.each(items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function () {
- type.push(BICst.WIDGET.GIS_MAP);
- });
- types.push(type);
- });
-
- this.combineChart.populate(this._formatItems(items), types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.GISMapChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.gis_map_chart', BI.GISMapChart);/**
- * 图表控件
- * @class BI.LineChart
- * @extends BI.Widget
- */
-BI.LineChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.LineChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-line-chart"
- })
- },
-
- _init: function () {
- BI.LineChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.xAxis = [{
- type: "category",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- position: "bottom",
- gridLineWidth: 0
- }];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.LineChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this, o = this.options;
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- formatChartLineStyle();
- formatCordon();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.plotOptions.connectNulls = this.config.nullContinue;
- config.dataSheet.enabled = this.config.showDataTable;
- config.xAxis[0].showLabel = !config.dataSheet.enabled;
- config.zoom.zoomTool.enabled = this.config.showZoom;
- if (this.config.showZoom === true) {
- delete config.dataSheet;
- delete config.zoom.zoomType;
- }
-
- config.yAxis = this.yAxis;
- BI.each(config.yAxis, function (idx, axis) {
- var title = "";
- switch (axis.axisIndex) {
- case self.constants.LEFT_AXIS:
- axis.title.rotation = self.constants.ROTATION;
- title = getXYAxisUnit(self.config.leftYAxisNumberLevel, self.constants.LEFT_AXIS);
- axis.title.text = self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + title : title;
- BI.extend(axis, {
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- reversed: self.config.leftYAxisReversed,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)
- });
- self.formatNumberLevelInYaxis(config, items, self.config.leftYAxisNumberLevel, idx, axis.formatter);
- break;
- case self.constants.RIGHT_AXIS:
- title = getXYAxisUnit(self.config.rightYAxisNumberLevel, self.constants.RIGHT_AXIS);
- axis.title.text = self.config.showRightYAxisTitle === true ? self.config.rightYAxisTitle + title : title;
- axis.title.rotation = self.constants.ROTATION;
- BI.extend(axis, {
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- reversed: self.config.rightYAxisReversed,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators)
- });
- self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisNumberLevel, idx, axis.formatter);
- break;
- }
- });
-
- config.xAxis[0].title.align = "center";
- config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
- BI.extend(config.xAxis[0], {
- lineWidth: this.config.lineWidth,
- enableTick: this.config.enableTick,
- labelRotation: this.config.textDirection,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- maxHeight: '40%'
- });
-
- config.chartType = "line";
-
- //为了给数据标签加个%,还要遍历所有的系列,唉
- this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
-
- //全局样式的图表文字
- this.setFontStyle(this.config.chartFont, config);
-
- return [items, config];
-
- function formatChartStyle() {
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatCordon() {
- BI.each(self.config.cordon, function (idx, cor) {
- if (idx === 0 && self.xAxis.length > 0) {
- var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if (idx > 0 && self.yAxis.length >= idx) {
- var magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- }
-
- function formatChartLineStyle() {
- switch (self.config.chartLineType) {
- case BICst.CHART_SHAPE.RIGHT_ANGLE:
- config.plotOptions.curve = false;
- config.plotOptions.step = true;
- break;
- case BICst.CHART_SHAPE.CURVE:
- config.plotOptions.curve = true;
- config.plotOptions.step = false;
- break;
- case BICst.CHART_SHAPE.NORMAL:
- default:
- config.plotOptions.curve = false;
- config.plotOptions.step = false;
- break;
- }
- }
-
- function getXYAxisUnit(numberLevelType, position) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if (position === self.constants.X_AXIS) {
- self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
- }
- if (position === self.constants.LEFT_AXIS) {
- self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
- }
- if (position === self.constants.RIGHT_AXIS) {
- self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
- }
- return unit === "" ? unit : "(" + unit + ")";
- }
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- rightYAxisTitle: options.rightYAxisTitle || "",
- chartLineType: options.chartLineType || c.NORMAL,
- chartColor: options.chartColor || [],
- chartStyle: options.chartStyle || c.NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- showRightYAxisTitle: options.showRightYAxisTitle || false,
- leftYAxisReversed: options.leftYAxisReversed || false,
- rightYAxisReversed: options.rightYAxisReversed || false,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- rightYAxisUnit: options.rightYAxisUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showDataTable: options.showDataTable || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- showZoom: options.showZoom || false,
- textDirection: options.textDirection || 0,
- cordon: options.cordon || [],
- lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
- showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
- enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
- enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
- numSeparators: options.numSeparators || false,
- rightNumSeparators: options.rightNumSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE,
- nullContinue: options.nullContinue || false
- };
- this.options.items = items;
-
- var types = [];
- BI.each(items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function (id, item) {
- type.push(BICst.WIDGET.LINE);
- });
- types.push(type);
- });
-
- this.yAxis = [];
- BI.each(types, function (idx, type) {
- if (BI.isEmptyArray(type)) {
- return;
- }
- var newYAxis = {
- type: "value",
- title: {
- style: self.constants.FONT_STYLE
- },
- labelStyle: self.constants.FONT_STYLE,
- position: idx > 0 ? "right" : "left",
- lineWidth: 1,
- axisIndex: idx,
- gridLineWidth: 0
- };
- self.yAxis.push(newYAxis);
- });
-
- this.combineChart.populate(items, types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.LineChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.line_chart', BI.LineChart);/**
- * 图表控件
- * @class BI.MapChart
- * @extends BI.Widget
- */
-BI.MapChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.MapChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-map-chart"
- })
- },
-
- _init: function () {
- BI.MapChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.MapChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this, c = this.constants;
- formatRangeLegend();
- delete config.legend;
- delete config.zoom;
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.plotOptions.tooltip.shared = true;
- var formatterArray = [];
- BI.each(items, function (idx, item) {
- if (BI.has(item, "settings")) {
- formatterArray.push(formatToolTipAndDataLabel(item.settings.format || c.NORMAL, item.settings.num_level || c.NORMAL,
- item.settings.unit || "", item.settings.numSeparators || c.NUM_SEPARATORS));
- }
- });
- config.plotOptions.tooltip.formatter = function () {
- var tip = this.name;
- var point = this.points[0];
- var index = BI.isNull(point.size) ? 0 : 1;
- tip += ('
' + point.seriesName + ':' + BI.contentFormat(point.size || point.y, formatterArray[index]) + '
');
- return tip;
- };
- config.plotOptions.dataLabels.formatter.valueFormat = function () {
- return BI.contentFormat(arguments[0], formatterArray[0]);
- };
- config.plotOptions.dataLabels.style = this.config.chartFont;
-
- config.plotOptions.bubble.dataLabels = config.plotOptions.dataLabels;
- config.plotOptions.bubble.dataLabels.formatter.identifier = "${SIZE}";
-
- config.plotOptions.bubble.tooltip = config.plotOptions.tooltip;
-
- config.geo = this.config.geo;
- if (this.config.showBackgroundLayer === true && BI.isNotNull(this.config.backgroundLayerInfo)) {
- if (this.config.backgroundLayerInfo.type === BICst.WMS_SERVER) {
- config.geo.tileLayer = false;
- config.geo.wmsUrl = this.config.backgroundLayerInfo.url;
- config.geo.wmsLayer = this.config.backgroundLayerInfo.wmsLayer
- } else {
- config.geo.tileLayer = this.config.backgroundLayerInfo.url;
- }
- }
- if (this.config.initDrillPath.length > 1) {
- config.initDrillPath = this.config.initDrillPath;
- }
- config.dTools.enabled = true;
- config.dTools.click = function (point) {
- point = point || {};
- var pointOption = point.options || {};
- self.fireEvent(BI.MapChart.EVENT_CLICK_DTOOL, pointOption);
- };
- config.chartType = "areaMap";
- delete config.xAxis;
- delete config.yAxis;
-
- var find = BI.find(items, function (idx, item) {
- return BI.has(item, "type") && item.type === "areaMap";
- });
- if (BI.isNull(find)) {
- items.push({
- type: "areaMap",
- data: []
- })
- }
-
- return [items, config];
-
- function formatRangeLegend() {
- config.rangeLegend.enabled = true;
- switch (self.config.chartLegend) {
- case BICst.CHART_LEGENDS.BOTTOM:
- config.rangeLegend.visible = true;
- config.rangeLegend.position = "bottom";
- break;
- case BICst.CHART_LEGENDS.RIGHT:
- config.rangeLegend.visible = true;
- config.rangeLegend.position = "right";
- break;
- case BICst.CHART_LEGENDS.NOT_SHOW:
- config.rangeLegend.visible = false;
- break;
- }
- config.rangeLegend.continuous = false;
- config.rangeLegend.range = getRangeStyle(self.config.mapStyles, self.config.autoCustom, self.config.themeColor);
- config.rangeLegend.formatter = function () {
- var to = this.to;
- if (BI.isNotEmptyArray(items) && BI.has(items[0], "settings")) {
- var settings = items[0].settings;
- var legendFormat = formatToolTipAndDataLabel(settings.format || c.NORMAL, settings.num_level || c.NORMAL,
- settings.unit || "", settings.numSeparators || c.NUM_SEPARATORS);
- to = BI.contentFormat(to, legendFormat)
- }
- return to
- };
- }
-
- function formatToolTipAndDataLabel(format, numberLevel, unit, numSeparators) {
- var formatter = '#.##';
- switch (format) {
- case self.constants.NORMAL:
- formatter = '#.##';
- if (numSeparators) formatter = '#,###.##';
- break;
- case self.constants.ZERO2POINT:
- formatter = '#0';
- if (numSeparators) formatter = '#,###';
- break;
- case self.constants.ONE2POINT:
- formatter = '#0.0';
- if (numSeparators) formatter = '#,###.0';
- break;
- case self.constants.TWO2POINT:
- formatter = '#0.00';
- if (numSeparators) formatter = '#,###.00';
- break;
- }
-
- switch (numberLevel) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- formatter += '';
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- formatter += BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- formatter += BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- formatter += BI.i18nText("BI-Yi");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.PERCENT:
- formatter += '%';
- break;
- }
-
- return formatter + unit;
- }
-
- function getRangeStyle(styles, change, defaultColor) {
- var range = [], color = null, defaultStyle = {};
- var conditionMax = null, conditionMin = null, min = null;
-
- BI.each(items, function (idx, item) {
- BI.each(item.data, function (id, it) {
- if (BI.isNull(min) || BI.parseFloat(min) > BI.parseFloat(it.y)) {
- min = it.y
- }
- })
- });
-
- switch (change) {
- case BICst.SCALE_SETTING.AUTO:
- defaultStyle.color = defaultColor;
- return defaultStyle;
- case BICst.SCALE_SETTING.CUSTOM:
- if (styles.length !== 0) {
- var maxScale = _calculateValueNiceDomain(0, self.max)[1];
- BI.each(styles, function (idx, style) {
- if (style.range.max) {
- range.push({
- color: style.color || "rgba(255,255,255,0)",
- from: style.range.min,
- to: style.range.max
- });
- } else {
- var to = style.range.min < maxScale ? maxScale : 266396;
- range.push({
- color: style.color || "rgba(255,255,255,0)",
- from: style.range.min,
- to: to,
- });
- }
- color = style.color;
- conditionMax = style.range.max
- });
-
- conditionMin = BI.parseFloat(styles[0].range.min);
- if (conditionMin !== 0) {
- range.push({
- color: "#808080",
- from: 0,
- to: conditionMin
- });
- }
-
- if (conditionMax && conditionMax < maxScale) {
- range.push({
- color: color || "rgba(255,255,255,0)",
- from: conditionMax,
- to: maxScale
- });
- }
- return range;
- } else {
- defaultStyle.color = defaultColor;
- return defaultStyle;
- }
- }
- }
-
- function _calculateValueNiceDomain(minValue, maxValue) {
- minValue = Math.min(0, minValue);
- var tickInterval = _linearTickInterval(minValue, maxValue);
-
- return _linearNiceDomain(minValue, maxValue, tickInterval);
- }
-
- function _linearTickInterval(minValue, maxValue, m) {
- m = m || 5;
- var span = maxValue - minValue;
- var step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10));
- var err = m / span * step;
-
- if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
-
- return step;
- }
-
- function _linearNiceDomain(minValue, maxValue, tickInterval) {
- minValue = VanUtils.accMul(Math.floor(minValue / tickInterval), tickInterval);
- maxValue = VanUtils.accMul(Math.ceil(maxValue / tickInterval), tickInterval);
-
- return [minValue, maxValue];
- }
- },
-
- _formatDrillItems: function (items) {
- var self = this;
- BI.each(items.series, function (idx, da) {
- var hasArea = false;
- BI.each(da.data, function (idx, data) {
- data.y = self.formatXYDataWithMagnify(data.y, 1);
- if (BI.has(da, "settings")) {
- data.y = self.formatXYDataWithMagnify(data.y, self.calcMagnify(da.settings.num_level || self.constants.NORMAL));
- }
- if (BI.has(da, "type") && da.type == "bubble") {
- data.name = data.x;
- data.size = data.y;
- } else {
- data.name = data.x;
- data.value = data.y;
- }
- if (BI.has(da, "type") && da.type === "areaMap") {
- hasArea = true;
- }
- if (BI.has(data, "drilldown")) {
- self._formatDrillItems(data.drilldown);
- }
- });
- if (hasArea === false) {
- items.series.push({
- type: "areaMap",
- data: []
- });
- }
- });
- },
-
- _formatItems: function (items) {
- var self = this;
- this.max = null;
- this.min = null;
- BI.each(items, function (idx, item) {
- BI.each(item, function (id, it) {
- BI.each(it.data, function (i, da) {
- da.y = self.formatXYDataWithMagnify(da.y, 1);
- if (BI.has(it, "settings")) {
- da.y = self.formatXYDataWithMagnify(da.y, self.calcMagnify(it.settings.num_level || self.constants.NORMAL));
- }
- if ((BI.isNull(self.max) || BI.parseFloat(da.y) > BI.parseFloat(self.max)) && id === 0) {
- self.max = da.y;
- }
- if ((BI.isNull(self.min) || BI.parseFloat(da.y) < BI.parseFloat(self.min)) && id === 0) {
- self.min = da.y;
- }
- if (BI.has(it, "type") && it.type == "bubble") {
- da.name = da.x;
- da.size = da.y;
- } else {
- da.name = da.x;
- da.value = da.y;
- }
- if (BI.has(da, "drilldown")) {
- self._formatDrillItems(da.drilldown);
- }
- });
- })
- });
- return items;
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- geo: options.geo,
- initDrillPath: options.initDrillPath || [],
- tooltip: options.tooltip || "",
- themeColor: options.themeColor || "#65bce7",
- mapStyles: options.mapStyles || [],
- autoCustom: options.autoCustom || c.AUTO_CUSTOM,
- showBackgroundLayer: options.showBackgroundLayer || false,
- backgroundLayerInfo: options.backgroundLayerInfo,
- chartFont: options.chartFont || c.FONT_STYLE
- };
- this.options.items = items;
-
- var types = [];
- BI.each(items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function (id, item) {
- type.push(BICst.WIDGET.MAP);
- });
- types.push(type);
- });
-
- this.combineChart.populate(this._formatItems(items), types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.MapChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.MapChart.EVENT_CLICK_DTOOL = "EVENT_CLICK_DTOOL";
-BI.shortcut('bi.map_chart', BI.MapChart);/**
- * 图表控件
- * @class BI.MultiAxisChart
- * @extends BI.Widget
- * leftYxis 左值轴属性
- * rightYxis 右值轴属性
- * xAxis 分类轴属性
- */
-BI.MultiAxisChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.MultiAxisChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-multi-axis-chart"
- })
- },
-
- _init: function () {
- BI.MultiAxisChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.xAxis = [{
- type: "category",
- title: {
- style: {"fontFamily": "inherit", "color": "#808080", "fontSize": "12px", "fontWeight": ""}
- },
- labelStyle: {
- "fontFamily": "inherit", "color": "#808080", "fontSize": "12px"
- },
- position: "bottom",
- gridLineWidth: 0
- }];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.MultiAxisChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this, o = this.options;
- config.colors = this.config.chartColor;
- config.style = this.formatChartStyle();
- this.formatCordon();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.plotOptions.connectNulls = this.config.nullContinue;
- config.dataSheet.enabled = this.config.showDataTable;
- config.xAxis[0].showLabel = !config.dataSheet.enabled;
- config.zoom.zoomTool.enabled = this.config.showZoom;
- if (this.config.showZoom === true) {
- delete config.dataSheet;
- delete config.zoom.zoomType;
- }
-
- config.yAxis = this.yAxis;
- BI.each(config.yAxis, function (idx, axis) {
- var title = "";
- switch (axis.axisIndex) {
- case self.constants.LEFT_AXIS:
- title = self.getXYAxisUnit(self.config.leftYAxisNumberLevel, self.constants.LEFT_AXIS);
- axis.title.text = self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + title : title;
- axis.title.rotation = self.constants.ROTATION;
- BI.extend(axis, {
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- reversed: self.config.leftYAxisReversed,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)
- });
- self.formatNumberLevelInYaxis(config, items, self.config.leftYAxisNumberLevel, idx, axis.formatter);
- break;
- case self.constants.RIGHT_AXIS:
- title = self.getXYAxisUnit(self.config.rightYAxisNumberLevel, self.constants.RIGHT_AXIS);
- axis.title.text = self.config.showRightYAxisTitle === true ? self.config.rightYAxisTitle + title : title;
- axis.title.rotation = self.constants.ROTATION;
- BI.extend(axis, {
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- reversed: self.config.rightYAxisReversed,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators)
- });
- self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisNumberLevel, idx, axis.formatter);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- title = self.getXYAxisUnit(self.config.rightYAxisSecondNumberLevel, self.constants.RIGHT_AXIS_SECOND);
- axis.title.text = self.config.showRightYAxisSecondTitle === true ? self.config.rightYAxisSecondTitle + title : title;
- axis.title.rotation = self.constants.ROTATION;
- BI.extend(axis, {
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- reversed: self.config.rightYAxisSecondReversed,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.rightYAxisSecondStyle, self.config.rightYAxisSecondNumberLevel, self.config.rightNumSeparators)
- });
- self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisSecondNumberLevel, idx, axis.formatter);
- break;
- default:
- break;
- }
- });
- config.xAxis[0].title.align = "center";
- config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
- BI.extend(config.xAxis[0], {
- lineWidth: this.config.lineWidth,
- enableTick: this.config.enableTick,
- labelRotation: this.config.textDirection,
- enableMinorTick: this.config.enableMinorTick,
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- maxHeight: '40%'
- });
-
- //为了给数据标签加个%,还要遍历所有的系列,唉
- this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
-
- //全局样式的图表文字
- if (config.dataSheet) {
- config.dataSheet.style = this.config.chartFont;
- }
- config.xAxis[0].title.style = config.xAxis[0].labelStyle = this.config.chartFont;
- config.legend.style = this.config.chartFont;
- config.plotOptions.dataLabels.style = this.config.chartFont;
- BI.each(config.yAxis, function (idx, axis) {
- axis.title.style = self.config.chartFont;
- });
-
- return [items, config];
- },
-
- formatChartStyle: function () {
- switch (this.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- },
-
- formatCordon: function () {
- var self = this;
- var magnify = 1;
- BI.each(this.config.cordon, function (idx, cor) {
- if (idx === 0 && self.xAxis.length > 0) {
- magnify = self.calcMagnify(self.config.xAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style": {
- "fontFamily": "inherit",
- "color": "#808080",
- "fontSize": "12px",
- "fontWeight": ""
- },
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if (idx > 0 && self.yAxis.length >= idx) {
- magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
- break;
- default:
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style": {
- "fontFamily": "inherit",
- "color": "#808080",
- "fontSize": "12px",
- "fontWeight": ""
- },
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- },
-
- getXYAxisUnit: function (numberLevelType, position) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- default:
- break;
- }
- if (position === this.constants.X_AXIS) {
- this.config.xAxisUnit !== "" && (unit = unit + this.config.xAxisUnit)
- }
- if (position === this.constants.LEFT_AXIS) {
- this.config.leftYAxisUnit !== "" && (unit = unit + this.config.leftYAxisUnit)
- }
- if (position === this.constants.RIGHT_AXIS) {
- this.config.rightYAxisUnit !== "" && (unit = unit + this.config.rightYAxisUnit)
- }
- if (position === this.constants.RIGHT_AXIS_SECOND) {
- this.config.rightYAxisSecondUnit !== "" && (unit = unit + this.config.rightYAxisSecondUnit)
- }
- return unit === "" ? unit : "(" + unit + ")";
- },
-
- populate: function (items, options, types) {
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- rightYAxisTitle: options.rightYAxisTitle || "",
- rightYAxisSecondTitle: options.rightYAxisSecondTitle || "",
- chartColor: options.chartColor || ["#5caae4", "#70cc7f", "#ebbb67", "#e97e7b", "#6ed3c9"],
- chartStyle: options.chartStyle || c.NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
- rightYAxisSecondStyle: options.rightYAxisSecondStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- showRightYAxisTitle: options.showRightYAxisTitle || false,
- showRightYAxisSecondTitle: options.showRightYAxisSecondTitle || false,
- leftYAxisReversed: options.leftYAxisReversed || false,
- rightYAxisReversed: options.rightYAxisReversed || false,
- rightYAxisSecondReversed: options.rightYAxisSecondReversed || false,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
- rightYAxisSecondNumberLevel: options.rightYAxisSecondNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- rightYAxisUnit: options.rightYAxisUnit || "",
- rightYAxisSecondUnit: options.rightYAxisSecondUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showDataTable: options.showDataTable || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- showZoom: options.showZoom || false,
- textDirection: options.textDirection || 0,
- cordon: options.cordon || [],
- lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
- showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
- enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
- enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
- numSeparators: options.numSeparators || false,
- rightNumSeparators: options.rightNumSeparators || false,
- rightNumSeparators: options.rightNumSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE,
- nullContinue: options.nullContinue || false
- };
- this.options.items = items;
-
- this.yAxis = [];
- BI.each(types, function (idx, type) {
- if (BI.isEmptyArray(type)) {
- return;
- }
- var newYAxis = {
- type: "value",
- title: {
- style: {"fontFamily": "inherit", "color": "#808080", "fontSize": "12px", "fontWeight": ""}
- },
- labelStyle: {
- "fontFamily": "inherit", "color": "#808080", "fontSize": "12px"
- },
- position: idx > 0 ? "right" : "left",
- lineWidth: 1,
- axisIndex: idx,
- gridLineWidth: 0
- };
- self.yAxis.push(newYAxis);
- });
-
- this.combineChart.populate(items, types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.MultiAxisChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.multi_axis_chart', BI.MultiAxisChart);/**
- * 图表控件
- * @class BI.MultiAxisChart
- * @extends BI.Widget
- * leftYxis 左值轴属性
- * rightYxis 右值轴属性
- * xAxis 分类轴属性
- */
-BI.MultiAxisCombineChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.MultiAxisCombineChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-multi-axis-combine-chart"
- })
- },
-
- _init: function () {
- BI.MultiAxisCombineChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.xAxis = [{
- type: "category",
- title: {
- style: {"fontFamily": "inherit", "color": "#808080", "fontSize": "12px", "fontWeight": ""}
- },
- labelStyle: {
- "fontFamily": "inherit", "color": "#808080", "fontSize": "12px"
- },
- position: "bottom",
- gridLineWidth: 0
- }];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.MultiAxisCombineChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this, o = this.options;
- config.colors = this.config.chartColor;
- config.style = this.formatChartStyle();
- this.formatCordon();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.plotOptions.connectNulls = this.config.nullContinue;
- config.dataSheet.enabled = this.config.showDataTable;
- config.xAxis[0].showLabel = !config.dataSheet.enabled;
- config.zoom.zoomTool.enabled = this.config.showZoom;
- if (this.config.showZoom === true) {
- delete config.dataSheet;
- delete config.zoom.zoomType;
- }
-
- config.yAxis = this.yAxis;
- BI.each(config.yAxis, function (idx, axis) {
- var title = "";
- switch (axis.axisIndex) {
- case self.constants.LEFT_AXIS:
- title = self.getXYAxisUnit(self.config.leftYAxisNumberLevel, self.constants.LEFT_AXIS);
- axis.title.text = self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + title : title;
- axis.title.rotation = self.constants.ROTATION;
- axis.labelStyle.color = axis.lineColor = axis.tickColor = config.colors[0];
- BI.extend(axis, {
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- reversed: self.config.leftYAxisReversed,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)
- });
- self.formatNumberLevelInYaxis(config, items, self.config.leftYAxisNumberLevel, idx, axis.formatter);
- break;
- case self.constants.RIGHT_AXIS:
- title = self.getXYAxisUnit(self.config.rightYAxisNumberLevel, self.constants.RIGHT_AXIS);
- axis.title.text = self.config.showRightYAxisTitle === true ? self.config.rightYAxisTitle + title : title;
- axis.title.rotation = self.constants.ROTATION;
- axis.labelStyle.color = axis.lineColor = axis.tickColor = config.colors[1];
- BI.extend(axis, {
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- reversed: self.config.rightYAxisReversed,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators)
- });
- self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisNumberLevel, idx, axis.formatter);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- title = self.getXYAxisUnit(self.config.rightYAxisSecondNumberLevel, self.constants.RIGHT_AXIS_SECOND);
- axis.title.text = self.config.showRightYAxisSecondTitle === true ? self.config.rightYAxisSecondTitle + title : title;
- axis.title.rotation = self.constants.ROTATION;
- axis.labelStyle.color = axis.lineColor = axis.tickColor = config.colors[2];
- BI.extend(axis, {
- lineWidth: self.config.lineWidth,
- showLabel: self.config.showLabel,
- enableTick: self.config.enableTick,
- reversed: self.config.rightYAxisSecondReversed,
- enableMinorTick: self.config.enableMinorTick,
- gridLineWidth: self.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(self.config.rightYAxisSecondStyle, self.config.rightYAxisSecondNumberLevel, self.config.rightNumSeparators)
- });
- self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisSecondNumberLevel, idx, axis.formatter);
- break;
- default:
- break;
- }
- });
- config.xAxis[0].title.align = "center";
- config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
- BI.extend(config.xAxis[0], {
- lineWidth: this.config.lineWidth,
- enableTick: this.config.enableTick,
- labelRotation: this.config.textDirection,
- enableMinorTick: this.config.enableMinorTick,
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- maxHeight: '40%'
- });
-
- //为了给数据标签加个%,还要遍历所有的系列,唉
- this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
-
- //全局样式的图表文字
- if (config.dataSheet) {
- config.dataSheet.style = this.config.chartFont;
- }
- config.xAxis[0].title.style = config.xAxis[0].labelStyle = this.config.chartFont;
- config.legend.style = this.config.chartFont;
- config.plotOptions.dataLabels.style = this.config.chartFont;
- BI.each(config.yAxis, function (idx, axis) {
- axis.title.style = self.config.chartFont;
- });
-
- return [items, config];
- },
-
- formatChartStyle: function () {
- switch (this.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- },
-
- formatCordon: function () {
- var self = this;
- var magnify = 1;
- BI.each(this.config.cordon, function (idx, cor) {
- if (idx === 0 && self.xAxis.length > 0) {
- magnify = self.calcMagnify(self.config.xAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style": {
- "fontFamily": "inherit",
- "color": "#808080",
- "fontSize": "12px",
- "fontWeight": ""
- },
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if (idx > 0 && self.yAxis.length >= idx) {
- magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
- break;
- default:
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style": {
- "fontFamily": "inherit",
- "color": "#808080",
- "fontSize": "12px",
- "fontWeight": ""
- },
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- },
-
- getXYAxisUnit: function (numberLevelType, position) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- default:
- break;
- }
- if (position === this.constants.X_AXIS) {
- this.config.xAxisUnit !== "" && (unit = unit + this.config.xAxisUnit)
- }
- if (position === this.constants.LEFT_AXIS) {
- this.config.leftYAxisUnit !== "" && (unit = unit + this.config.leftYAxisUnit)
- }
- if (position === this.constants.RIGHT_AXIS) {
- this.config.rightYAxisUnit !== "" && (unit = unit + this.config.rightYAxisUnit)
- }
- if (position === this.constants.RIGHT_AXIS_SECOND) {
- this.config.rightYAxisSecondUnit !== "" && (unit = unit + this.config.rightYAxisSecondUnit)
- }
- return unit === "" ? unit : "(" + unit + ")";
- },
-
- populate: function (items, options, types) {
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- rightYAxisTitle: options.rightYAxisTitle || "",
- rightYAxisSecondTitle: options.rightYAxisSecondTitle || "",
- chartColor: options.chartColor || ["#5caae4", "#70cc7f", "#ebbb67", "#e97e7b", "#6ed3c9"],
- chartStyle: options.chartStyle || c.NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
- rightYAxisSecondStyle: options.rightYAxisSecondStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- showRightYAxisTitle: options.showRightYAxisTitle || false,
- showRightYAxisSecondTitle: options.showRightYAxisSecondTitle || false,
- leftYAxisReversed: options.leftYAxisReversed || false,
- rightYAxisReversed: options.rightYAxisReversed || false,
- rightYAxisSecondReversed: options.rightYAxisSecondReversed || false,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
- rightYAxisSecondNumberLevel: options.rightYAxisSecondNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- rightYAxisUnit: options.rightYAxisUnit || "",
- rightYAxisSecondUnit: options.rightYAxisSecondUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showDataTable: options.showDataTable || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- showZoom: options.showZoom || false,
- textDirection: options.textDirection || 0,
- cordon: options.cordon || [],
- lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
- showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
- enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
- enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
- numSeparators: options.numSeparators || false,
- rightNumSeparators: options.rightNumSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE,
- nullContinue: options.nullContinue || false
- };
- this.options.items = items;
-
- this.yAxis = [];
- BI.each(types, function (idx, type) {
- if (BI.isEmptyArray(type)) {
- return;
- }
- var newYAxis = {
- type: "value",
- title: {
- style: {"fontFamily": "inherit", "color": "#808080", "fontSize": "12px", "fontWeight": ""}
- },
- labelStyle: {
- "fontFamily": "inherit", "color": "#808080", "fontSize": "12px"
- },
- position: idx > 0 ? "right" : "left",
- lineWidth: 1,
- axisIndex: idx,
- gridLineWidth: 0
- };
- self.yAxis.push(newYAxis);
- });
-
- this.combineChart.populate(items, types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.MultiAxisCombineChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.multi_axis_combine_chart', BI.MultiAxisCombineChart);/**
- * 图表控件
- * @class BI.PercentAccumulateAreaChart
- * @extends BI.Widget
- */
-BI.PercentAccumulateAreaChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.PercentAccumulateAreaChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-percent-accumulate-area-chart"
- })
- },
-
- _init: function () {
- BI.PercentAccumulateAreaChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.xAxis = [{
- type: "category",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- position: "bottom",
- gridLineWidth: 0
- }];
- this.yAxis = [{
- type: "value",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- position: "left",
- gridLineWidth: 0
- }];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.PercentAccumulateAreaChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this;
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- formatCordon();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.plotOptions.connectNulls = this.config.nullContinue;
- config.dataSheet.enabled = this.config.showDataTable;
- config.xAxis[0].showLabel = !config.dataSheet.enabled;
- config.zoom.zoomTool.enabled = this.config.showZoom;
- if (this.config.showZoom === true) {
- delete config.dataSheet;
- delete config.zoom.zoomType;
- }
-
- config.yAxis = this.yAxis;
- config.yAxis[0].title.text = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
- config.yAxis[0].title.rotation = this.constants.ROTATION;
- BI.extend(config.yAxis[0], {
- lineWidth: this.config.lineWidth,
- showLabel: this.config.showLabel,
- enableTick: this.config.enableTick,
- reversed: this.config.leftYAxisReversed,
- enableMinorTick: this.config.enableMinorTick,
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators)
- });
- self.formatNumberLevelInYaxis(config, items, this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS, config.yAxis[0].formatter, true);
-
- config.xAxis[0].title.align = "center";
- config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
- BI.extend(config.xAxis[0], {
- lineWidth: this.config.lineWidth,
- enableTick: this.config.enableTick,
- labelRotation: this.config.textDirection,
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- maxHeight: '40%'
- });
-
- config.chartType = "area";
-
- //为了给数据标签加个%,还要遍历所有的系列,唉
- this.formatDataLabelForAxis(config.plotOptions.dataLabels.enabled, items, config.yAxis[0].formatter, this.config.chartFont, true);
-
- //全局样式的图表文字
- this.setFontStyle(this.config.chartFont, config);
-
- return [items, config];
-
- function formatChartStyle() {
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatCordon() {
- BI.each(self.config.cordon, function (idx, cor) {
- if (idx === 0 && self.xAxis.length > 0) {
- var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style": self.config.chartFont,
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if (idx > 0 && self.yAxis.length >= idx) {
- var magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style": self.config.chartFont,
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- }
-
- function getXYAxisUnit(numberLevelType, position) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if (position === self.constants.X_AXIS) {
- self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
- }
- if (position === self.constants.LEFT_AXIS) {
- self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
- }
-
- unit = unit === "" ? unit : "(" + unit + ")";
-
- return self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + unit : unit
- }
- },
-
- _formatItems: function (items) {
- return BI.map(items, function (idx, item) {
- var i = BI.UUID();
- return BI.map(item, function (id, it) {
- return BI.extend({}, it, {stack: i, stackByPercent: true});
- });
- });
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- chartColor: options.chartColor || [],
- chartStyle: options.chartStyle || c.NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- leftYAxisReversed: options.leftYAxisReversed || false,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showDataTable: options.showDataTable || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- showZoom: options.showZoom || false,
- textDirection: options.textDirection || 0,
- cordon: options.cordon || [],
- lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
- showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
- enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
- enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
- numSeparators: options.numSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE,
- nullContinue: options.nullContinue || false
- };
- this.options.items = items;
-
- var types = [];
- BI.each(items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function (id, item) {
- type.push(BICst.WIDGET.AREA);
- });
- types.push(type);
- });
-
- this.combineChart.populate(this._formatItems(items), types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.PercentAccumulateAreaChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.percent_accumulate_area_chart', BI.PercentAccumulateAreaChart);/**
- * 图表控件 百分比堆积柱状
- * @class BI.PercentAccumulateAxisChart
- * @extends BI.Widget
- */
-BI.PercentAccumulateAxisChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.PercentAccumulateAxisChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-percent-accumulate-axis-chart"
- })
- },
-
- _init: function () {
- BI.PercentAccumulateAxisChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.xAxis = [{
- type: "category",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- position: "bottom",
- gridLineWidth: 0
- }];
- this.yAxis = [{
- type: "value",
- title: {
- style: self.constants.FONT_STYLE
- },
- labelStyle: self.constants.FONT_STYLE,
- position: "left",
- gridLineWidth: 0
- }];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.PercentAccumulateAxisChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this, o = this.options;
- var yTitle = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- formatCordon();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.dataSheet.enabled = this.config.showDataTable;
- config.xAxis[0].showLabel = !config.dataSheet.enabled;
- config.zoom.zoomTool.enabled = this.config.showZoom;
- if (this.config.showZoom === true) {
- delete config.dataSheet;
- delete config.zoom.zoomType;
- }
-
- config.yAxis = this.yAxis;
- config.yAxis[0].title.rotation = this.constants.ROTATION;
- config.yAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + yTitle : yTitle;
- BI.extend(config.yAxis[0], {
- lineWidth: this.config.lineWidth,
- showLabel: this.config.showLabel,
- enableTick: this.config.enableTick,
- reversed: this.config.leftYAxisReversed,
- enableMinorTick: this.config.enableMinorTick,
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- formatter: self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators)
- });
- self.formatNumberLevelInYaxis(config, items, this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS, config.yAxis[0].formatter, true);
-
- config.xAxis[0].title.align = "center";
- config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
- BI.extend(config.xAxis[0], {
- lineWidth: this.config.lineWidth,
- enableTick: this.config.enableTick,
- labelRotation: this.config.textDirection,
- enableMinorTick: this.config.enableMinorTick,
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- maxHeight: '40%'
- });
-
- //为了给数据标签加个%,还要遍历所有的系列,唉
- this.formatDataLabelForAxis(config.plotOptions.dataLabels.enabled, items, config.yAxis[0].formatter, this.config.chartFont, true);
-
- //全局样式的图表文字
- this.setFontStyle(this.config.chartFont, config);
-
- return [items, config];
-
- function formatChartStyle() {
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatCordon() {
- BI.each(self.config.cordon, function (idx, cor) {
- if (idx === 0 && self.xAxis.length > 0) {
- var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if (idx > 0 && self.yAxis.length >= idx) {
- var magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- }
-
- function getXYAxisUnit(numberLevelType, position) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if (position === self.constants.X_AXIS) {
- self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
- }
- if (position === self.constants.LEFT_AXIS) {
- self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
- }
- return unit === "" ? unit : "(" + unit + ")";
- }
- },
-
- _formatItems: function (items) {
- return BI.map(items, function (idx, item) {
- var i = BI.UUID();
- return BI.map(item, function (id, it) {
- return BI.extend({}, it, {stack: i, stackByPercent: true});
- });
- });
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- chartColor: options.chartColor || [],
- chartStyle: options.chartStyle || c.NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- leftYAxisReversed: options.leftYAxisReversed || false,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showDataTable: options.showDataTable || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- showZoom: options.showZoom || false,
- textDirection: options.textDirection || 0,
- cordon: options.cordon || [],
- lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
- showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
- enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
- enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
- numSeparators: options.numSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE
- };
- this.options.items = items;
-
- var types = [];
- BI.each(items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function (id, item) {
- type.push(BICst.WIDGET.AXIS);
- });
- types.push(type);
- });
-
- this.combineChart.populate(this._formatItems(items), types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.PercentAccumulateAxisChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.percent_accumulate_axis_chart', BI.PercentAccumulateAxisChart);/**
- * 图表控件
- * @class BI.PieChart
- * @extends BI.Widget
- */
-BI.PieChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.PieChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-pie-chart"
- })
- },
-
- _init: function () {
- BI.PieChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.PieChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function(config, items){
- var self = this, o = this.options;
- delete config.zoom;
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- formatChartPieStyle();
-
- this.formatChartLegend(config, this.config.chartLegend);
-
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.plotOptions.tooltip.formatter.identifier = "${CATEGORY}${SERIES}${VALUE}${PERCENT}";
-
- config.chartType = "pie";
- delete config.xAxis;
- delete config.yAxis;
- config.plotOptions.dataLabels.align = "outside";
- config.plotOptions.dataLabels.connectorWidth = "outside";
- config.plotOptions.dataLabels.formatter.identifier = "${VALUE}${PERCENT}";
- config.plotOptions.dataLabels.style = this.config.chartFont;
- BI.each(items, function (idx, item) {
- BI.each(item.data, function (id, da) {
- da.y = self.formatXYDataWithMagnify(da.y, 1);
- })
- });
-
- config.legend.style = this.config.chartFont;
-
- return [items, config];
-
- function formatChartStyle(){
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatChartPieStyle(){
- switch (self.config.chartPieType){
- case BICst.CHART_SHAPE.EQUAL_ARC_ROSE:
- config.plotOptions.roseType = "sameArc";
- break;
- case BICst.CHART_SHAPE.NOT_EQUAL_ARC_ROSE:
- config.plotOptions.roseType = "differentArc";
- break;
- case BICst.CHART_SHAPE.NORMAL:
- default:
- delete config.plotOptions.roseType;
- break;
- }
- config.plotOptions.innerRadius = self.config.chartInnerRadius + "%";
- config.plotOptions.endAngle = self.config.chartTotalAngle;
- }
-
- },
-
- //目前饼图不会有多个系列,如果有多个就要把它们合并在一起
- _isNeedConvert: function(items){
- var result = BI.find(items, function(idx, item){
- return item.length > 1;
- });
- return BI.isNotNull(result);
- },
-
- _formatItems: function(items){
- if(this._isNeedConvert(items)){
- //把每个坐标轴所有的多个系列合并成一个系列
- return BI.map(items, function(idx, item){
- var seriesItem = [];
- var obj = {data: [], name: ""};
- seriesItem.push(obj);
- BI.each(item, function(id, series){
- BI.each(series.data, function(i, da){
- obj.data.push(BI.extend({}, da, {x: series.name}));
- });
- });
- return seriesItem;
- })
- }else{
- return items;
- }
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- chartColor: options.chartColor || [],
- chartStyle: options.chartStyle || c.NORMAL,
- chartPieType: options.chartPieType || c.NORMAL,
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- chartInnerRadius: options.chartInnerRadius || 0,
- chartTotalAngle: options.chartTotalAngle || BICst.PIE_ANGLES.TOTAL,
- chartFont: options.chartFont || c.FONT_STYLE
- };
- this.options.items = items;
-
- var types = [];
- BI.each(items, function(idx, axisItems){
- var type = [];
- BI.each(axisItems, function(id, item){
- type.push(BICst.WIDGET.PIE);
- });
- types.push(type);
- });
-
- this.combineChart.populate(this._formatItems(items), types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function(){
- this.combineChart.magnify();
- }
-});
-BI.PieChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.pie_chart', BI.PieChart);
-
-/**
- * 图表控件
- * @class BI.RadarChart
- * @extends BI.Widget
- */
-BI.RadarChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.RadarChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-radar-chart"
- })
- },
-
- _init: function () {
- BI.RadarChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.radiusAxis = [{
- type: "value",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- formatter: function () {
- return this > 0 ? this : (-1) * this
- },
- gridLineWidth: 0,
- position: "bottom"
- }];
-
- this.angleAxis = [{
- type: "category",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE
- }];
-
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.RadarChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this;
-
- delete config.zoom;
-
- var title = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
-
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- formatChartRadarStyle();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.plotOptions.connectNulls = this.config.nullContinue;
-
- config.radiusAxis = this.radiusAxis;
- config.angleAxis = this.angleAxis;
- config.radiusAxis[0].formatter = self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators);
- formatNumberLevelInYaxis(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS, config.radiusAxis[0].formatter);
- config.radiusAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + title : title;
- config.radiusAxis[0].gridLineWidth = this.config.showGridLine === true ? 1 : 0;
- config.chartType = "radar";
- delete config.xAxis;
- delete config.yAxis;
- //为了给数据标签加个%,还要遍历所有的系列,唉
- this.formatDataLabelForAxis(config.plotOptions.dataLabels.enabled, items, config.radiusAxis[0].formatter, this.config.chartFont);
-
- //全局样式
- config.legend.style = this.config.chartFont;
- config.radiusAxis[0].title.style = config.radiusAxis[0].labelStyle = this.config.chartFont;
- config.angleAxis[0].title.style = config.angleAxis[0].labelStyle = this.config.chartFont;
-
- return [items, config];
-
- function formatChartStyle() {
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatChartRadarStyle() {
- switch (self.config.chartRadarType) {
- case BICst.CHART_SHAPE.POLYGON:
- config.plotOptions.shape = "polygon";
- break;
- case BICst.CHART_SHAPE.CIRCLE:
- config.plotOptions.shape = "circle";
- break;
- }
- }
-
- function formatNumberLevelInYaxis(type, position, formatter) {
- var magnify = self.calcMagnify(type);
- BI.each(items, function (idx, item) {
- BI.each(item.data, function (id, da) {
- if (position === item.yAxis) {
- da.y = self.formatXYDataWithMagnify(da.y, magnify);
- }
- })
- });
- config.plotOptions.tooltip.formatter.valueFormat = formatter;
- }
-
- function getXYAxisUnit(numberLevelType, position) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if (position === self.constants.X_AXIS) {
- self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
- }
- if (position === self.constants.LEFT_AXIS) {
- self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
- }
- if (position === self.constants.RIGHT_AXIS) {
- self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
- }
- return unit === "" ? unit : "(" + unit + ")";
- }
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- chartRadarType: options.chartRadarType || c.POLYGON,
- chartColor: options.chartColor || [],
- chartStyle: options.chartStyle || c.STYLE_NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- cordon: options.cordon || [],
- numSeparators: options.numSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE,
- nullContinue: options.nullContinue || false
- };
- this.options.items = items;
- var types = [];
- BI.each(items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function (id, item) {
- type.push(BICst.WIDGET.RADAR);
- });
- types.push(type);
- });
- this.combineChart.populate(items, types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.RadarChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.radar_chart', BI.RadarChart);/**
- * 图表控件
- * @class BI.RangeAreaChart
- * @extends BI.Widget
- * 范围面积图的构造范围的两组item的必须有对应y值item1完全大于item2
- */
-BI.RangeAreaChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.RangeAreaChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-range-area-chart"
- })
- },
-
- _init: function () {
- BI.RangeAreaChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.xAxis = [{
- type: "category",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- position: "bottom",
- gridLineWidth: 0
- }];
- this.yAxis = [{
- type: "value",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- position: "left",
- gridLineWidth: 0
- }];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.RangeAreaChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
- _formatConfig: function (config, items) {
- var self = this;
- var title = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- formatCordon();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.plotOptions.connectNulls = this.config.nullContinue;
-
- config.yAxis = this.yAxis;
- config.yAxis[0].title.rotation = this.constants.ROTATION;
- config.yAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + title : title;
- BI.extend(config.yAxis[0], {
- lineWidth: this.config.lineWidth,
- showLabel: this.config.showLabel,
- enableTick: this.config.enableTick,
- enableMinorTick: this.config.enableMinorTick,
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- reversed: config.yAxis[0].reversed = this.config.leftYAxisReversed,
- formatter: self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators)
- });
- formatNumberLevelInYaxis(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS, config.yAxis[0].formatter);
-
- config.xAxis[0].title.align = "center";
- config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
- BI.extend(config.xAxis[0], {
- lineWidth: this.config.lineWidth,
- enableTick: this.config.enableTick,
- labelRotation: this.config.textDirection,
- gridLineWidth: this.config.showGridLine === true ? 1 : 0,
- maxHeight: '40%'
- });
-
- config.chartType = "area";
- config.plotOptions.tooltip.formatter.identifier = "${CATEGORY}${VALUE}";
-
- //为了给数据标签加个%,还要遍历所有的系列,唉
- this.formatDataLabelForAxis(config.plotOptions.dataLabels.enabled, items, config.yAxis[0].formatter, this.config.chartFont);
-
- //全局样式的图表文字
- this.setFontStyle(this.config.chartFont, config);
-
- return [items, config];
-
- function formatChartStyle() {
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatCordon() {
- BI.each(self.config.cordon, function (idx, cor) {
- if (idx === 0 && self.xAxis.length > 0) {
- var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if (idx > 0 && self.yAxis.length >= idx) {
- var magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style" : self.config.chartFont,
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- }
-
- function formatNumberLevelInYaxis(type, position, formatter) {
- var magnify = self.calcMagnify(type);
- BI.each(items, function (idx, item) {
- BI.each(item.data, function (id, da) {
- if (position === item.yAxis) {
- da.y = self.formatXYDataWithMagnify(da.y, magnify);
- }
- })
- });
- config.plotOptions.tooltip.formatter.valueFormat = formatter;
- }
-
- function getXYAxisUnit(numberLevelType, position) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if (position === self.constants.X_AXIS) {
- self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
- }
- if (position === self.constants.LEFT_AXIS) {
- self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
- }
- return unit === "" ? unit : "(" + unit + ")";
- }
- },
-
- _formatItems: function (data) {
- var o = this.options;
- var items = [];
- BI.each(data, function (idx, item) {
- items = BI.concat(items, item);
- });
- if (BI.isEmptyArray(items)) {
- return [];
- }
- if (items.length === 1) {
- return [items];
- }
- var colors = this.config.chartColor || [];
- if (BI.isEmptyArray(colors)) {
- colors = ["#5caae4"];
- }
- var seriesMinus = [];
- BI.each(items[0].data, function (idx, item) {
- var res = items[1].data[idx].y - item.y;
- seriesMinus.push({
- x: items[1].data[idx].x,
- y: res,
- targetIds: items[1].data[idx].targetIds
- });
- });
- items[1] = {
- data: seriesMinus,
- name: items[1].name,
- stack: "stackedArea",
- fillColor: colors[0]
- };
- BI.each(items, function (idx, item) {
- if (idx === 0) {
- BI.extend(item, {
- name: items[0].name,
- fillColorOpacity: 0,
- stack: "stackedArea",
- marker: {enabled: false},
- fillColor: "#000000"
- });
- }
- });
- return [items];
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- chartColor: options.chartColor || [],
- chartStyle: options.chartStyle || c.NORMAL,
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- leftYAxisReversed: options.leftYAxisReversed || false,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- textDirection: options.textDirection || 0,
- cordon: options.cordon || [],
- lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
- showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
- enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
- enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
- numSeparators: options.numSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE,
- nullContinue: options.nullContinue || false
- };
- this.options.items = items;
-
- var types = [];
- var type = [];
- BI.each(items, function (idx, axisItems) {
- type.push(BICst.WIDGET.AREA);
- });
- if (BI.isNotEmptyArray(type)) {
- types.push(type);
- }
-
- this.combineChart.populate(this._formatItems(items), types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.RangeAreaChart.EVENT_CHANGE = "EVENT_CHANGE";
-BI.shortcut('bi.range_area_chart', BI.RangeAreaChart);/**
- * 图表控件
- * @class BI.ScatterChart
- * @extends BI.Widget
- */
-BI.ScatterChart = BI.inherit(BI.AbstractChart, {
-
- _defaultConfig: function () {
- return BI.extend(BI.ScatterChart.superclass._defaultConfig.apply(this, arguments), {
- baseCls: "bi-scatter-chart"
- })
- },
-
- _init: function () {
- BI.ScatterChart.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
- this.xAxis = [{
- type: "value",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- position: "bottom",
- gridLineWidth: 0
- }];
- this.yAxis = [{
- type: "value",
- title: {
- style: this.constants.FONT_STYLE
- },
- labelStyle: this.constants.FONT_STYLE,
- position: "left",
- gridLineWidth: 0
- }];
- this.combineChart = BI.createWidget({
- type: "bi.combine_chart",
- xAxis: this.xAxis,
- popupItemsGetter: o.popupItemsGetter,
- formatConfig: BI.bind(this._formatConfig, this),
- element: this.element
- });
- this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
- self.fireEvent(BI.ScatterChart.EVENT_CHANGE, obj);
- });
- this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
- self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
- });
- },
-
-
- _formatConfig: function (config, items) {
- var self = this;
- delete config.zoom;
- config.colors = this.config.chartColor;
- config.style = formatChartStyle();
- config.plotOptions.marker = {"symbol": "circle", "radius": 4.5, "enabled": true};
- formatCordon();
- this.formatChartLegend(config, this.config.chartLegend);
- config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
- config.plotOptions.dataLabels.formatter.identifier = "${X}${Y}";
-
- config.yAxis = this.yAxis;
- config.xAxis = this.xAxis;
-
- config.yAxis[0].formatter = self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators);
- formatNumberLevelInYaxis(this.config.leftYAxisNumberLevel);
- config.yAxis[0].title.text = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
- config.yAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + config.yAxis[0].title.text : config.yAxis[0].title.text;
- config.yAxis[0].gridLineWidth = this.config.showGridLine === true ? 1 : 0;
- config.yAxis[0].title.rotation = this.constants.ROTATION;
- config.yAxis[0].maxWidth = '40%';
-
- config.xAxis[0].formatter = self.formatTickInXYaxis(this.config.xAxisStyle, this.config.xAxisNumberLevel, this.config.rightNumSeparators);
- formatNumberLevelInXaxis(this.config.xAxisNumberLevel);
- config.xAxis[0].title.text = getXYAxisUnit(this.config.xAxisNumberLevel, this.constants.X_AXIS);
- config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle + config.xAxis[0].title.text : config.xAxis[0].title.text;
- config.xAxis[0].title.align = "center";
- config.xAxis[0].gridLineWidth = this.config.showGridLine === true ? 1 : 0;
- config.xAxis[0].maxHeight = '40%';
- config.chartType = "scatter";
-
- if (BI.isNotEmptyArray(this.config.tooltip)) {
- config.plotOptions.tooltip.formatter = function () {
- var y = self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)(this.y);
- var x = self.formatTickInXYaxis(self.config.xAxisStyle, self.config.xAxisNumberLevel, self.config.rightNumSeparators)(this.x);
- return this.seriesName + '
(X)' + self.config.tooltip[0]
- + ':' + x + '
(Y)' + self.config.tooltip[1] + ':' + y + '
'
- };
- }
-
- if (config.plotOptions.dataLabels.enabled === true) {
- BI.each(items, function (idx, item) {
- item.dataLabels = {
- "style": self.config.chartFont,
- "align": "outside",
- "autoAdjust": true,
- enabled: true,
- formatter: {
- identifier: "${X}${Y}",
- "XFormat": function () {
- return BI.contentFormat(arguments[0], '#.##;-#.##')
- },
- "YFormat": function () {
- return BI.contentFormat(arguments[0], '#.##;-#.##')
- }
- }
- };
- item.dataLabels.formatter.XFormat = config.xAxis[0].formatter;
- item.dataLabels.formatter.YFormat = config.yAxis[0].formatter;
- });
- }
-
- //全局样式图表文字
- config.legend.style = this.config.chartFont;
- config.yAxis[0].title.style = config.yAxis[0].labelStyle = this.config.chartFont;
- config.xAxis[0].title.style = config.xAxis[0].labelStyle = this.config.chartFont;
-
- return [items, config];
-
- function formatChartStyle() {
- switch (self.config.chartStyle) {
- case BICst.CHART_STYLE.STYLE_GRADUAL:
- return "gradual";
- case BICst.CHART_STYLE.STYLE_NORMAL:
- default:
- return "normal";
- }
- }
-
- function formatCordon() {
- BI.each(self.config.cordon, function (idx, cor) {
- if (idx === 0 && self.xAxis.length > 0) {
- var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
- self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style": self.config.chartFont,
- "text": t.text,
- "align": "top"
- }
- });
- });
- }
- if (idx > 0 && self.yAxis.length >= idx) {
- var magnify = 1;
- switch (idx - 1) {
- case self.constants.LEFT_AXIS:
- magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS:
- magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
- break;
- case self.constants.RIGHT_AXIS_SECOND:
- magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
- break;
- }
- self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
- return BI.extend(t, {
- value: t.value.div(magnify),
- width: 1,
- label: {
- "style": self.config.chartFont,
- "text": t.text,
- "align": "left"
- }
- });
- });
- }
- })
- }
-
- function formatNumberLevelInXaxis(type) {
- var magnify = self.calcMagnify(type);
- BI.each(items, function (idx, item) {
- BI.each(item.data, function (id, da) {
- da.x = self.formatXYDataWithMagnify(da.x, magnify);
- })
- })
- }
-
- function formatNumberLevelInYaxis(type) {
- var magnify = self.calcMagnify(type);
- BI.each(items, function (idx, item) {
- BI.each(item.data, function (id, da) {
- da.y = self.formatXYDataWithMagnify(da.y, magnify);
- })
- });
- }
-
- function getXYAxisUnit(numberLevelType, position) {
- var unit = "";
- switch (numberLevelType) {
- case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
- unit = "";
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
- unit = BI.i18nText("BI-Wan");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
- unit = BI.i18nText("BI-Million");
- break;
- case BICst.TARGET_STYLE.NUM_LEVEL.YI:
- unit = BI.i18nText("BI-Yi");
- break;
- }
- if (position === self.constants.X_AXIS) {
- self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
- }
- if (position === self.constants.LEFT_AXIS) {
- self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
- }
- if (position === self.constants.RIGHT_AXIS) {
- self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
- }
- return unit === "" ? unit : "(" + unit + ")";
- }
- },
-
- populate: function (items, options) {
- options || (options = {});
- var self = this, c = this.constants;
- this.config = {
- leftYAxisTitle: options.leftYAxisTitle || "",
- chartColor: options.chartColor || [],
- leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
- xAxisStyle: options.xAxisStyle || c.NORMAL,
- showXAxisTitle: options.showXAxisTitle || false,
- showLeftYAxisTitle: options.showLeftYAxisTitle || false,
- xAxisNumberLevel: options.xAxisNumberLevel || c.NORMAL,
- leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
- xAxisUnit: options.xAxisUnit || "",
- leftYAxisUnit: options.leftYAxisUnit || "",
- xAxisTitle: options.xAxisTitle || "",
- chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
- showDataLabel: options.showDataLabel || false,
- showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
- cordon: options.cordon || [],
- tooltip: options.tooltip || [],
- numSeparators: options.numSeparators || false,
- rightNumSeparators: options.rightNumSeparators || false,
- chartFont: options.chartFont || c.FONT_STYLE
- };
- this.options.items = items;
- var types = [];
- BI.each(items, function (idx, axisItems) {
- var type = [];
- BI.each(axisItems, function (id, item) {
- type.push(BICst.WIDGET.SCATTER);
- });
- types.push(type);
- });
- this.combineChart.populate(items, types);
- },
-
- resize: function () {
- this.combineChart.resize();
- },
-
- magnify: function () {
- this.combineChart.magnify();
- }
-});
-BI.ScatterChart.EVENT_CHANGE = "EVENT_CHANGE";
+/**
+ * 图表控件
+ * @class BI.Chart
+ * @extends BI.Widget
+ */
+BI.Chart = BI.inherit(BI.Pane, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.Chart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-chart"
+ })
+ },
+
+ _init: function () {
+ BI.Chart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+
+ this.isSetOptions = false;
+ this.vanCharts = VanCharts.init(self.element[0]);
+
+ this._resizer = BI.debounce(function () {
+ if (self.element.width() > 0 && self.element.height() > 0) {
+ self.vanCharts.resize();
+ }
+ }, 30);
+ BI.ResizeDetector.addResizeListener(this, function (e) {
+ self._resizer();
+ });
+ },
+
+ resize: function () {
+ if (this.isSetOptions === true) {
+ this._resizer();
+ }
+ },
+
+ magnify: function () {
+ this.vanCharts.refreshRestore()
+ },
+
+ populate: function (items, options) {
+ var self = this, o = this.options;
+ o.items = items;
+ this.config = options || {};
+ this.config.series = o.items;
+
+ var setOptions = function () {
+ self.vanCharts.setOptions(self.config);
+ self.isSetOptions = true;
+ };
+ BI.nextTick(setOptions);
+ }
+});
+BI.Chart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.chart', BI.Chart);/**
+ * 图表控件
+ * @class BI.CombineChart
+ * @extends BI.Widget
+ */
+BI.CombineChart = BI.inherit(BI.Widget, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.CombineChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-combine-chart",
+ items: [],
+ xAxis: [{type: "category"}],
+ yAxis: [{type: "value"}],
+ types: [[], []],
+ popupItemsGetter: BI.emptyFn,
+ formatConfig: BI.emptyFn
+ })
+ },
+
+ _init: function () {
+ BI.CombineChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+
+ //图可配置属性
+ this.CombineChart = BI.createWidget({
+ type: "bi.chart",
+ element: this.element
+ });
+ this.CombineChart.on(BI.Chart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.CombineChart.EVENT_CHANGE, obj);
+ });
+
+ if (BI.isNotEmptyArray(o.items)) {
+ this.populate(o.items);
+ }
+ },
+
+ _formatItems: function (items) {
+ var result = [], self = this, o = this.options;
+ var yAxisIndex = 0;
+ BI.each(items, function (i, belongAxisItems) {
+ var combineItems = BI.ChartCombineFormatItemFactory.combineItems(o.types[i], belongAxisItems);
+ BI.each(combineItems, function (j, axisItems) {
+ if (BI.isArray(axisItems)) {
+ result = BI.concat(result, axisItems);
+ } else {
+ result.push(BI.extend(axisItems, {"yAxis": yAxisIndex}));
+ }
+ });
+ if (BI.isNotEmptyArray(combineItems)) {
+ yAxisIndex++;
+ }
+ });
+ var config = BI.ChartCombineFormatItemFactory.combineConfig();
+ config.plotOptions.click = function () {
+ var data = BI.clone(this.options);
+ data.toolTipRect = this.getTooltipRect();
+ var items = o.popupItemsGetter(data);
+ if (items && items.length === 1) {
+ self.fireEvent(BI.CombineChart.EVENT_ITEM_CLICK, BI.extend({}, items[0], data));
+ }
+ if (items && items.length > 1) {
+ self._createPopup(items, data.toolTipRect, data);
+ }
+ self.fireEvent(BI.CombineChart.EVENT_CHANGE, data);
+ };
+ return [result, config];
+ },
+
+ _createPopup: function (items, rect, opt) {
+ var self = this;
+ if (this.combo) {
+ this.combo.destroy();
+ }
+ this._doDestroy = true;
+ this.combo = BI.createWidget({
+ type: "bi.combo",
+ direction: "bottom",
+ isNeedAdjustWidth: false,
+ popup: {
+ el: BI.createWidget({
+ type: "bi.vertical",
+ cls: "bi-linkage-list",
+ items: BI.map(items, function (i, item) {
+ return {
+ el: BI.extend({
+ type: "bi.text_button",
+ cls: "bi-linkage-list-item",
+ height: 30,
+ handler: function () {
+ self.fireEvent(BI.CombineChart.EVENT_ITEM_CLICK, BI.extend({}, item, opt));
+ self.combo.destroy();
+ },
+ hgap: 10
+ }, item)
+ }
+ })
+ })
+ },
+ width: 0
+ });
+ BI.createWidget({
+ type: "bi.absolute",
+ element: this.element,
+ items: [{
+ el: this.combo,
+ top: rect.y,
+ left: rect.x
+ }]
+ });
+ this.combo.element.hover(function () {
+ self._doDestroy = false;
+ }, function () {
+ self._doDestroy = true;
+ self._debounce2Destroy();
+ });
+ this._debounce2Destroy = BI.debounce(BI.bind(destroyCombo, this.combo), 3000);
+ this.combo.showView();
+ this._debounce2Destroy();
+
+ function destroyCombo() {
+ if (self._doDestroy) {
+ this.destroy();
+ }
+ }
+ },
+
+ setTypes: function (types) {
+ this.options.types = types || [[]];
+ },
+
+ populate: function (items, types) {
+ var o = this.options;
+ if (BI.isNotNull(types)) {
+ this.setTypes(types);
+ }
+ var opts = this._formatItems(items);
+ BI.extend(opts[1], {
+ xAxis: o.xAxis,
+ yAxis: o.yAxis
+ });
+ var result = o.formatConfig(opts[1], opts[0]) || opts;
+ this.CombineChart.populate(result[0], result[1]);
+ },
+
+ resize: function () {
+ this.CombineChart.resize();
+ },
+
+ magnify: function () {
+ this.CombineChart.magnify();
+ }
+});
+BI.CombineChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.CombineChart.EVENT_ITEM_CLICK = "EVENT_ITEM_CLICK";
+BI.shortcut('bi.combine_chart', BI.CombineChart);BI.ChartCombineFormatItemFactory = {
+ combineItems: function (types, items) {
+ var calItems = BI.values(items);
+ return BI.map(calItems, function (idx, item) {
+ return BI.ChartCombineFormatItemFactory.formatItems(types[idx], item);
+ });
+ },
+
+ formatItems: function (type, items) {
+ var item = {};
+ switch (type) {
+ case BICst.WIDGET.BAR:
+ case BICst.WIDGET.ACCUMULATE_BAR:
+ case BICst.WIDGET.COMPARE_BAR:
+ item = BI.extend({"type": "bar"}, items);
+ break;
+ case BICst.WIDGET.BUBBLE:
+ item = BI.extend({"type": "bubble"}, items);
+ break;
+ case BICst.WIDGET.FORCE_BUBBLE:
+ item = BI.extend({"type": "forceBubble"}, items);
+ break;
+ case BICst.WIDGET.SCATTER:
+ item = BI.extend({"type": "scatter"}, items);
+ break;
+ case BICst.WIDGET.AXIS:
+ case BICst.WIDGET.ACCUMULATE_AXIS:
+ case BICst.WIDGET.PERCENT_ACCUMULATE_AXIS:
+ case BICst.WIDGET.COMPARE_AXIS:
+ case BICst.WIDGET.FALL_AXIS:
+ item = BI.extend({"type": "column"}, items);
+ break;
+ case BICst.WIDGET.LINE:
+ item = BI.extend({"type": "line"}, items);
+ break;
+ case BICst.WIDGET.AREA:
+ case BICst.WIDGET.ACCUMULATE_AREA:
+ case BICst.WIDGET.COMPARE_AREA:
+ case BICst.WIDGET.RANGE_AREA:
+ case BICst.WIDGET.PERCENT_ACCUMULATE_AREA:
+ item = BI.extend({"type": "area"}, items);
+ break;
+ case BICst.WIDGET.DONUT:
+ item = BI.extend({"type": "pie"}, items);
+ break;
+ case BICst.WIDGET.RADAR:
+ case BICst.WIDGET.ACCUMULATE_RADAR:
+ item = BI.extend({"type": "radar"}, items);
+ break;
+ case BICst.WIDGET.PIE:
+ item = BI.extend({"type": "pie"}, items);
+ break;
+ case BICst.WIDGET.DASHBOARD:
+ item = BI.extend({"type": "gauge"}, items);
+ break;
+ case BICst.WIDGET.MAP:
+ item = BI.extend({"type": "areaMap"}, items);
+ break;
+ case BICst.WIDGET.GIS_MAP:
+ item = BI.extend({"type": "pointMap"}, items);
+ break;
+ default:
+ item = BI.extend({"type": "column"}, items);
+ break;
+ }
+ return item;
+ },
+
+ combineConfig: function () {
+ return {
+ "title": "",
+ "chartType": "column",
+ "plotOptions": {
+ "rotatable": false,
+ "startAngle": 0,
+ "borderRadius": 0,
+ "endAngle": 360,
+ "innerRadius": "0.0%",
+ "layout": "horizontal",
+ "hinge": "rgb(101,107,109)",
+ "dataLabels": {
+ "autoAdjust": true,
+ "style": {"fontFamily": "inherit", "color": "inherit", "fontSize": "12px"},
+ "formatter": {
+ "identifier": "${VALUE}",
+ "valueFormat": this._contentFormat2Decimal,
+ "seriesFormat": this._contentFormat,
+ "percentFormat": this._contentFormatPercentage,
+ "categoryFormat": this._contentFormat,
+ "XFormat": this._contentFormat2Decimal,
+ "YFormat": this._contentFormat2Decimal,
+ "sizeFormat": this._contentFormat2Decimal
+ },
+ "align": "outside",
+ "enabled": false
+ },
+ "percentageLabel": {
+ "formatter": {
+ "identifier": "${PERCENT}",
+ "valueFormat": this._contentFormat2Decimal,
+ "seriesFormat": this._contentFormat,
+ "percentFormat": this._contentFormatPercentage,
+ "categoryFormat": this._contentFormat
+ },
+ "style": {
+ "fontFamily": "inherit", "color": "inherit", "fontSize": "12px"
+ },
+ "align": "bottom",
+ "enabled": true
+ },
+ "valueLabel": {
+ "formatter": {
+ "identifier": "${SERIES}${VALUE}",
+ "valueFormat": this._contentFormat2Decimal,
+ "seriesFormat": this._contentFormat,
+ "percentFormat": this._contentFormatPercentage,
+ "categoryFormat": this._contentFormat
+ },
+ "backgroundColor": "rgb(255,255,0)",
+ "style": {
+ "fontFamily": "inherit", "color": "inherit", "fontSize": "12px"
+ },
+ "align": "inside",
+ "enabled": true
+ },
+ "hingeBackgroundColor": "rgb(220,242,249)",
+ "seriesLabel": {
+ "formatter": {
+ "identifier": "${CATEGORY}",
+ "valueFormat": this._contentFormat2Decimal,
+ "seriesFormat": this._contentFormat,
+ "percentFormat": this._contentFormatPercentage,
+ "categoryFormat": this._contentFormat
+ },
+ "style": {
+ "fontFamily": "inherit", "color": "inherit", "fontSize": "12px"
+ },
+ "align": "bottom",
+ "enabled": true
+ },
+ "paneBackgroundColor": "rgb(252,252,252)",
+ "needle": "rgb(229,113,90)",
+ "large": false,
+ "connectNulls": false,
+ "shadow": true,
+ "curve": false,
+ "sizeBy": "area",
+ "tooltip": {
+ "formatter": {
+ "identifier": "${SERIES}${X}${Y}${SIZE}{CATEGORY}${SERIES}${VALUE}",
+ "valueFormat": this._contentFormat2Decimal,
+ "seriesFormat": this._contentFormat,
+ "percentFormat": this._contentFormatPercentage,
+ "categoryFormat": this._contentFormat,
+ "XFormat": this._contentFormat2Decimal,
+ "sizeFormat": this._contentFormat2Decimal,
+ "YFormat": this._contentFormat2Decimal
+ },
+ "shared": false,
+ "padding": 5,
+ "backgroundColor": "rgba(0,0,0,0.4980392156862745)",
+ "borderColor": "rgb(0,0,0)",
+ "shadow": false,
+ "borderRadius": 2,
+ "borderWidth": 0,
+ "follow": false,
+ "enabled": true,
+ "animation": true,
+ "style": {
+ "fontFamily": "Microsoft YaHei, Hiragino Sans GB W3",
+ "color": "#c4c6c6",
+ "fontSize": "12px",
+ "fontWeight": ""
+ }
+ },
+ "maxSize": 80,
+ "fillColorOpacity": 0.5,
+ "step": false,
+ "force": false,
+ "minSize": 15,
+ "displayNegative": true,
+ "categoryGap": "16.0%",
+ "borderColor": "rgb(255,255,255)",
+ "borderWidth": 1,
+ "gap": "22.0%",
+ "animation": true,
+ "lineWidth": 2,
+ "bubble": {
+ "large": false,
+ "connectNulls": false,
+ "shadow": true,
+ "curve": false,
+ "sizeBy": "area",
+ "maxSize": 80,
+ "minSize": 15,
+ "lineWidth": 0,
+ "animation": true,
+ "fillColorOpacity": 0.699999988079071,
+ "marker": {
+ "symbol": "circle",
+ "radius": 28.39695010101295,
+ "enabled": true
+ }
+ }
+ },
+ "dTools": {
+ "enabled": false,
+ "style": {
+ "fontFamily": "Microsoft YaHei, Hiragino Sans GB W3",
+ "color": "#1a1a1a",
+ "fontSize": "12px"
+ },
+ "backgroundColor": 'white'
+ },
+ "dataSheet": {
+ "enabled": false,
+ "borderColor": "rgb(0,0,0)",
+ "borderWidth": 1,
+ "formatter": this._contentFormat2Decimal,
+ "style": {
+ "fontFamily": "inherit", "color": "inherit", "fontSize": "12px"
+ }
+ },
+ "borderColor": "rgb(238,238,238)",
+ "shadow": false,
+ "legend": {
+ "borderColor": "rgb(204,204,204)",
+ "borderRadius": 0,
+ "shadow": false,
+ "borderWidth": 0,
+ "visible": true,
+ "style": {
+ "fontFamily": "inherit", "color": "inherit", "fontSize": "12px"
+ },
+ "position": "right",
+ "enabled": false
+ },
+ "rangeLegend": {
+ "range": {
+ "min": 0,
+ "color": [
+ [
+ 0,
+ "rgb(182,226,255)"
+ ],
+ [
+ 0.5,
+ "rgb(109,196,255)"
+ ],
+ [
+ 1,
+ "rgb(36,167,255)"
+ ]
+ ],
+ "max": 266393
+ },
+ "enabled": false
+ },
+ "zoom": {"zoomType": "xy", "zoomTool": {"visible": false, "resize": true, "from": "", "to": ""}},
+ "plotBorderColor": "rgba(255,255,255,0)",
+ "tools": {
+ "hidden": false,
+ "toImage": {"enabled": false},
+ "sort": {"enabled": false},
+ "fullScreen": {"enabled": false},
+ "refresh": {
+ "enabled": false
+ }
+ },
+ "plotBorderWidth": 0,
+ "style": "normal",
+ "colors": ["rgb(99,178,238)", "rgb(118,218,145)"],
+ "borderRadius": 0,
+ "borderWidth": 0,
+ "plotShadow": false,
+ "plotBorderRadius": 0
+ };
+ },
+
+ _contentFormat: function () {
+ return BI.contentFormat(arguments[0], '')
+ },
+
+ _contentFormat2Decimal: function () {
+ return BI.contentFormat(arguments[0], '#.##;-#.##')
+ },
+
+ _contentFormatPercentage: function () {
+ return BI.contentFormat(arguments[0], '#.##%;-#.##%')
+ }
+};/**
+ * 图表控件
+ * @class BI.AbstractChart
+ * @extends BI.Widget
+ */
+BI.AbstractChart = BI.inherit(BI.Widget, {
+
+ constants: {
+ LEFT_AXIS: 0,
+ RIGHT_AXIS: 1,
+ RIGHT_AXIS_SECOND: 2,
+ X_AXIS: 3,
+ ROTATION: -90,
+ NORMAL: 1,
+ LEGEND_BOTTOM: 4,
+ ZERO2POINT: 2,
+ ONE2POINT: 3,
+ TWO2POINT: 4,
+ MINLIMIT: 1e-5,
+ LEGEND_HEIGHT: 80,
+ LEGEND_WIDTH: "30.0%",
+ FIX_COUNT: 6,
+ STYLE_NORMAL: 21,
+ NO_PROJECT: 16,
+ DASHBOARD_AXIS: 4,
+ ONE_POINTER: 1,
+ MULTI_POINTER: 2,
+ HALF_DASHBOARD: 9,
+ PERCENT_DASHBOARD: 10,
+ PERCENT_SCALE_SLOT: 11,
+ VERTICAL_TUBE: 12,
+ HORIZONTAL_TUBE: 13,
+ LNG_FIRST: 3,
+ LAT_FIRST: 4,
+ themeColor: "#65bce7",
+ autoCustom: 1,
+ POLYGON: 7,
+ AUTO_CUSTOM: 1,
+ AUTO: 1,
+ NOT_SHOW: 2,
+ LINE_WIDTH: 1,
+ NUM_SEPARATORS: false,
+ FONT_STYLE: {
+ "fontFamily": "inherit",
+ "color": "inherit",
+ "fontSize": "12px"
+ }
+ },
+
+ _defaultConfig: function () {
+ return BI.extend(BI.AbstractChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-abstract-chart",
+ popupItemsGetter: BI.emptyFn
+ })
+ },
+
+ _init: function () {
+ BI.AbstractChart.superclass._init.apply(this, arguments);
+ },
+
+ /**
+ * 格式化坐标轴数量级及其所影响的系列的各项属性
+ * @param config 配置信息
+ * @param items 系列数据
+ * @param type 坐标轴数量级
+ * @param position 坐标轴位置
+ * @param formatter 系列tooltip格式化内容
+ */
+ formatNumberLevelInYaxis: function (config, items, type, position, formatter, isPercentChart) {
+ var magnify = this.calcMagnify(type);
+ BI.each(items, function (idx, item) {
+ BI.each(item.data, function (id, da) {
+ if (position === item.yAxis) {
+ if (BI.isNotNull(da.y) && !BI.isNumber(da.y)) {
+ da.y = BI.parseFloat(da.y);
+ }
+ if (BI.isNotNull(da.y)) {
+ da.y = BI.contentFormat(BI.parseFloat(da.y.div(magnify).toFixed(4)), "#.####;-#.####");
+ }
+ }
+ });
+ if (position === item.yAxis) {
+ item.tooltip = BI.deepClone(config.plotOptions.tooltip);
+ item.tooltip.formatter.valueFormat = formatter;
+ if(isPercentChart) {
+ item.tooltip.formatter.percentFormat = formatter;
+ item.tooltip.formatter.identifier = "${CATEGORY}${SERIES}${PERCENT}";
+ }
+ }
+ });
+ },
+
+ formatNumberLevelInXaxis: function (items, type) {
+ var magnify = this.calcMagnify(type);
+ BI.each(items, function (idx, item) {
+ BI.each(item.data, function (id, da) {
+ if (BI.isNotNull(da.x) && !BI.isNumber(da.x)) {
+ da.x = BI.parseFloat(da.x);
+ }
+ if (BI.isNotNull(da.x)) {
+ da.x = BI.contentFormat(BI.parseFloat(da.x.div(magnify).toFixed(4)), "#.####;-#.####");
+ }
+ });
+ })
+ },
+
+ formatXYDataWithMagnify: function (number, magnify) {
+ if (BI.isNull(number)) {
+ return null
+ }
+ if (!BI.isNumber(number)) {
+ number = BI.parseFloat(number);
+ }
+ return BI.contentFormat(BI.parseFloat(number.div(magnify).toFixed(4)), "#.####;-#.####");
+ },
+
+ calcMagnify: function (type) {
+ var magnify = 1;
+ switch (type) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ case BICst.TARGET_STYLE.NUM_LEVEL.PERCENT:
+ magnify = 1;
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ magnify = 10000;
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ magnify = 1000000;
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ magnify = 100000000;
+ break;
+ }
+ return magnify;
+ },
+
+ formatChartLegend: function (config, chartLegend) {
+ switch (chartLegend) {
+ case BICst.CHART_LEGENDS.BOTTOM:
+ config.legend.enabled = true;
+ config.legend.position = "bottom";
+ config.legend.maxHeight = this.constants.LEGEND_HEIGHT;
+ break;
+ case BICst.CHART_LEGENDS.RIGHT:
+ config.legend.enabled = true;
+ config.legend.position = "right";
+ config.legend.maxWidth = this.constants.LEGEND_WIDTH;
+ break;
+ case BICst.CHART_LEGENDS.NOT_SHOW:
+ default:
+ config.legend.enabled = false;
+ break;
+ }
+ },
+
+ getXYAxisUnit: function (numberLevelType, axis_unit) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ return (BI.isEmptyString(unit) && BI.isEmptyString(axis_unit)) ? unit : "(" + unit + axis_unit + ")";
+ },
+
+ formatTickInXYaxis: function (type, number_level, separators, isCompareBar) {
+ var formatter = '#.##';
+ switch (type) {
+ case this.constants.NORMAL:
+ formatter = '#.##';
+ if (separators) {
+ formatter = '#,###.##'
+ }
+ break;
+ case this.constants.ZERO2POINT:
+ formatter = '#0';
+ if (separators) {
+ formatter = '#,###';
+ }
+ break;
+ case this.constants.ONE2POINT:
+ formatter = '#0.0';
+ if (separators) {
+ formatter = '#,###.0';
+ }
+ break;
+ case this.constants.TWO2POINT:
+ formatter = '#0.00';
+ if (separators) {
+ formatter = '#,###.00';
+ }
+ break;
+ }
+ if (number_level === BICst.TARGET_STYLE.NUM_LEVEL.PERCENT) {
+ formatter += '%';
+ }
+ formatter += ";-" + formatter;
+ if(isCompareBar) {
+ return function () {
+ arguments[0] = arguments[0] > 0 ? arguments[0] : (-1) * arguments[0];
+ return BI.contentFormat(arguments[0], formatter);
+ }
+ }
+ return function () {
+ return BI.contentFormat(arguments[0], formatter)
+ }
+ },
+
+ formatDataLabel: function (state, items, config, style) {
+ var self = this;
+ if (state === true) {
+ BI.each(items, function (idx, item) {
+ item.dataLabels = {
+ "align": "outside",
+ "autoAdjust": true,
+ style: style,
+ enabled: true,
+ formatter: {
+ identifier: "${VALUE}",
+ valueFormat: config.yAxis[item.yAxis].formatter
+ }
+ };
+ });
+ }
+ },
+
+ formatDataLabelForAxis: function (state, items, format, style, isPercentChart) {
+ var self = this;
+ if (state === true) {
+ BI.each(items, function (idx, item) {
+ item.dataLabels = {
+ "align": "outside",
+ "autoAdjust": true,
+ style: style,
+ enabled: true,
+ formatter: {
+ identifier: "${VALUE}",
+ valueFormat: format,
+ }
+ };
+ if(isPercentChart) {
+ item.dataLabels.formatter.identifier = "${PERCENT}";
+ item.dataLabels.formatter.percentFormat = format;
+ }
+ });
+ }
+ },
+
+ setFontStyle: function (fontStyle, config) {
+ if (config.dataSheet) {
+ config.dataSheet.style = fontStyle;
+ }
+ config.xAxis[0].title.style = fontStyle;
+ config.xAxis[0].labelStyle = fontStyle;
+ config.legend.style = fontStyle;
+ BI.each(config.yAxis, function (idx, axis) {
+ axis.labelStyle = fontStyle;
+ axis.title.style = fontStyle;
+ })
+ },
+
+ _formatItems: function (items) {
+ return items;
+ },
+
+ populate: function (items, options) {
+ },
+
+ resize: function () {
+ },
+
+ magnify: function () {
+ }
+});
+
+BI.AbstractChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.AbstractChart.EVENT_ITEM_CLICK = "EVENT_ITEM_CLICK";
+/**
+ * 图表控件
+ * @class BI.AccumulateAreaChart
+ * @extends BI.Widget
+ */
+BI.AccumulateAreaChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.AccumulateAreaChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-accumulate-area-chart"
+ })
+ },
+
+ _init: function () {
+ BI.AccumulateAreaChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+
+ this.xAxis = [{
+ type: "category",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE
+ }];
+ this.yAxis = [];
+
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.AccumulateAreaChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this;
+
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle(this.config.chartStyle);
+ formatChartLineStyle(this.config.chartLineType);
+ formatCordon(this.config.cordon);
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.plotOptions.connectNulls = this.config.nullContinue;
+ config.dataSheet.enabled = this.config.showDataTable;
+ config.xAxis[0].showLabel = !config.dataSheet.enabled;
+ config.zoom.zoomTool.enabled = this.config.showZoom;
+ if (this.config.showZoom === true) {
+ delete config.dataSheet;
+ delete config.zoom.zoomType;
+ }
+
+ config.yAxis = this.yAxis;
+ BI.each(config.yAxis, function (idx, axis) {
+ var unit = "";
+ switch (axis.axisIndex) {
+ case self.constants.LEFT_AXIS:
+ unit = self.getXYAxisUnit(self.config.leftYAxisNumberLevel, self.config.leftYAxisUnit);
+ axis.title.text = self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + unit : unit;
+ axis.title.rotation = self.constants.ROTATION;
+ BI.extend(axis, {
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ reversed: self.config.leftYAxisReversed,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)
+ });
+ self.formatNumberLevelInYaxis(config, items, self.config.leftYAxisNumberLevel, idx, axis.formatter, self.config.numSeparators);
+
+ break;
+ case self.constants.RIGHT_AXIS:
+ unit = self.getXYAxisUnit(self.config.rightYAxisNumberLevel, self.config.rightYAxisUnit);
+ axis.title.text = self.config.showRightYAxisTitle === true ? self.config.rightYAxisTitle + unit : unit;
+ axis.title.rotation = self.constants.ROTATION;
+ BI.extend(axis, {
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ reversed: self.config.rightYAxisReversed,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators)
+ });
+ self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisNumberLevel, idx, axis.formatter, self.config.rightNumSeparators);
+ break;
+ }
+ });
+
+ config.xAxis[0].title.align = "center";
+ config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
+ BI.extend(config.xAxis[0], {
+ lineWidth: this.config.lineWidth,
+ enableTick: this.config.enableTick,
+ labelRotation: this.config.textDirection,
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ maxHeight: '40%'
+ });
+
+ config.chartType = "area";
+
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
+
+ //全局样式的图表文字
+ this.setFontStyle(this.config.chartFont, config);
+
+ return [items, config];
+
+ function formatChartStyle(v) {
+ switch (v) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatChartLineStyle(v) {
+ switch (v) {
+ case BICst.CHART_SHAPE.RIGHT_ANGLE:
+ config.plotOptions.curve = false;
+ config.plotOptions.step = true;
+ break;
+ case BICst.CHART_SHAPE.CURVE:
+ config.plotOptions.curve = true;
+ config.plotOptions.step = false;
+ break;
+ case BICst.CHART_SHAPE.NORMAL:
+ default:
+ config.plotOptions.curve = false;
+ config.plotOptions.step = false;
+ break;
+ }
+ }
+
+ function formatCordon(cordon) {
+ BI.each(cordon, function (idx, cor) {
+ if (idx === 0 && self.xAxis.length > 0) {
+ var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if (idx > 0 && self.yAxis.length >= idx) {
+ var magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ }
+ },
+
+ _formatItems: function (items) {
+ return BI.map(items, function (idx, item) {
+ var i = BI.UUID();
+ return BI.map(item, function (id, it) {
+ return BI.extend({}, it, {stack: i});
+ });
+ });
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ rightYAxisTitle: options.rightYAxisTitle || "",
+ chartColor: options.chartColor || [],
+ chartStyle: options.chartStyle || c.STYLE_NORMAL,
+ chartLineType: options.chartLineType || c.NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ showRightYAxisTitle: options.showRightYAxisTitle || false,
+ leftYAxisReversed: options.leftYAxisReversed || false,
+ rightYAxisReversed: options.rightYAxisReversed || false,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ rightYAxisUnit: options.rightYAxisUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showDataTable: options.showDataTable || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ showZoom: options.showZoom || false,
+ textDirection: options.textDirection || 0,
+ cordon: options.cordon || [],
+ lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
+ showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
+ enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
+ enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
+ numSeparators: options.numSeparators || false,
+ rightNumSeparators: options.rightNumSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE,
+ nullContinue: options.nullContinue || false
+ };
+ this.options.items = items;
+ this.yAxis = [];
+ var types = [];
+ BI.each(items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function (id, item) {
+ type.push(BICst.WIDGET.AREA);
+ });
+ types.push(type);
+ });
+ BI.each(types, function (idx, type) {
+ if (BI.isEmptyArray(type)) {
+ return;
+ }
+ var newYAxis = {
+ type: "value",
+ title: {
+ style: self.constants.FONT_STYLE
+ },
+ labelStyle: self.constants.FONT_STYLE,
+ position: idx > 0 ? "right" : "left",
+ lineWidth: 1,
+ axisIndex: idx,
+ gridLineWidth: 0
+ };
+ self.yAxis.push(newYAxis);
+ });
+ this.combineChart.populate(this._formatItems(items), types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.AccumulateAreaChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.accumulate_area_chart', BI.AccumulateAreaChart);/**
+ * 图表控件
+ * @class BI.AccumulateAxisChart
+ * @extends BI.Widget
+ */
+BI.AccumulateAxisChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.AccumulateAxisChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-accumulate-axis-chart"
+ })
+ },
+
+ _init: function () {
+ BI.AccumulateAxisChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.xAxis = [{
+ type: "category",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE
+ }];
+ this.yAxis = [];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.AccumulateAxisChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this, o = this.options;
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ formatCordon();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.dataSheet.enabled = this.config.showDataTable;
+ config.xAxis[0].showLabel = !config.dataSheet.enabled;
+ config.zoom.zoomTool.enabled = this.config.showZoom;
+ if (this.config.showZoom === true) {
+ delete config.dataSheet;
+ delete config.zoom.zoomType;
+ }
+
+ config.yAxis = this.yAxis;
+ BI.each(config.yAxis, function (idx, axis) {
+ switch (axis.axisIndex) {
+ case self.constants.LEFT_AXIS:
+ axis.title.text = getTitleText(self.config.leftYAxisNumberLevel, self.constants.LEFT_AXIS, self.config.showLeftYAxisTitle, self.config.leftYAxisTitle);
+ axis.title.rotation = self.constants.ROTATION;
+ BI.extend(axis, {
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ reversed: self.config.leftYAxisReversed,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)
+ });
+ self.formatNumberLevelInYaxis(config, items, self.config.leftYAxisNumberLevel, idx, axis.formatter);
+ break;
+ case self.constants.RIGHT_AXIS:
+ axis.title.text = getTitleText(self.config.rightYAxisNumberLevel, self.constants.RIGHT_AXIS, self.config.showRightYAxisTitle, self.config.rightYAxisTitle);
+ axis.title.rotation = self.constants.ROTATION;
+ BI.extend(axis, {
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ reversed: self.config.rightYAxisReversed,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators)
+ });
+ self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisNumberLevel, idx, axis.formatter);
+ break;
+ }
+ });
+
+ config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
+ config.xAxis[0].title.align = "center";
+ BI.extend(config.xAxis[0], {
+ lineWidth: self.config.lineWidth,
+ enableTick: self.config.enableTick,
+ labelRotation: this.config.textDirection,
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ maxHeight: '40%'
+ });
+
+ config.chartType = "column";
+
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
+
+ //全局样式的图表文字
+ this.setFontStyle(this.config.chartFont, config);
+
+ return [items, config];
+
+ function formatCordon() {
+ BI.each(self.config.cordon, function (idx, cor) {
+ if (idx === 0 && self.xAxis.length > 0) {
+ var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if (idx > 0 && self.yAxis.length >= idx) {
+ var magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ }
+
+ function formatChartStyle() {
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function getTitleText(numberLevelType, position, show, title) {
+ var unit = "";
+
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if (position === self.constants.X_AXIS) {
+ self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
+ }
+ if (position === self.constants.LEFT_AXIS) {
+ self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
+ }
+ if (position === self.constants.RIGHT_AXIS) {
+ self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
+ }
+
+ unit = unit === "" ? unit : "(" + unit + ")";
+
+ return show === true ? title + unit : unit;
+ }
+ },
+
+ _formatItems: function (items) {
+ return BI.map(items, function (idx, item) {
+ var i = BI.UUID();
+ return BI.map(item, function (id, it) {
+ return BI.extend({}, it, {stack: i});
+ });
+ });
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ rightYAxisTitle: options.rightYAxisTitle || "",
+ chartColor: options.chartColor || [],
+ chartStyle: options.chartStyle || c.STYLE_NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ showRightYAxisTitle: options.showRightYAxisTitle || false,
+ leftYAxisReversed: options.leftYAxisReversed || false,
+ rightYAxisReversed: options.rightYAxisReversed || false,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ rightYAxisUnit: options.rightYAxisUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showDataTable: options.showDataTable || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ showZoom: options.showZoom || false,
+ textDirection: options.textDirection || 0,
+ cordon: options.cordon || [],
+ lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
+ showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
+ enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
+ enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
+ numSeparators: options.numSeparators || false,
+ rightNumSeparators: options.rightNumSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE
+ };
+ this.options.items = items;
+ this.yAxis = [];
+ var types = [];
+ BI.each(items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function (id, item) {
+ type.push(BICst.WIDGET.AXIS);
+ });
+ types.push(type);
+ });
+ BI.each(types, function (idx, type) {
+ if (BI.isEmptyArray(type)) {
+ return;
+ }
+ var newYAxis = {
+ type: "value",
+ title: {
+ style: self.constants.FONT_STYLE
+ },
+ labelStyle: self.constants.FONT_STYLE,
+ position: idx > 0 ? "right" : "left",
+ lineWidth: 1,
+ axisIndex: idx,
+ gridLineWidth: 0
+ };
+ self.yAxis.push(newYAxis);
+ });
+ this.combineChart.populate(this._formatItems(items), types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.AccumulateAxisChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.accumulate_axis_chart', BI.AccumulateAxisChart);/**
+ * 图表控件
+ * @class BI.AccumulateBarChart
+ * @extends BI.Widget
+ */
+BI.AccumulateBarChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.AccumulateBarChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-accumulate-bar-chart"
+ })
+ },
+
+ _init: function () {
+ BI.AccumulateBarChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.xAxis = [{
+ type: "value",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ formatter: function () {
+ return this > 0 ? this : (-1) * this
+ },
+ gridLineWidth: 0
+ }];
+ this.yAxis = [{
+ type: "category",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ gridLineWidth: 0,
+ position: "left"
+ }];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.AccumulateBarChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this;
+ var unit = getXYAxisUnit(this.config.xAxisNumberLevel, this.constants.LEFT_AXIS);
+ var xTitle = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.X_AXIS);
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ formatCordon();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+
+ config.yAxis = this.yAxis;
+ config.yAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle + unit : unit;
+ config.yAxis[0].title.rotation = this.constants.ROTATION;
+ BI.extend(config.yAxis[0], {
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ labelRotation: this.config.textDirection,
+ lineWidth: this.config.lineWidth,
+ enableTick: this.config.enableTick,
+ maxWidth: '40%'
+ });
+
+ self.formatNumberLevelInXaxis(items, this.config.leftYAxisNumberLevel);
+ config.xAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + xTitle : xTitle;
+ config.xAxis[0].title.align = "center";
+ BI.extend(config.xAxis[0], {
+ formatter: self.formatTickInXYaxis(this.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators),
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ showLabel: this.config.showLabel,
+ enableTick: this.config.enableTick,
+ lineWidth: this.config.lineWidth,
+ enableMinorTick: this.config.enableMinorTick
+ });
+ config.chartType = "bar";
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ this.formatDataLabelForAxis(config.plotOptions.dataLabels.enabled, items, config.xAxis[0].formatter, this.config.chartFont);
+
+ config.plotOptions.tooltip.formatter.valueFormat = config.xAxis[0].formatter;
+
+ //全局样式的图表文字
+ this.setFontStyle(this.config.chartFont, config);
+
+ return [items, config];
+
+ function formatChartStyle() {
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatCordon() {
+ BI.each(self.config.cordon, function (idx, cor) {
+ if (idx === 0 && self.xAxis.length > 0) {
+ var magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if (idx > 0 && self.yAxis.length >= idx) {
+ var magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.xAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ }
+
+ function getXYAxisUnit(numberLevelType, position) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if (position === self.constants.X_AXIS) {
+ self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
+ }
+ if (position === self.constants.LEFT_AXIS) {
+ self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
+ }
+ if (position === self.constants.RIGHT_AXIS) {
+ self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
+ }
+ return unit === "" ? unit : "(" + unit + ")";
+ }
+ },
+
+ _formatItems: function (items) {
+ BI.each(items, function (idx, item) {
+ var stackId = BI.UUID();
+ BI.each(item, function (id, it) {
+ it.stack = stackId;
+ BI.each(it.data, function (i, t) {
+ var tmp = t.x;
+ t.x = t.y;
+ t.y = tmp;
+ })
+ });
+ });
+ return items;
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ chartColor: options.chartColor || [],
+ chartStyle: options.chartStyle || c.STYLE_NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ xAxisStyle: options.xAxisStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ leftYAxisReversed: options.leftYAxisReversed || false,
+ xAxisNumberLevel: options.xAxisNumberLevel || c.NORMAL,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showDataTable: options.showDataTable || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ showZoom: options.showZoom || false,
+ textDirection: options.textDirection || 0,
+ cordon: options.cordon || [],
+ minimalist_model: options.minimalist_model || false,
+ lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
+ showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
+ enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
+ enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
+ numSeparators: options.numSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE
+ };
+ this.options.items = items;
+ var types = [];
+ BI.each(items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function (id, item) {
+ type.push(BICst.WIDGET.BAR);
+ });
+ types.push(type);
+ });
+ this.combineChart.populate(this._formatItems(items), types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.AccumulateBarChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.accumulate_bar_chart', BI.AccumulateBarChart);/**
+ * 图表控件
+ * @class BI.AccumulateRadarChart
+ * @extends BI.Widget
+ */
+BI.AccumulateRadarChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.AccumulateRadarChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-accumulate-radar-chart"
+ })
+ },
+
+ _init: function () {
+ BI.AccumulateRadarChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.radiusAxis = [{
+ type: "value",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ formatter: function () {
+ return this > 0 ? this : (-1) * this
+ },
+ gridLineWidth: 0,
+ position: "bottom"
+ }];
+
+ this.angleAxis = [{
+ type: "category",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE
+ }];
+
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.AccumulateRadarChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatItems: function (items) {
+ return BI.map(items, function (idx, item) {
+ var i = BI.UUID();
+ return BI.map(item, function (id, it) {
+ return BI.extend({}, it, {stack: i});
+ });
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this;
+
+ delete config.zoom;
+
+ var title = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ formatChartRadarStyle();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.plotOptions.connectNulls = this.config.nullContinue;
+
+ config.radiusAxis = this.radiusAxis;
+ config.angleAxis = this.angleAxis;
+ config.radiusAxis[0].formatter = self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators);
+ formatNumberLevelInYaxis(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS, config.radiusAxis[0].formatter);
+ config.radiusAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + title : title;
+ config.radiusAxis[0].gridLineWidth = this.config.showGridLine === true ? 1 : 0;
+ config.chartType = "radar";
+ config.plotOptions.columnType = true;
+ delete config.xAxis;
+ delete config.yAxis;
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ this.formatDataLabelForAxis(config.plotOptions.dataLabels.enabled, items, config.radiusAxis[0].formatter, this.config.chartFont);
+
+ //全局样式的图表文字
+ config.radiusAxis[0].labelStyle = config.radiusAxis[0].title.style = this.config.chartFont;
+ config.angleAxis[0].labelStyle = config.angleAxis[0].title.style = this.config.chartFont;
+ config.legend.style = this.config.chartFont;
+
+ return [items, config];
+
+ function formatChartStyle() {
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatChartRadarStyle() {
+ switch (self.config.chartRadarType) {
+ case BICst.CHART_SHAPE.POLYGON:
+ config.plotOptions.shape = "polygon";
+ break;
+ case BICst.CHART_SHAPE.CIRCLE:
+ config.plotOptions.shape = "circle";
+ break;
+ }
+ }
+
+ function formatNumberLevelInYaxis(type, position, formatter) {
+ var magnify = self.calcMagnify(type);
+ BI.each(items, function (idx, item) {
+ BI.each(item.data, function (id, da) {
+ if (position === item.yAxis) {
+ da.y = self.formatXYDataWithMagnify(da.y, magnify);
+ }
+ })
+ });
+ config.plotOptions.tooltip.formatter.valueFormat = formatter;
+ }
+
+ function getXYAxisUnit(numberLevelType, position) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if (position === self.constants.X_AXIS) {
+ self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
+ }
+ if (position === self.constants.LEFT_AXIS) {
+ self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
+ }
+ if (position === self.constants.RIGHT_AXIS) {
+ self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
+ }
+ return unit === "" ? unit : "(" + unit + ")";
+ }
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ chartRadarType: options.chartRadarType || c.NORMAL,
+ chartColor: options.chartColor || [],
+ chartStyle: options.chartStyle || c.STYLE_NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ cordon: options.cordon || [],
+ numSeparators: options.numSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE,
+ nullContinue: options.nullContinue || false
+ };
+ this.options.items = items;
+ var types = [];
+ BI.each(items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function (id, item) {
+ type.push(BICst.WIDGET.RADAR);
+ });
+ types.push(type);
+ });
+ this.combineChart.populate(this._formatItems(items), types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.AccumulateRadarChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.accumulate_radar_chart', BI.AccumulateRadarChart);/**
+ * 图表控件
+ * @class BI.AreaChart
+ * @extends BI.Widget
+ */
+BI.AreaChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.AreaChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-area-chart"
+ })
+ },
+
+ _init: function () {
+ BI.AreaChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.xAxis = [{
+ type: "category",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ position: "bottom",
+ gridLineWidth: 0
+ }];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.AreaChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this;
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ formatChartLineStyle();
+ formatCordon();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.plotOptions.connectNulls = this.config.nullContinue;
+ config.dataSheet.enabled = this.config.showDataTable;
+ config.xAxis[0].showLabel = !config.dataSheet.enabled;
+ config.zoom.zoomTool.enabled = this.config.showZoom;
+ if (this.config.showZoom === true) {
+ delete config.dataSheet;
+ delete config.zoom.zoomType;
+ }
+
+ config.yAxis = this.yAxis;
+ BI.each(config.yAxis, function (idx, axis) {
+ var title = "";
+ switch (axis.axisIndex) {
+ case self.constants.LEFT_AXIS:
+ title = getXYAxisUnit(self.config.leftYAxisNumberLevel, self.constants.LEFT_AXIS);
+ axis.title.text = self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + title : title;
+ axis.title.rotation = self.constants.ROTATION;
+ BI.extend(axis, {
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ reversed: self.config.leftYAxisReversed,
+ enableMinorTick: self.config.enableMinorTick,
+ formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators),
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0
+ });
+ self.formatNumberLevelInYaxis(config, items, self.config.leftYAxisNumberLevel, idx, axis.formatter);
+ break;
+ case self.constants.RIGHT_AXIS:
+ title = getXYAxisUnit(self.config.rightYAxisNumberLevel, self.constants.RIGHT_AXIS);
+ axis.title.text = self.config.showRightYAxisTitle === true ? self.config.rightYAxisTitle + title : title;
+ axis.title.rotation = self.constants.ROTATION;
+ BI.extend(axis, {
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ reversed: self.config.rightYAxisReversed,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators)
+ });
+ self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisNumberLevel, idx, axis.formatter);
+ break;
+ }
+ });
+
+ config.xAxis[0].title.align = "center";
+ config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
+ BI.extend(config.xAxis[0], {
+ lineWidth: this.config.lineWidth,
+ enableTick: this.config.enableTick,
+ labelRotation: this.config.textDirection,
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ maxHeight: '40%'
+ });
+
+ config.chartType = "area";
+
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
+
+ //全局样式的图表文字
+ this.setFontStyle(this.config.chartFont, config);
+
+ return [items, config];
+
+ function formatChartStyle() {
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatCordon() {
+ BI.each(self.config.cordon, function (idx, cor) {
+ if (idx === 0 && self.xAxis.length > 0) {
+ var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if (idx > 0 && self.yAxis.length >= idx) {
+ var magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ }
+
+ function formatChartLineStyle() {
+ switch (self.config.chartLineType) {
+ case BICst.CHART_SHAPE.RIGHT_ANGLE:
+ config.plotOptions.curve = false;
+ config.plotOptions.step = true;
+ break;
+ case BICst.CHART_SHAPE.CURVE:
+ config.plotOptions.curve = true;
+ config.plotOptions.step = false;
+ break;
+ case BICst.CHART_SHAPE.NORMAL:
+ default:
+ config.plotOptions.curve = false;
+ config.plotOptions.step = false;
+ break;
+ }
+ }
+
+ function getXYAxisUnit(numberLevelType, position) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if (position === self.constants.X_AXIS) {
+ self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
+ }
+ if (position === self.constants.LEFT_AXIS) {
+ self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
+ }
+ if (position === self.constants.RIGHT_AXIS) {
+ self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
+ }
+ return unit === "" ? unit : "(" + unit + ")";
+ }
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ rightYAxisTitle: options.rightYAxisTitle || "",
+ rightYAxisSecondTitle: options.rightYAxisSecondTitle || "",
+ chartLineType: options.chartLineType || c.NORMAL,
+ chartColor: options.chartColor || [],
+ chartStyle: options.chartStyle || c.NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
+ rightYAxisSecondStyle: options.rightYAxisSecondStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ showRightYAxisTitle: options.showRightYAxisTitle || false,
+ showRightYAxisSecondTitle: options.showRightYAxisSecondTitle || false,
+ leftYAxisReversed: options.leftYAxisReversed || false,
+ rightYAxisReversed: options.rightYAxisReversed || false,
+ rightYAxisSecondReversed: options.rightYAxisSecondReversed || false,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
+ rightYAxisSecondNumberLevel: options.rightYAxisSecondNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ rightYAxisUnit: options.rightYAxisUnit || "",
+ rightYAxisSecondUnit: options.rightYAxisSecondUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showDataTable: options.showDataTable || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ showZoom: options.showZoom || false,
+ textDirection: options.textDirection || 0,
+ cordon: options.cordon || [],
+ lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
+ showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
+ enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
+ enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
+ numSeparators: options.numSeparators || false,
+ rightNumSeparators: options.rightNumSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE,
+ nullContinue: options.nullContinue || false
+ };
+ this.options.items = items;
+
+ var types = [];
+ BI.each(items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function (id, item) {
+ type.push(BICst.WIDGET.AREA);
+ });
+ types.push(type);
+ });
+
+ this.yAxis = [];
+ BI.each(types, function (idx, type) {
+ if (BI.isEmptyArray(type)) {
+ return;
+ }
+ var newYAxis = {
+ type: "value",
+ title: {
+ style: self.constants.FONT_STYLE
+ },
+ labelStyle: self.constants.FONT_STYLE,
+ position: idx > 0 ? "right" : "left",
+ lineWidth: 1,
+ axisIndex: idx,
+ gridLineWidth: 0
+ };
+ self.yAxis.push(newYAxis);
+ });
+
+ this.combineChart.populate(items, types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.AreaChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.area_chart', BI.AreaChart);/**
+ * 图表控件 柱状
+ * @class BI.AxisChart
+ * @extends BI.Widget
+ * leftYxis 左值轴属性
+ * rightYxis 右值轴属性
+ * xAxis 分类轴属性
+ */
+BI.AxisChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.AxisChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-axis-chart"
+ })
+ },
+
+ _init: function () {
+ BI.AxisChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.xAxis = [{
+ type: "category",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ position: "bottom",
+ gridLineWidth: 0
+ }];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.AxisChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this, o = this.options;
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ formatCordon();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.plotOptions.connectNulls = this.config.nullContinue;
+ config.dataSheet.enabled = this.config.showDataTable;
+ config.xAxis[0].showLabel = !config.dataSheet.enabled;
+ config.zoom.zoomTool.enabled = this.config.showZoom;
+ if (this.config.showZoom === true) {
+ delete config.dataSheet;
+ delete config.zoom.zoomType;
+ }
+
+ config.yAxis = this.yAxis;
+ BI.each(config.yAxis, function (idx, axis) {
+ var title;
+ switch (axis.axisIndex) {
+ case self.constants.LEFT_AXIS:
+ title = getXYAxisUnit(self.config.leftYAxisNumberLevel, self.constants.LEFT_AXIS);
+ axis.title.text = self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + title : title;
+ axis.title.rotation = self.constants.ROTATION;
+ BI.extend(axis, {
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ reversed: self.config.leftYAxisReversed,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)
+ });
+ self.formatNumberLevelInYaxis(config, items, self.config.leftYAxisNumberLevel, idx, axis.formatter);
+ break;
+ case self.constants.RIGHT_AXIS:
+ title = getXYAxisUnit(self.config.rightYAxisNumberLevel, self.constants.RIGHT_AXIS);
+ axis.title.text = self.config.showRightYAxisTitle === true ? self.config.rightYAxisTitle + title : title;
+ axis.title.rotation = self.constants.ROTATION;
+ BI.extend(axis, {
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ reversed: self.config.rightYAxisReversed,
+ enableMinorTIck: self.config.enableMinorTick,
+ formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators),
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0
+ });
+ self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisNumberLevel, idx, axis.formatter);
+ break;
+ }
+ });
+
+ config.xAxis[0].title.align = "center";
+ config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
+ BI.extend(config.xAxis[0], {
+ lineWidth: this.config.lineWidth,
+ enableTick: this.config.enableTick,
+ labelRotation: this.config.textDirection,
+ enableMinorTick: this.config.enableMinorTick,
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ maxHeight: '40%'
+ });
+
+ var lineItem = [];
+ var otherItem = [];
+ BI.each(items, function (idx, item) {
+ if (item.type === "line") {
+ lineItem.push(item);
+ } else {
+ otherItem.push(item);
+ }
+ });
+
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
+
+ //全局样式的图表文字
+ this.setFontStyle(this.config.chartFont, config);
+
+ return [BI.concat(otherItem, lineItem), config];
+
+ function formatChartStyle() {
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatCordon() {
+ BI.each(self.config.cordon, function (idx, cor) {
+ if (idx === 0 && self.xAxis.length > 0) {
+ var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if (idx > 0 && self.yAxis.length >= idx) {
+ var magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ }
+
+ function getXYAxisUnit(numberLevelType, position) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if (position === self.constants.X_AXIS) {
+ self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
+ }
+ if (position === self.constants.LEFT_AXIS) {
+ self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
+ }
+ if (position === self.constants.RIGHT_AXIS) {
+ self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
+ }
+ return unit === "" ? unit : "(" + unit + ")";
+ }
+ },
+
+ populate: function (items, options, types) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ rightYAxisTitle: options.rightYAxisTitle || "",
+ chartColor: options.chartColor || [],
+ chartStyle: options.chartStyle || c.NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ showRightYAxisTitle: options.showRightYAxisTitle || false,
+ leftYAxisReversed: options.leftYAxisReversed || false,
+ rightYAxisReversed: options.rightYAxisReversed || false,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ rightYAxisUnit: options.rightYAxisUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showDataTable: options.showDataTable || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ showZoom: options.showZoom || false,
+ textDirection: options.textDirection || 0,
+ cordon: options.cordon || [],
+ lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
+ showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
+ enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
+ enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
+ numSeparators: options.numSeparators || false,
+ rightNumSeparators: options.rightNumSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE,
+ nullContinue: true
+ };
+ this.options.items = items;
+
+ this.yAxis = [];
+ BI.each(types, function (idx, type) {
+ if (BI.isEmptyArray(type)) {
+ return;
+ }
+ var newYAxis = {
+ type: "value",
+ title: {
+ style: self.constants.FONT_STYLE
+ },
+ labelStyle: self.constants.FONT_STYLE,
+ position: idx > 0 ? "right" : "left",
+ lineWidth: 1,
+ axisIndex: idx,
+ gridLineWidth: 0
+ };
+ self.yAxis.push(newYAxis);
+ });
+
+ this.combineChart.populate(items, types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.AxisChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.axis_chart', BI.AxisChart);/**
+ * 图表控件
+ * @class BI.BarChart
+ * @extends BI.Widget
+ */
+BI.BarChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.BarChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-bar-chart"
+ })
+ },
+
+ _init: function () {
+ BI.BarChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.xAxis = [{
+ type: "value",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ formatter: function () {
+ return this > 0 ? this : (-1) * this
+ },
+ gridLineWidth: 0
+ }];
+ this.yAxis = [{
+ type: "category",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ gridLineWidth: 0,
+ position: "left"
+ }];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ var tmp = obj.x;
+ obj.x = obj.y;
+ obj.y = tmp;
+ self.fireEvent(BI.BarChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this;
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ formatCordon();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+
+ //分类轴
+ config.yAxis = this.yAxis;
+ config.yAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
+ config.yAxis[0].title.rotation = this.constants.ROTATION;
+ BI.extend(config.yAxis[0], {
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ labelRotation: this.config.textDirection,
+ enableTick: this.config.enableTick,
+ lineWidth: this.config.lineWidth,
+ maxWidth: '40%'
+ });
+
+ //值轴
+ self.formatNumberLevelInXaxis(items, this.config.leftYAxisNumberLevel);
+ config.xAxis[0].title.text = getXAxisTitle(this.config.leftYAxisNumberLevel, this.constants.X_AXIS);
+ config.xAxis[0].title.align = "center";
+ BI.extend(config.xAxis[0], {
+ formatter: self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators),
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ enableTick: this.config.enableTick,
+ showLabel: this.config.showLabel,
+ lineWidth: this.config.lineWidth,
+ enableMinorTick: this.config.enableMinorTick
+ });
+ config.chartType = "bar";
+
+ this.formatDataLabelForAxis(config.plotOptions.dataLabels.enabled, items, config.xAxis[0].formatter, this.config.chartFont);
+
+ config.plotOptions.tooltip.formatter.valueFormat = config.xAxis[0].formatter;
+
+ //全局样式的图表文字
+ this.setFontStyle(this.config.chartFont, config);
+
+ return [items, config];
+
+ function formatChartStyle() {
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatCordon() {
+ BI.each(self.config.cordon, function (idx, cor) {
+ if (idx === 0 && self.xAxis.length > 0) {
+ var magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if (idx > 0 && self.yAxis.length >= idx) {
+ var magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.xAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ }
+
+ function getXAxisTitle(numberLevelType, position) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if (position === self.constants.X_AXIS) {
+ self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
+ }
+ if (position === self.constants.LEFT_AXIS) {
+ self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
+ }
+ unit = unit === "" ? unit : "(" + unit + ")";
+
+ return self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + unit : unit;
+ }
+ },
+
+ _formatItems: function (items) {
+ BI.each(items, function (idx, item) {
+ BI.each(item, function (id, it) {
+ BI.each(it.data, function (i, t) {
+ var tmp = t.x;
+ t.x = t.y;
+ t.y = tmp;
+ })
+ });
+ });
+ return items;
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ chartColor: options.chartColor || [],
+ chartStyle: options.chartStyle || c.STYLE_NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ xAxisStyle: options.xAxisStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ leftYAxisReversed: options.leftYAxisReversed || false,
+ xAxisNumberLevel: options.xAxisNumberLevel || c.NORMAL,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ showZoom: options.showZoom || false,
+ textDirection: options.textDirection || 0,
+ cordon: options.cordon || [],
+ lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
+ showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
+ enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
+ enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
+ numSeparators: options.numSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE
+ };
+ this.options.items = items;
+ var types = [];
+ BI.each(items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function (id, item) {
+ type.push(BICst.WIDGET.BAR);
+ });
+ types.push(type);
+ });
+ this.combineChart.populate(this._formatItems(items), types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.BarChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.bar_chart', BI.BarChart);/**
+ * 图表控件
+ * @class BI.BubbleChart
+ * @extends BI.Widget
+ */
+BI.BubbleChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.BubbleChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-bubble-chart"
+ })
+ },
+
+ _init: function () {
+ BI.BubbleChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.xAxis = [{
+ type: "value",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ position: "bottom",
+ gridLineWidth: 0
+ }];
+ this.yAxis = [{
+ type: "value",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ position: "left",
+ gridLineWidth: 0
+ }];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.BubbleChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this, o = this.options;
+ delete config.zoom;
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ formatCordon();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.plotOptions.dataLabels.formatter.identifier = "${X}${Y}${SIZE}";
+ config.plotOptions.shadow = this.config.bubbleStyle !== this.constants.NO_PROJECT;
+ config.yAxis = this.yAxis;
+
+ config.yAxis[0].formatter = self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators);
+ formatNumberLevelInYaxis(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
+ config.yAxis[0].title.text = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
+ config.yAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + config.yAxis[0].title.text : config.yAxis[0].title.text;
+ config.yAxis[0].gridLineWidth = this.config.showGridLine === true ? 1 : 0;
+ config.yAxis[0].lineWidth = 1;
+ config.yAxis[0].title.rotation = this.constants.ROTATION;
+ config.yAxis[0].maxWidth = '40%';
+
+ config.xAxis[0].formatter = self.formatTickInXYaxis(this.config.xAxisStyle, this.config.xAxisNumberLevel, this.config.rightNumSeparators);
+ self.formatNumberLevelInXaxis(items, this.config.xAxisNumberLevel);
+ config.xAxis[0].title.text = getXYAxisUnit(this.config.xAxisNumberLevel, this.constants.X_AXIS);
+ config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle + config.xAxis[0].title.text : config.xAxis[0].title.text;
+ config.xAxis[0].title.align = "center";
+ config.xAxis[0].gridLineWidth = this.config.showGridLine === true ? 1 : 0;
+ config.xAxis[0].maxHeith = '40%';
+ config.chartType = "bubble";
+
+ if (BI.isNotEmptyArray(this.config.tooltip)) {
+ config.plotOptions.bubble.tooltip = {
+ useHtml: true,
+ style: {
+ color: 'RGB(184, 184, 184)'
+ },
+ formatter: function () {
+ var y = self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)(this.y);
+ var x = self.formatTickInXYaxis(self.config.xAxisStyle, self.config.xAxisNumberLevel, self.config.rightNumSeparators)(this.x);
+ return this.seriesName + '
(X)' + self.config.tooltip[0] + ':' + x + '
(Y)' + self.config.tooltip[1]
+ + ':' + y + '
(' + BI.i18nText("BI-Size") + ')' + self.config.tooltip[2] + ':' + this.size + '
'}
+ };
+ }
+
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ if (config.plotOptions.dataLabels.enabled === true) {
+ BI.each(items, function (idx, item) {
+ item.dataLabels = {
+ "style" : self.config.chartFont,
+ "align": "outside",
+ "autoAdjust": true,
+ enabled: true,
+ formatter: {
+ identifier: "${X}${Y}${SIZE}",
+ "XFormat": function () {
+ return BI.contentFormat(arguments[0], '#.##;-#.##')
+ },
+ "YFormat": function () {
+ return BI.contentFormat(arguments[0], '#.##;-#.##')
+ },
+ "sizeFormat": function () {
+ return BI.contentFormat(arguments[0], '#.##;-#.##')
+ }
+ }
+ };
+ item.dataLabels.formatter.XFormat = config.xAxis[0].formatter;
+ item.dataLabels.formatter.YFormat = config.yAxis[0].formatter;
+ });
+ }
+
+ //全局样式图表文字
+ config.yAxis[0].title.style = config.yAxis[0].labelStyle = this.config.chartFont;
+ config.xAxis[0].title.style = config.xAxis[0].labelStyle = this.config.chartFont;
+ config.legend.style = this.config.chartFont;
+
+ return [items, config];
+
+ function formatChartStyle() {
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatCordon() {
+ BI.each(self.config.cordon, function (idx, cor) {
+ if (idx === 0 && self.xAxis.length > 0) {
+ var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if (idx > 0 && self.yAxis.length >= idx) {
+ var magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ }
+
+ function formatNumberLevelInYaxis(type, position) {
+ var magnify = self.calcMagnify(type);
+ BI.each(items, function (idx, item) {
+ BI.each(item.data, function (id, da) {
+ if (position === item.yAxis) {
+ da.y = self.formatXYDataWithMagnify(da.y, magnify);
+ }
+ })
+ });
+ if (type === BICst.TARGET_STYLE.NUM_LEVEL.PERCENT) {
+ //config.plotOptions.tooltip.formatter.valueFormat = "function(){return window.FR ? FR.contentFormat(arguments[0], '#0%') : arguments[0]}";
+ }
+ }
+
+ function getXYAxisUnit(numberLevelType, position) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if (position === self.constants.X_AXIS) {
+ self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
+ }
+ if (position === self.constants.LEFT_AXIS) {
+ self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
+ }
+ if (position === self.constants.RIGHT_AXIS) {
+ self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
+ }
+ return unit === "" ? unit : "(" + unit + ")";
+ }
+ },
+
+ _formatItems: function (items) {
+ BI.each(items, function (idx, item) {
+ BI.each(item, function (id, it) {
+ BI.each(it.data, function (i, da) {
+ var data = da.size;
+ da.size = BI.contentFormat(data, '#.##;-#.##')
+ })
+ })
+ });
+ return items;
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ chartColor: options.chartColor || [],
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ xAxisStyle: options.xAxisStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ xAxisNumberLevel: options.xAxisNumberLevel || c.NORMAL,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ cordon: options.cordon || [],
+ tooltip: options.tooltip || [],
+ bubbleStyle: options.bubbleStyle || c.NO_PROJECT,
+ numSeparators: options.numSeparators || false,
+ rightNumSeparators: options.rightNumSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE
+ };
+ this.options.items = items;
+ var types = [];
+ BI.each(items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function (id, item) {
+ type.push(BICst.WIDGET.BUBBLE);
+ });
+ types.push(type);
+ });
+ this.combineChart.populate(this._formatItems(items), types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.BubbleChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.bubble_chart', BI.BubbleChart);
+/**
+ * 图表控件
+ * @class BI.CompareAreaChart
+ * @extends BI.Widget
+ */
+BI.CompareAreaChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.CompareAreaChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-compare-area-chart"
+ })
+ },
+
+ _init: function () {
+ BI.CompareAreaChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.xAxis = [{
+ type: "category",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ position: "bottom",
+ gridLineWidth: 0
+ }];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.CompareAreaChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this;
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ formatChartLineStyle();
+ formatCordon();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.plotOptions.connectNulls = this.config.nullContinue;
+ config.dataSheet.enabled = this.config.showDataTable;
+ config.xAxis[0].showLabel = !config.dataSheet.enabled;
+ config.zoom.zoomTool.enabled = this.config.showZoom;
+ if (this.config.showZoom === true) {
+ delete config.dataSheet;
+ delete config.zoom.zoomType;
+ }
+
+ config.yAxis = this.yAxis;
+ BI.each(config.yAxis, function (idx, axis) {
+ var title = "";
+ switch (axis.axisIndex) {
+ case self.constants.LEFT_AXIS:
+ title = getXYAxisUnit(self.config.leftYAxisNumberLevel, self.constants.LEFT_AXIS);
+ axis.title.rotation = self.constants.ROTATION;
+ axis.title.text = self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + title : title;
+ BI.extend(axis, {
+ reversed: false,
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)
+ });
+ formatNumberLevelInYaxis(self.config.leftYAxisNumberLevel, idx, axis.formatter);
+ break;
+ case self.constants.RIGHT_AXIS:
+ title = getXYAxisUnit(self.config.rightYAxisNumberLevel, self.constants.RIGHT_AXIS);
+ axis.title.rotation = self.constants.ROTATION;
+ axis.title.text = self.config.showRightYAxisTitle === true ? self.config.rightYAxisTitle + title : title;
+ BI.extend(axis, {
+ reversed: true,
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators)
+ });
+ formatNumberLevelInYaxis(self.config.rightYAxisNumberLevel, idx, axis.formatter);
+ break;
+ }
+ var res = _calculateValueNiceDomain(0, self.maxes[idx]);
+ axis.max = res[1].mul(2);
+ axis.min = res[0].mul(2);
+ axis.tickInterval = BI.parseFloat((BI.parseFloat(axis.max).sub(BI.parseFloat(axis.min)))).div(5);
+ });
+
+ config.xAxis[0].title.align = "center";
+ config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
+ BI.extend(config.xAxis[0], {
+ lineWidth: this.config.lineWidth,
+ enableTick: this.config.enableTick,
+ labelRotation: this.config.textDirection,
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ maxHeight: '40%'
+ });
+
+ config.chartType = "area";
+
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
+
+ //全局样式的图表文字
+ this.setFontStyle(this.config.chartFont, config);
+
+ return [items, config];
+
+ function _calculateValueNiceDomain(minValue, maxValue) {
+
+ minValue = Math.min(0, minValue);
+
+ var tickInterval = _linearTickInterval(minValue, maxValue);
+
+ return _linearNiceDomain(minValue, maxValue, tickInterval);
+ }
+
+ function _linearTickInterval(minValue, maxValue, m) {
+
+ m = m || 5;
+ var span = maxValue - minValue;
+ var step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10));
+ var err = m / span * step;
+
+ if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
+
+ return step;
+ }
+
+ function _linearNiceDomain(minValue, maxValue, tickInterval) {
+
+ minValue = VanUtils.accMul(Math.floor(minValue / tickInterval), tickInterval);
+
+ maxValue = VanUtils.accMul(Math.ceil(maxValue / tickInterval), tickInterval);
+
+ return [minValue, maxValue];
+ }
+
+ function formatChartStyle() {
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatCordon() {
+ BI.each(self.config.cordon, function (idx, cor) {
+ if (idx === 0 && self.xAxis.length > 0) {
+ var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style": self.config.chartFont,
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if (idx > 0 && self.yAxis.length >= idx) {
+ var magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style": self.config.chartFont,
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ }
+
+ function formatChartLineStyle() {
+ switch (self.config.chartLineType) {
+ case BICst.CHART_SHAPE.RIGHT_ANGLE:
+ config.plotOptions.area = {
+ curve: false,
+ step: true
+ };
+ break;
+ case BICst.CHART_SHAPE.CURVE:
+ config.plotOptions.area = {
+ curve: true,
+ step: false
+ };
+ break;
+ case BICst.CHART_SHAPE.NORMAL:
+ default:
+ config.plotOptions.area = {
+ curve: false,
+ step: false
+ };
+ break;
+ }
+ }
+
+ function formatNumberLevelInYaxis(type, position, formatter) {
+ var magnify = self.calcMagnify(type);
+ BI.each(items, function (idx, item) {
+ var max = null;
+ BI.each(item.data, function (id, da) {
+ if (position === item.yAxis) {
+ da.y = self.formatXYDataWithMagnify(da.y, magnify);
+ if ((BI.isNull(max) || BI.parseFloat(da.y) > BI.parseFloat(max))) {
+ max = da.y;
+ }
+ }
+ });
+ if (position === item.yAxis) {
+ item.tooltip = BI.deepClone(config.plotOptions.tooltip);
+ item.tooltip.formatter.valueFormat = formatter;
+ }
+ if (BI.isNotNull(max)) {
+ self.maxes.push(max);
+ }
+ });
+ }
+
+ function getXYAxisUnit(numberLevelType, position) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if (position === self.constants.X_AXIS) {
+ self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
+ }
+ if (position === self.constants.LEFT_AXIS) {
+ self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
+ }
+ if (position === self.constants.RIGHT_AXIS) {
+ self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
+ }
+ return unit === "" ? unit : "(" + unit + ")";
+ }
+ },
+
+ _formatItems: function (items) {
+ var self = this;
+ this.maxes = [];
+ BI.each(items, function (idx, item) {
+ BI.each(item, function (id, it) {
+ if (idx > 0) {
+ BI.extend(it, {reversed: true, xAxis: 0});
+ } else {
+ BI.extend(it, {reversed: false, xAxis: 1});
+ }
+ });
+ });
+ return items;
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ rightYAxisTitle: options.rightYAxisTitle || "",
+ chartColor: options.chartColor || [],
+ chartStyle: options.chartStyle || c.NORMAL,
+ chartLineType: options.chartLineType || c.NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ showRightYAxisTitle: options.showRightYAxisTitle || false,
+ leftYAxisReversed: options.leftYAxisReversed || false,
+ rightYAxisReversed: options.rightYAxisReversed || false,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ rightYAxisUnit: options.rightYAxisUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showDataTable: options.showDataTable || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ showZoom: options.showZoom || false,
+ textDirection: options.textDirection || 0,
+ cordon: options.cordon || [],
+ lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
+ showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
+ enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
+ enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
+ numSeparators: options.numSeparators || false,
+ rightNumSeparators: options.rightNumSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE,
+ nullContinue: options.nullContinue || false
+ };
+ this.options.items = items;
+
+ var types = [];
+ BI.each(items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function (id, item) {
+ type.push(BICst.WIDGET.AREA);
+ });
+ types.push(type);
+ });
+
+ this.yAxis = [];
+ BI.each(types, function (idx, type) {
+ if (BI.isEmptyArray(type)) {
+ return;
+ }
+ var newYAxis = {
+ type: "value",
+ title: {
+ style: self.constants.FONT_STYLE
+ },
+ labelStyle: self.constants.FONT_STYLE,
+ position: idx > 0 ? "right" : "left",
+ lineWidth: 1,
+ axisIndex: idx,
+ gridLineWidth: 0
+ };
+ self.yAxis.push(newYAxis);
+ });
+
+ this.combineChart.populate(this._formatItems(items), types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.CompareAreaChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.compare_area_chart', BI.CompareAreaChart);/**
+ * 图表控件
+ * @class BI.CompareAxisChart
+ * @extends BI.Widget
+ */
+BI.CompareAxisChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.CompareAxisChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-compare-axis-chart"
+ })
+ },
+
+ _init: function () {
+ BI.CompareAxisChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.xAxis = [{
+ type: "category",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ position: "bottom",
+ gridLineWidth: 0
+ }, {
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ position: "top",
+ gridLineWidth: 0,
+ type: "category",
+ showLabel: false
+ }];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.CompareAxisChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function(config, items){
+ var self = this, o = this.options;
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ formatChartLineStyle();
+ formatCordon();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.dataSheet.enabled = this.config.showDataTable;
+ config.xAxis[0].showLabel = !config.dataSheet.enabled;
+ config.zoom.zoomTool.enabled = this.config.showZoom;
+ if(this.config.showZoom === true){
+ delete config.dataSheet;
+ delete config.zoom.zoomType;
+ }
+
+ config.yAxis = this.yAxis;
+ BI.each(config.yAxis, function(idx, axis){
+ var unit = '';
+ switch (axis.axisIndex){
+ case self.constants.LEFT_AXIS:
+ unit = getXYAxisUnit(self.config.leftYAxisNumberLevel, self.constants.LEFT_AXIS);
+ axis.title.rotation = self.constants.ROTATION;
+ axis.title.text = self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + unit : unit;
+ BI.extend(axis, {
+ reversed: false,
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)
+ });
+ formatNumberLevelInYaxis(self.config.leftYAxisNumberLevel, idx, axis.formatter);
+ break;
+ case self.constants.RIGHT_AXIS:
+ unit = getXYAxisUnit(self.config.rightYAxisNumberLevel, self.constants.RIGHT_AXIS);
+ axis.title.rotation = self.constants.ROTATION;
+ axis.title.text = self.config.showRightYAxisTitle === true ? self.config.rightYAxisTitle + unit : unit;
+ BI.extend(axis, {
+ reversed: true,
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators)
+ });
+ formatNumberLevelInYaxis(self.config.rightYAxisNumberLevel, idx, axis.formatter);
+ break;
+ }
+ var res = _calculateValueNiceDomain(0, self.maxes[idx]);
+ axis.max = res[1].mul(2);
+ axis.min = res[0].mul(2);
+ axis.tickInterval = BI.parseFloat((BI.parseFloat(axis.max).sub(BI.parseFloat(axis.min)))).div(5);
+ });
+
+ config.xAxis[0].title.align = "center";
+ config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
+ BI.extend(config.xAxis[0], {
+ lineWidth: this.config.lineWidth,
+ enableTick: this.config.enableTick,
+ labelRotation: this.config.textDirection,
+ enableMinorTick: this.config.enableMinorTick,
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ maxHeight: '40%'
+ });
+
+ BI.extend(config.xAxis[1], {
+ lineWidth: this.config.lineWidth,
+ enableTick: this.config.enableTick,
+ enableMinorTick: this.config.enableMinorTick
+ });
+
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
+
+ //全局样式的图表文字
+ this.setFontStyle(this.config.chartFont, config);
+
+ return [items, config];
+
+ function formatChartStyle(){
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatCordon(){
+ BI.each(self.config.cordon, function(idx, cor){
+ if(idx === 0 && self.xAxis.length > 0){
+ var magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function(i, t){
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if(idx > 0 && self.yAxis.length >= idx){
+ var magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function(i, t){
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ }
+
+ function formatChartLineStyle(){
+ switch (self.config.chartLineType) {
+ case BICst.CHART_SHAPE.RIGHT_ANGLE:
+ config.plotOptions.curve = false;
+ config.plotOptions.step = true;
+ break;
+ case BICst.CHART_SHAPE.CURVE:
+ config.plotOptions.curve = true;
+ config.plotOptions.step = false;
+ break;
+ case BICst.CHART_SHAPE.NORMAL:
+ default:
+ config.plotOptions.curve = false;
+ config.plotOptions.step = false;
+ break;
+ }
+ }
+
+ function formatNumberLevelInYaxis(type, position, formatter){
+ var magnify = self.calcMagnify(type);
+ BI.each(items, function (idx, item) {
+ var max = null;
+ BI.each(item.data, function (id, da) {
+ if (position === item.yAxis) {
+ da.y = self.formatXYDataWithMagnify(da.y, magnify);
+ if((BI.isNull(max) || BI.parseFloat(da.y) > BI.parseFloat(max))){
+ max = da.y;
+ }
+ }
+ });
+ if(position === item.yAxis){
+ item.tooltip = BI.deepClone(config.plotOptions.tooltip);
+ item.tooltip.formatter.valueFormat = formatter;
+ }
+ if(BI.isNotNull(max)){
+ self.maxes.push(max);
+ }
+ });
+ }
+
+ function getXYAxisUnit(numberLevelType, position){
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if(position === self.constants.X_AXIS){
+ self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
+ }
+ if(position === self.constants.LEFT_AXIS){
+ self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
+ }
+ if(position === self.constants.RIGHT_AXIS){
+ self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
+ }
+ return unit === "" ? unit : "(" + unit + ")";
+ }
+
+ function _calculateValueNiceDomain(minValue, maxValue){
+
+ minValue = Math.min(0, minValue);
+
+ var tickInterval = _linearTickInterval(minValue, maxValue);
+
+ return _linearNiceDomain(minValue, maxValue, tickInterval);
+ }
+
+ function _linearTickInterval(minValue, maxValue, m){
+
+ m = m || 5;
+ var span = maxValue - minValue;
+ var step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10));
+ var err = m / span * step;
+
+ if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
+
+ return step;
+ }
+
+ function _linearNiceDomain(minValue, maxValue, tickInterval){
+
+ minValue = VanUtils.accMul(Math.floor(minValue / tickInterval), tickInterval);
+
+ maxValue = VanUtils.accMul(Math.ceil(maxValue / tickInterval), tickInterval);
+
+ return [minValue, maxValue];
+ }
+ },
+
+ _formatItems: function(items){
+ var self = this;
+ this.maxes = [];
+ BI.each(items, function(idx, item){
+ BI.each(item, function(id, it){
+ if(idx > 0){
+ BI.extend(it, {reversed: true, xAxis: 1});
+ }else{
+ BI.extend(it, {reversed: false, xAxis: 0});
+ }
+ });
+ });
+ return items;
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ rightYAxisTitle: options.rightYAxisTitle || "",
+ chartColor: options.chartColor || [],
+ chartStyle: options.chartStyle || c.NORMAL,
+ chartLineType: options.chartLineType || c.NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ showRightYAxisTitle: options.showRightYAxisTitle || false,
+ leftYAxisReversed: options.leftYAxisReversed || false,
+ rightYAxisReversed: options.rightYAxisReversed || false,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ rightYAxisUnit: options.rightYAxisUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showDataTable: options.showDataTable || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ showZoom: options.showZoom || false,
+ textDirection: options.textDirection || 0,
+ cordon: options.cordon || [],
+ lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
+ showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
+ enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
+ enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
+ numSeparators: options.numSeparators || false,
+ rightNumSeparators: options.rightNumSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE
+ };
+ this.options.items = items;
+
+ this.yAxis = [];
+
+ var types = [];
+ BI.each(items, function(idx, axisItems){
+ var type = [];
+ BI.each(axisItems, function(id, item){
+ type.push(BICst.WIDGET.AXIS);
+ });
+ types.push(type);
+ });
+
+ BI.each(types, function(idx, type){
+ if(BI.isEmptyArray(type)){
+ return;
+ }
+ var newYAxis = {
+ type: "value",
+ title: {
+ style: self.constants.FONT_STYLE
+ },
+ labelStyle: self.constants.FONT_STYLE,
+ position: idx > 0 ? "right" : "left",
+ lineWidth: 1,
+ axisIndex: idx,
+ gridLineWidth: 0,
+ reversed: idx > 0
+ };
+ self.yAxis.push(newYAxis);
+ });
+
+ this.combineChart.populate(this._formatItems(items), types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function(){
+ this.combineChart.magnify();
+ }
+});
+BI.CompareAxisChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.compare_axis_chart', BI.CompareAxisChart);/**
+ * 图表控件
+ * @class BI.CompareBarChart
+ * @extends BI.Widget
+ */
+BI.CompareBarChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.CompareBarChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-compare-bar-chart"
+ })
+ },
+
+ _init: function () {
+ BI.CompareBarChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.xAxis = [{
+ type: "value",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ formatter: function () {
+ return this > 0 ? this : (-1) * this;
+ },
+ gridLineWidth: 0
+ }];
+ this.yAxis = [{
+ type: "category",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ gridLineWidth: 0,
+ position: "left"
+ }];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.CompareBarChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this, o = this.options;
+ var yTitle = getXYAxisUnit(this.config.xAxisNumberLevel, this.constants.LEFT_AXIS);
+ var xTitle = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.X_AXIS);
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ formatCordon();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+
+ config.yAxis = this.yAxis;
+ config.yAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle + yTitle : yTitle;
+ config.yAxis[0].title.rotation = this.constants.ROTATION;
+ BI.extend(config.yAxis[0], {
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ lineWidth: this.config.lineWidth,
+ enableTick: this.config.enableTick,
+ labelRotation: this.config.textDirection,
+ maxWidth: '40%'
+ });
+
+ self.formatNumberLevelInXaxis(items, this.config.leftYAxisNumberLevel);
+ config.xAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + xTitle : xTitle;
+ config.xAxis[0].title.align = "center";
+ BI.extend(config.xAxis[0], {
+ formatter: self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators, true),
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ lineWidth: this.config.lineWidth,
+ showLabel: this.config.showLabel,
+ enableTick: this.config.enableTick,
+ enableMinorTick: this.config.enableMinorTick
+ });
+
+ config.chartType = "bar";
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ this.formatDataLabelForAxis(config.plotOptions.dataLabels.enabled, items, config.xAxis[0].formatter, this.config.chartFont);
+
+ config.plotOptions.tooltip.formatter.valueFormat = config.xAxis[0].formatter;
+
+ //全局样式的图表文字
+ this.setFontStyle(this.config.chartFont, config);
+
+ return [items, config];
+
+ function formatChartStyle() {
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatCordon() {
+ BI.each(self.config.cordon, function (idx, cor) {
+ if (idx === 0 && self.xAxis.length > 0) {
+ var magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if (idx > 0 && self.yAxis.length >= idx) {
+ var magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.xAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ }
+
+ function getXYAxisUnit(numberLevelType, position) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if (position === self.constants.X_AXIS) {
+ self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
+ }
+ if (position === self.constants.LEFT_AXIS) {
+ self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
+ }
+ if (position === self.constants.RIGHT_AXIS) {
+ self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
+ }
+ return unit === "" ? unit : "(" + unit + ")";
+ }
+ },
+
+ _formatItems: function (items) {
+ var result = [];
+ var i = BI.UUID();
+ BI.each(items, function (idx, item) {
+ BI.each(item, function (id, it) {
+ BI.each(it.data, function (i, t) {
+ var tmp = t.x;
+ t.x = t.y;
+ t.y = tmp;
+ if (idx === 0) {
+ t.x = -t.x;
+ }
+ });
+ it.stack = i;
+ })
+ });
+ BI.each(items, function (idx, item) {
+ result = BI.concat(result, item);
+ });
+ return [result];
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ chartColor: options.chartColor || [],
+ chartStyle: options.chartStyle || c.STYLE_NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ xAxisStyle: options.xAxisStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ leftYAxisReversed: options.leftYAxisReversed || false,
+ xAxisNumberLevel: options.xAxisNumberLevel || c.NORMAL,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showDataTable: options.showDataTable || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ showZoom: options.showZoom || false,
+ textDirection: options.textDirection || 0,
+ cordon: options.cordon || [],
+ lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
+ showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
+ enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
+ enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
+ numSeparators: options.numSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE
+ };
+ this.options.items = this._formatItems(items);
+ var types = [];
+ BI.each(this.options.items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function (id, item) {
+ type.push(BICst.WIDGET.BAR);
+ });
+ types.push(type);
+ });
+ this.combineChart.populate(this.options.items, types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.CompareBarChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.compare_bar_chart', BI.CompareBarChart);/**
+ * 图表控件
+ * @class BI.DashboardChart
+ * @extends BI.Widget
+ */
+BI.DashboardChart = BI.inherit(BI.AbstractChart, {
+
+
+ _defaultConfig: function () {
+ return BI.extend(BI.DashboardChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-dashboard-chart"
+ })
+ },
+
+ _init: function () {
+ BI.DashboardChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.gaugeAxis = [{
+ "minorTickColor": "rgb(226,226,226)",
+ "tickColor": "rgb(186,186,186)",
+ labelStyle: this.constants.FONT_STYLE,
+ "step": 0,
+ "showLabel": true
+ }];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.DashboardChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this, o = this.options;
+ var isDashboard = BI.contains([self.constants.NORMAL, self.constants.HALF_DASHBOARD], self.config.chartDashboardType);
+ var isMultiPointers = self.config.numberOfPointer === self.constants.MULTI_POINTER;
+ formatChartDashboardStyle();
+ config.chartType = "gauge";
+ delete config.zoom;
+ delete config.xAxis;
+ delete config.yAxis;
+ if (isDashboard && !isMultiPointers) {
+ config.plotOptions.seriesLabel.enabled = false;
+ if(BI.isNull(items[0].data[0].z)) {
+ config.plotOptions.tooltip.formatter.identifier = "${SERIES}${X}${Y}${SIZE}${VALUE}"
+ }
+ }
+ config.gaugeAxis[0].labelStyle = this.config.chartFont;
+ return [items, config];
+
+ function formatChartDashboardStyle() {
+ var bands = getBandsStyles(self.config.bandsStyles, self.config.autoCustomStyle);
+ var percentageLabel = BI.extend(config.plotOptions.percentageLabel, {
+ enabled: self.config.showPercentage === BICst.PERCENTAGE.SHOW
+ });
+
+ config.gaugeAxis = self.gaugeAxis;
+ var slotValueLAbel = {
+ enabled: true,
+ formatter: function () {
+ var value = this.value;
+ if (self.config.dashboardNumberLevel === BICst.TARGET_STYLE.NUM_LEVEL.PERCENT && self.config.numSeparators) {
+ value = BI.contentFormat(this.value, "#,##0%;-#,##0%")
+ } else if (self.config.dashboardNumberLevel === BICst.TARGET_STYLE.NUM_LEVEL.PERCENT && !self.config.numSeparators) {
+ value = BI.contentFormat(this.value, "#0.00%");
+ } else if (!(self.config.dashboardNumberLevel === BICst.TARGET_STYLE.NUM_LEVEL.PERCENT) && self.config.numSeparators) {
+ value = BI.contentFormat(this.value, "#,###.##;-#,###.##")
+ } else {
+ value = BI.contentFormat(this.value, "#.##;-#.##");
+ }
+
+ var label = '
' + this.seriesName + '
' + '
' + value +
+ getXYAxisUnit(self.config.dashboardNumberLevel, self.constants.DASHBOARD_AXIS) + '
';
+
+ if (isDashboard && items[0].data.length > 1) {
+ if (isMultiPointers) {
+ return '
' + this.seriesName + ':' + value +
+ getXYAxisUnit(self.config.dashboardNumberLevel, self.constants.DASHBOARD_AXIS) + '
';
+ }
+ return label
+ } else if (isDashboard && BI.isNull(items[0].data[0].z)) {
+ return label
+ }
+
+ return '
' + this.category + '
' + label;
+ },
+ style: self.config.chartFont,
+ useHtml: true
+ };
+ switch (self.config.chartDashboardType) {
+ case BICst.CHART_SHAPE.HALF_DASHBOARD:
+ setPlotOptions("pointer_semi", bands, slotValueLAbel, percentageLabel);
+ break;
+ case BICst.CHART_SHAPE.PERCENT_DASHBOARD:
+ setPlotOptions("ring", bands, slotValueLAbel, percentageLabel);
+ break;
+ case BICst.CHART_SHAPE.PERCENT_SCALE_SLOT:
+ setPlotOptions("slot", bands, slotValueLAbel, percentageLabel);
+ break;
+ case BICst.CHART_SHAPE.HORIZONTAL_TUBE:
+ BI.extend(slotValueLAbel, {
+ align: "bottom"
+ });
+ BI.extend(percentageLabel, {
+ align: "bottom"
+ });
+ setPlotOptions("thermometer", bands, slotValueLAbel, percentageLabel, "horizontal", "vertical");
+ break;
+ case BICst.CHART_SHAPE.VERTICAL_TUBE:
+ BI.extend(slotValueLAbel, {
+ align: "left"
+ });
+ BI.extend(percentageLabel, {
+ align: "left"
+ });
+ setPlotOptions("thermometer", bands, slotValueLAbel, percentageLabel, "vertical", "horizontal");
+ break;
+ case BICst.CHART_SHAPE.NORMAL:
+ default:
+ setPlotOptions("pointer", bands, slotValueLAbel, percentageLabel);
+ break;
+ }
+ changeMaxMinScale();
+ formatNumberLevelInYaxis(self.config.dashboardNumberLevel, self.constants.LEFT_AXIS);
+ if (self.config.dashboardNumberLevel === BICst.TARGET_STYLE.NUM_LEVEL.PERCENT) {
+ config.gaugeAxis[0].formatter = function () {
+ var scaleValue = this;
+ if (self.config.numSeparators) {
+ scaleValue = BI.contentFormat(scaleValue, '#,##0%;-#,##0%')
+ } else {
+ scaleValue = BI.contentFormat(scaleValue, '#0.00%')
+ }
+ return scaleValue + getXYAxisUnit(self.config.dashboardNumberLevel, self.constants.DASHBOARD_AXIS);
+ };
+ } else {
+ config.gaugeAxis[0].formatter = function () {
+ var value = this;
+ if (self.config.numSeparators) {
+ value = BI.contentFormat(value, "#,###;-#,###")
+ }
+ return value + getXYAxisUnit(self.config.dashboardNumberLevel, self.constants.DASHBOARD_AXIS);
+ };
+ }
+ }
+
+ function setPlotOptions(style, bands, slotValueLAbel, percentageLabel, thermometerLayout, layout) {
+ config.style = style;
+ config.plotOptions.bands = bands;
+ config.plotOptions.valueLabel = slotValueLAbel;
+ config.plotOptions.percentageLabel = percentageLabel;
+ config.plotOptions.thermometerLayout = thermometerLayout;
+ config.plotOptions.layout = layout;
+ }
+
+ function changeMaxMinScale() {
+ self.gaugeAxis[0].min = BI.parseFloat(self.config.minScale) || null;
+ self.gaugeAxis[0].max = BI.parseFloat(self.config.maxScale) || null;
+ }
+
+ function formatNumberLevelInYaxis(type, position) {
+ var magnify = self.calcMagnify(type);
+ BI.each(items, function (idx, item) {
+ BI.each(item.data, function (id, da) {
+ if (position === item.yAxis) {
+ da.y = self.formatXYDataWithMagnify(da.y, magnify);
+ }
+ })
+ });
+
+ config.plotOptions.tooltip.formatter.valueFormat = function () {
+ return BI.contentFormat(this, '#.##;-#.##') + getXYAxisUnit(type, position)
+ };
+
+ if (self.config.numSeparators) {
+ config.plotOptions.tooltip.formatter.valueFormat = function () {
+ return BI.contentFormat(arguments[0], '#,###.##;-#,###.##')
+ };
+ }
+
+ if (type === BICst.TARGET_STYLE.NUM_LEVEL.PERCENT) {
+ config.plotOptions.tooltip.formatter.valueFormat = function () {
+ return BI.contentFormat(arguments[0], '#0.00%')
+ };
+ if (self.config.numSeparators) {
+ config.plotOptions.tooltip.formatter.valueFormat = function () {
+ return BI.contentFormat(arguments[0], '#,##0%;-#,##0%')
+ };
+ }
+ }
+ }
+
+ function getXYAxisUnit(numberLevelType, position) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if (position === self.constants.DASHBOARD_AXIS) {
+ self.config.dashboardUnit !== "" && (unit = unit + self.config.dashboardUnit)
+ }
+ return unit;
+ }
+
+ function getBandsStyles(styles, change) {
+ var min = 0, bands = [], color = null, max = null, conditionMax = null;
+
+ BI.each(items, function (idx, item) {
+ var data = item.data[0];
+ if ((BI.isNull(max) || data.y > max)) {
+ max = data.y
+ }
+ });
+
+ switch (change) {
+
+ case BICst.SCALE_SETTING.AUTO:
+ break;
+ case BICst.SCALE_SETTING.CUSTOM:
+ if (styles.length === 0) {
+ return bands
+ } else {
+ var maxScale = _calculateValueNiceDomain(0, max)[1];
+
+ BI.each(styles, function (idx, style) {
+ if(BI.parseFloat(style.range.min) > BI.parseFloat(style.range.max)) {
+ return bands.push({
+ color: color,
+ from: conditionMax,
+ to: maxScale
+ });
+ }
+ bands.push({
+ color: style.color,
+ from: style.range.min,
+ to: style.range.max
+ });
+ color = style.color;
+ conditionMax = style.range.max
+ });
+ min = BI.parseInt(styles[0].range.min);
+ bands.push({
+ color: "#808080",
+ from: 0,
+ to: min
+ });
+
+ bands.push({
+ color: color,
+ from: conditionMax,
+ to: maxScale
+ });
+
+ return bands;
+ }
+ }
+ }
+
+ function _calculateValueNiceDomain(minValue, maxValue) {
+ minValue = Math.min(0, minValue);
+ var tickInterval = _linearTickInterval(minValue, maxValue);
+
+ return _linearNiceDomain(minValue, maxValue, tickInterval);
+ }
+
+ function _linearTickInterval(minValue, maxValue, m) {
+ m = m || 5;
+ var span = maxValue - minValue;
+ var step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10));
+ var err = m / span * step;
+ if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
+
+ return step;
+ }
+
+ function _linearNiceDomain(minValue, maxValue, tickInterval) {
+ minValue = VanUtils.accMul(Math.floor(minValue / tickInterval), tickInterval);
+ maxValue = VanUtils.accMul(Math.ceil(maxValue / tickInterval), tickInterval);
+
+ return [minValue, maxValue];
+ }
+ },
+
+ _formatItems: function (items) {
+ if (items.length === 0) {
+ return [];
+ }
+ var c = this.constants;
+ if (this.config.chartDashboardType === c.NORMAL || this.config.chartDashboardType === c.HALF_DASHBOARD) {
+ var result = [];
+ if (this.config.numberOfPointer === c.ONE_POINTER && items[0].length === 1) {//单个系列
+ BI.each(items[0][0].data, function (idx, da) {
+ result.push({
+ data: [BI.extend({}, da, {
+ x: items[0][0].name
+ })],
+ name: da.x
+ })
+ });
+ return [result];
+ } else if(this.config.numberOfPointer === c.ONE_POINTER && items[0].length > 1) {
+ BI.each(items[0], function (idx, item) {
+ result.push({
+ data: [BI.extend(item.data[0], {
+ x: item.name
+ })],
+ name: BI.UUID()
+ })
+ });
+ return [result]
+ }
+ if (this.config.numberOfPointer === c.MULTI_POINTER && items[0].length > 1) {//多个系列
+ BI.each(items, function (idx, item) {
+ BI.each(item, function (id, it) {
+ var data = it.data[0];
+ data.x = it.name;
+ result.push(data);
+ })
+ });
+ return [[{
+ data: result,
+ name: ""
+ }]];
+ }
+ } else {
+ var others = [];
+ if (BI.isNotNull(items[0][0].data[0].z)) {
+ BI.each(items[0], function (idx, item) {
+ BI.each(item.data, function (id, da) {
+ others.push({
+ data: [BI.extend({}, da, {
+ x: item.name,
+ y: da.y
+ })],
+ name: da.x
+ })
+ })
+ });
+ return [others];
+ }
+ }
+ return items;
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants, o = this.options;
+ this.config = {
+ dashboardNumberLevel: options.dashboardNumberLevel || c.NORMAL,
+ dashboardUnit: options.dashboardUnit || "",
+ chartDashboardType: options.chartDashboardType || c.NORMAL,
+ numberOfPointer: options.numberOfPointer || c.ONE_POINTER,
+ bandsStyles: options.bandsStyles || [],
+ autoCustomStyle: options.autoCustom || c.AUTO,
+ minScale: options.minScale,
+ maxScale: options.maxScale,
+ showPercentage: options.showPercentage || c.NOT_SHOW,
+ numSeparators: options.numSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE
+ };
+ o.items = this._formatItems(items);
+ var types = [];
+ BI.each(o.items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function (id, item) {
+ type.push(BICst.WIDGET.DASHBOARD);
+ });
+ types.push(type);
+ });
+
+ this.combineChart.populate(o.items, types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.DashboardChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.dashboard_chart', BI.DashboardChart);/**
+ * 图表控件
+ * @class BI.DonutChart
+ * @extends BI.Widget
+ */
+BI.DonutChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.DonutChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-donut-chart"
+ })
+ },
+
+ _init: function () {
+ BI.DonutChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.DonutChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function(config, items){
+ var self = this;
+ delete config.zoom;
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+
+ this.formatChartLegend(config, this.config.chartLegend);
+
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+
+ config.plotOptions.innerRadius = "50.0%";
+ config.chartType = "pie";
+ config.plotOptions.dataLabels.align = "outside";
+ config.plotOptions.dataLabels.connectorWidth = "outside";
+ config.plotOptions.dataLabels.style = this.config.chartFont;
+ config.plotOptions.dataLabels.formatter.identifier = "${VALUE}${PERCENT}";
+ delete config.xAxis;
+ delete config.yAxis;
+ BI.each(items, function (idx, item) {
+ BI.each(item.data, function (id, da) {
+ da.y = self.formatXYDataWithMagnify(da.y, 1);
+ })
+ });
+
+ config.legend.style = this.config.chartFont;
+ return [items, config];
+
+ function formatChartStyle(){
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ chartColor: options.chartColor || [],
+ chartStyle: options.chartStyle || c.NORMAL,
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ chartFont: options.chartFont || c.FONT_STYLE
+ };
+ this.options.items = items;
+
+ var types = [];
+ BI.each(items, function(idx, axisItems){
+ var type = [];
+ BI.each(axisItems, function(id, item){
+ type.push(BICst.WIDGET.DONUT);
+ });
+ types.push(type);
+ });
+
+ this.combineChart.populate(items, types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function(){
+ this.combineChart.magnify();
+ }
+});
+BI.DonutChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.donut_chart', BI.DonutChart);/**
+ * 图表控件
+ * @class BI.FallAxisChart
+ * @extends BI.Widget
+ */
+BI.FallAxisChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.FallAxisChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-fall-axis-chart"
+ })
+ },
+
+ _init: function () {
+ BI.FallAxisChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.xAxis = [{
+ type: "category",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ position: "bottom",
+ gridLineWidth: 0
+ }];
+ this.yAxis = [{
+ type: "value",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ position: "left",
+ gridLineWidth: 0
+ }];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.FallAxisChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function(config, items){
+ var self = this, o = this.options;
+ var yTitle = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ formatCordon();
+ config.legend.enabled = false;
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.dataSheet.enabled = this.config.showDataTable;
+ if(config.dataSheet.enabled === true){
+ config.xAxis[0].showLabel = false;
+ }
+ config.zoom.zoomTool.enabled = this.config.showZoom;
+ if(this.config.showZoom === true){
+ delete config.dataSheet;
+ delete config.zoom.zoomType;
+ }
+
+ config.yAxis = this.yAxis;
+ BI.extend(config.yAxis[0], {
+ lineWidth: this.config.lineWidth,
+ showLabel: this.config.showLabel,
+ enableTick: this.config.enableTick,
+ enableMinorTick: this.config.enableMinorTick,
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators)
+ });
+ formatNumberLevelInYaxis(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS, config.yAxis[0].formatter);
+ config.yAxis[0].title.rotation = this.constants.ROTATION;
+ config.yAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + yTitle : yTitle;
+
+ config.xAxis[0].title.align = "center";
+ config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
+ BI.extend(config.xAxis[0], {
+ lineWidth: this.config.lineWidth,
+ enableTick: this.config.enableTick,
+ enableMinorTick: this.config.enableMinorTick,
+ labelRotation: this.config.textDirection,
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ maxHeight: '40%'
+ });
+
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ if(config.plotOptions.dataLabels.enabled === true){
+ BI.each(items, function(idx, item){
+ if(idx === 0){
+ item.dataLabels = {};
+ return;
+ }
+ item.dataLabels = {
+ "style": self.config.chartFont,
+ "align": "outside",
+ "autoAdjust": true,
+ enabled: true,
+ formatter: {
+ identifier: "${VALUE}",
+ valueFormat: config.yAxis[0].formatter
+ }
+ };
+ });
+ }
+
+ //全局样式的图表文字
+ this.setFontStyle(this.config.chartFont, config);
+
+ return [items, config];
+
+ function formatChartStyle(){
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatCordon(){
+ BI.each(self.config.cordon, function(idx, cor){
+ if(idx === 0 && self.xAxis.length > 0){
+ var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function(i, t){
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style": self.config.chartFont,
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if(idx > 0 && self.yAxis.length >= idx){
+ var magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function(i, t){
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style": self.config.chartFont,
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ }
+
+ function formatNumberLevelInYaxis(type, position, formatter){
+ var magnify = self.calcMagnify(type);
+ BI.each(items, function (idx, item) {
+ BI.each(item.data, function (id, da) {
+ if (position === item.yAxis) {
+ da.y = self.formatXYDataWithMagnify(da.y, magnify);
+ }
+ })
+ });
+ config.plotOptions.tooltip.formatter.valueFormat = formatter;
+ }
+
+ function getXYAxisUnit(numberLevelType, position){
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if(position === self.constants.X_AXIS){
+ self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
+ }
+ if(position === self.constants.LEFT_AXIS){
+ self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
+ }
+ if(position === self.constants.RIGHT_AXIS){
+ self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
+ }
+ return unit === "" ? unit : "(" + unit + ")";
+ }
+ },
+
+ _formatItems: function(items){
+ var o = this.options;
+ if(BI.isEmptyArray(items)){
+ return [];
+ }
+ items = items[0];
+ var tables = [], sum = 0;
+ var colors = this.config.chartColor || [];
+ if(BI.isEmptyArray(colors)){
+ colors = ["rgb(152, 118, 170)", "rgb(0, 157, 227)"];
+ }
+ BI.each(items, function(idx, item){
+ BI.each(item.data, function(i, t){
+ if(t.y < 0){
+ tables.push([t.x, t.y, sum + t.y, t]);
+ }else{
+ tables.push([t.x, t.y, sum, t]);
+ }
+ sum += t.y;
+ });
+ });
+
+ return [BI.map(BI.makeArray(2, null), function(idx, item){
+ return {
+ "data": BI.map(tables, function(id, cell){
+ var axis = BI.extend({}, cell[3], {
+ x: cell[0],
+ y: Math.abs(cell[2 - idx])
+ });
+ if(idx === 1){
+ axis.color = cell[2 - idx] < 0 ? colors[1] : colors[0];
+ }else{
+ axis.color = "rgba(0,0,0,0)";
+ axis.borderColor = "rgba(0,0,0,0)";
+ axis.borderWidth = 0;
+ axis.clickColor = "rgba(0,0,0,0)";
+ axis.mouseOverColor = "rgba(0,0,0,0)";
+ axis.tooltip = {
+ enable: false
+ }
+ }
+ return axis;
+ }),
+ stack: "stackedFall",
+ name: idx === 1 ? items[0].name : BI.UUID()
+ };
+ })];
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ chartColor: options.chartColor || ["#5caae4", "#70cc7f", "#ebbb67", "#e97e7b", "#6ed3c9"],
+ chartStyle: options.chartStyle || c.NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ showDataLabel: options.showDataLabel || false,
+ showDataTable: options.showDataTable || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ showZoom: options.showZoom || false,
+ textDirection: options.textDirection || 0,
+ cordon: options.cordon || [],
+ lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
+ showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
+ enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
+ enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
+ numSeparators: options.numSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE
+ };
+ this.options.items = items;
+ var types = [];
+ BI.each(items, function(idx, axisItems){
+ var type = [];
+ BI.each(axisItems, function(id, item){
+ type.push(BICst.WIDGET.AXIS);
+ });
+ types.push(type);
+ });
+
+ this.combineChart.populate(this._formatItems(items), types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function(){
+ this.combineChart.magnify();
+ }
+});
+BI.FallAxisChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.fall_axis_chart', BI.FallAxisChart);/**
+ * 图表控件
+ * @class BI.ForceBubbleChart
+ * @extends BI.Widget
+ */
+BI.ForceBubbleChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.ForceBubbleChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-force-bubble-chart"
+ })
+ },
+
+ _init: function () {
+ BI.ForceBubbleChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.ForceBubbleChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this, o = this.options;
+ config.chartType = 'forceBubble';
+ config.colors = this.config.chartColor;
+ this.formatChartLegend(config, this.config.chartLegend);
+
+ config.plotOptions.force = true;
+ config.plotOptions.shadow = this.config.bubbleStyle !== this.constants.NO_PROJECT;
+ config.plotOptions.dataLabels.enabled = true;
+ config.plotOptions.dataLabels.align = "inside";
+ config.plotOptions.dataLabels.style = this.config.chartFont;
+ config.plotOptions.dataLabels.formatter.identifier = "${CATEGORY}${VALUE}";
+ delete config.xAxis;
+ delete config.yAxis;
+ delete config.zoom;
+ BI.each(items, function (idx, item) {
+ BI.each(item.data, function (id, da) {
+ da.y = self.formatXYDataWithMagnify(da.y, 1);
+ })
+ });
+ config.legend.style = this.config.chartFont;
+ return [items, config];
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ chartColor: options.chartColor || [],
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ bubbleStyle: options.bubbleStyle || c.NO_PROJECT,
+ chartFont: options.chartFont || c.FONT_STYLE
+ };
+ this.options.items = items;
+
+ var types = [];
+ BI.each(items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function (id, item) {
+ type.push(BICst.WIDGET.FORCE_BUBBLE);
+ });
+ types.push(type);
+ });
+
+ this.combineChart.populate(items, types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.ForceBubbleChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.force_bubble_chart', BI.ForceBubbleChart);/**
+ * 图表控件
+ * @class BI.GISMapChart
+ * @extends BI.Widget
+ */
+BI.GISMapChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.GISMapChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-gis-map-chart"
+ })
+ },
+
+ _init: function () {
+ BI.GISMapChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.GISMapChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ delete config.dataSheet;
+ delete config.legend;
+ delete config.zoom;
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.plotOptions.dataLabels.useHtml = true;
+ config.plotOptions.dataLabels.style = this.config.chartFont;
+ config.plotOptions.dataLabels.formatter = function () {
+ var name = (BI.isArray(this.name) ? '' : this.name + ',') + BI.contentFormat(this.value, '#.##;-#.##') ;
+ var style = "padding: 5px; background-color: rgba(0,0,0,0.4980392156862745);border-color: rgb(0,0,0); border-radius:2px; border-width:0px;";
+ var a = '
' + name + '
';
+ return a;
+ };
+ config.plotOptions.tooltip.shared = true;
+ config.plotOptions.tooltip.formatter = function () {
+ var tip = BI.isArray(this.name) ? '' : this.name;
+ BI.each(this.points, function (idx, point) {
+ tip += ('
' + point.seriesName + ':' + BI.contentFormat((point.size || point.y), '#.##;-#.##') + '
');
+ });
+ return tip;
+ };
+ config.geo = {
+ "tileLayer": "http://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
+ "attribution": "
© 2016 AutoNavi"
+ };
+ if (this.config.showBackgroundLayer === true && BI.isNotNull(this.config.backgroundLayerInfo)) {
+ config.geo = {};
+ if (this.config.backgroundLayerInfo.type === BICst.WMS_SERVER) {
+ config.geo.tileLayer = false;
+ config.geo.wmsUrl = this.config.backgroundLayerInfo.url;
+ config.geo.wmsLayer = this.config.backgroundLayerInfo.wmsLayer
+ } else {
+ config.geo.tileLayer = this.config.backgroundLayerInfo.url;
+ }
+ }
+ config.chartType = "pointMap";
+ config.plotOptions.icon = {
+ iconUrl: BICst.GIS_ICON_PATH,
+ iconSize: [24, 24]
+ };
+
+ config.plotOptions.marker = {
+ symbol: BICst.GIS_ICON_PATH,
+ width: 24,
+ height: 24,
+ enable: true
+ };
+ delete config.xAxis;
+ delete config.yAxis;
+ return [items, config];
+
+ },
+
+ _checkLngLatValid: function (lnglat) {
+ if (lnglat.length < 2) {
+ return false;
+ }
+ return lnglat[0] <= 180 && lnglat[0] >= -180 && lnglat[1] <= 90 && lnglat[1] >= -90;
+ },
+
+ _formatItems: function (items) {
+ var self = this;
+ var results = [];
+ BI.each(items, function (idx, item) {
+ var result = [];
+ BI.each(item, function (id, it) {
+ var res = [];
+ BI.each(it.data, function (i, da) {
+ da.y = self.formatXYDataWithMagnify(da.y, 1);
+ var lnglat = da.x.split(",");
+ if (self.config.lnglat === self.constants.LAT_FIRST) {
+ var lng = lnglat[1];
+ lnglat[1] = lnglat[0];
+ lnglat[0] = lng;
+ }
+ da.lnglat = lnglat;
+ da.value = da.y;
+ da.name = BI.isNotNull(da.z) ? da.z : da.lnglat;
+ if (self._checkLngLatValid(da.lnglat)) {
+ res.push(da);
+ }
+ });
+ if (BI.isNotEmptyArray(res)) {
+ result.push(BI.extend(it, {
+ data: res
+ }));
+ }
+ });
+ if (BI.isNotEmptyArray(result)) {
+ results.push(result);
+ }
+ });
+ return results;
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ lnglat: options.lnglat || c.LNG_FIRST,
+ chartFont: options.chartFont || c.FONT_STYLE,
+ showBackgroundLayer: options.showBackgroundLayer || false,
+ backgroundLayerInfo: options.backgroundLayerInfo
+ };
+ this.options.items = items;
+
+ var types = [];
+ BI.each(items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function () {
+ type.push(BICst.WIDGET.GIS_MAP);
+ });
+ types.push(type);
+ });
+
+ this.combineChart.populate(this._formatItems(items), types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.GISMapChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.gis_map_chart', BI.GISMapChart);/**
+ * 图表控件
+ * @class BI.LineChart
+ * @extends BI.Widget
+ */
+BI.LineChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.LineChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-line-chart"
+ })
+ },
+
+ _init: function () {
+ BI.LineChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.xAxis = [{
+ type: "category",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ position: "bottom",
+ gridLineWidth: 0
+ }];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.LineChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this, o = this.options;
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ formatChartLineStyle();
+ formatCordon();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.plotOptions.connectNulls = this.config.nullContinue;
+ config.dataSheet.enabled = this.config.showDataTable;
+ config.xAxis[0].showLabel = !config.dataSheet.enabled;
+ config.zoom.zoomTool.enabled = this.config.showZoom;
+ if (this.config.showZoom === true) {
+ delete config.dataSheet;
+ delete config.zoom.zoomType;
+ }
+
+ config.yAxis = this.yAxis;
+ BI.each(config.yAxis, function (idx, axis) {
+ var title = "";
+ switch (axis.axisIndex) {
+ case self.constants.LEFT_AXIS:
+ axis.title.rotation = self.constants.ROTATION;
+ title = getXYAxisUnit(self.config.leftYAxisNumberLevel, self.constants.LEFT_AXIS);
+ axis.title.text = self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + title : title;
+ BI.extend(axis, {
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ reversed: self.config.leftYAxisReversed,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)
+ });
+ self.formatNumberLevelInYaxis(config, items, self.config.leftYAxisNumberLevel, idx, axis.formatter);
+ break;
+ case self.constants.RIGHT_AXIS:
+ title = getXYAxisUnit(self.config.rightYAxisNumberLevel, self.constants.RIGHT_AXIS);
+ axis.title.text = self.config.showRightYAxisTitle === true ? self.config.rightYAxisTitle + title : title;
+ axis.title.rotation = self.constants.ROTATION;
+ BI.extend(axis, {
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ reversed: self.config.rightYAxisReversed,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators)
+ });
+ self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisNumberLevel, idx, axis.formatter);
+ break;
+ }
+ });
+
+ config.xAxis[0].title.align = "center";
+ config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
+ BI.extend(config.xAxis[0], {
+ lineWidth: this.config.lineWidth,
+ enableTick: this.config.enableTick,
+ labelRotation: this.config.textDirection,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ maxHeight: '40%'
+ });
+
+ config.chartType = "line";
+
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
+
+ //全局样式的图表文字
+ this.setFontStyle(this.config.chartFont, config);
+
+ return [items, config];
+
+ function formatChartStyle() {
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatCordon() {
+ BI.each(self.config.cordon, function (idx, cor) {
+ if (idx === 0 && self.xAxis.length > 0) {
+ var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if (idx > 0 && self.yAxis.length >= idx) {
+ var magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ }
+
+ function formatChartLineStyle() {
+ switch (self.config.chartLineType) {
+ case BICst.CHART_SHAPE.RIGHT_ANGLE:
+ config.plotOptions.curve = false;
+ config.plotOptions.step = true;
+ break;
+ case BICst.CHART_SHAPE.CURVE:
+ config.plotOptions.curve = true;
+ config.plotOptions.step = false;
+ break;
+ case BICst.CHART_SHAPE.NORMAL:
+ default:
+ config.plotOptions.curve = false;
+ config.plotOptions.step = false;
+ break;
+ }
+ }
+
+ function getXYAxisUnit(numberLevelType, position) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if (position === self.constants.X_AXIS) {
+ self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
+ }
+ if (position === self.constants.LEFT_AXIS) {
+ self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
+ }
+ if (position === self.constants.RIGHT_AXIS) {
+ self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
+ }
+ return unit === "" ? unit : "(" + unit + ")";
+ }
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ rightYAxisTitle: options.rightYAxisTitle || "",
+ chartLineType: options.chartLineType || c.NORMAL,
+ chartColor: options.chartColor || [],
+ chartStyle: options.chartStyle || c.NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ showRightYAxisTitle: options.showRightYAxisTitle || false,
+ leftYAxisReversed: options.leftYAxisReversed || false,
+ rightYAxisReversed: options.rightYAxisReversed || false,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ rightYAxisUnit: options.rightYAxisUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showDataTable: options.showDataTable || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ showZoom: options.showZoom || false,
+ textDirection: options.textDirection || 0,
+ cordon: options.cordon || [],
+ lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
+ showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
+ enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
+ enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
+ numSeparators: options.numSeparators || false,
+ rightNumSeparators: options.rightNumSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE,
+ nullContinue: options.nullContinue || false
+ };
+ this.options.items = items;
+
+ var types = [];
+ BI.each(items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function (id, item) {
+ type.push(BICst.WIDGET.LINE);
+ });
+ types.push(type);
+ });
+
+ this.yAxis = [];
+ BI.each(types, function (idx, type) {
+ if (BI.isEmptyArray(type)) {
+ return;
+ }
+ var newYAxis = {
+ type: "value",
+ title: {
+ style: self.constants.FONT_STYLE
+ },
+ labelStyle: self.constants.FONT_STYLE,
+ position: idx > 0 ? "right" : "left",
+ lineWidth: 1,
+ axisIndex: idx,
+ gridLineWidth: 0
+ };
+ self.yAxis.push(newYAxis);
+ });
+
+ this.combineChart.populate(items, types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.LineChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.line_chart', BI.LineChart);/**
+ * 图表控件
+ * @class BI.MapChart
+ * @extends BI.Widget
+ */
+BI.MapChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.MapChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-map-chart"
+ })
+ },
+
+ _init: function () {
+ BI.MapChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.MapChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this, c = this.constants;
+ formatRangeLegend();
+ delete config.legend;
+ delete config.zoom;
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.plotOptions.tooltip.shared = true;
+ var formatterArray = [];
+ BI.each(items, function (idx, item) {
+ if (BI.has(item, "settings")) {
+ formatterArray.push(formatToolTipAndDataLabel(item.settings.format || c.NORMAL, item.settings.num_level || c.NORMAL,
+ item.settings.unit || "", item.settings.numSeparators || c.NUM_SEPARATORS));
+ }
+ });
+ config.plotOptions.tooltip.formatter = function () {
+ var tip = this.name;
+ var point = this.points[0];
+ var index = BI.isNull(point.size) ? 0 : 1;
+ tip += ('
' + point.seriesName + ':' + BI.contentFormat(point.size || point.y, formatterArray[index]) + '
');
+ return tip;
+ };
+ config.plotOptions.dataLabels.formatter.valueFormat = function () {
+ return BI.contentFormat(arguments[0], formatterArray[0]);
+ };
+ config.plotOptions.dataLabels.style = this.config.chartFont;
+
+ config.plotOptions.bubble.dataLabels = config.plotOptions.dataLabels;
+ config.plotOptions.bubble.dataLabels.formatter.identifier = "${SIZE}";
+
+ config.plotOptions.bubble.tooltip = config.plotOptions.tooltip;
+
+ config.geo = this.config.geo;
+ if (this.config.showBackgroundLayer === true && BI.isNotNull(this.config.backgroundLayerInfo)) {
+ if (this.config.backgroundLayerInfo.type === BICst.WMS_SERVER) {
+ config.geo.tileLayer = false;
+ config.geo.wmsUrl = this.config.backgroundLayerInfo.url;
+ config.geo.wmsLayer = this.config.backgroundLayerInfo.wmsLayer
+ } else {
+ config.geo.tileLayer = this.config.backgroundLayerInfo.url;
+ }
+ }
+ if (this.config.initDrillPath.length > 1) {
+ config.initDrillPath = this.config.initDrillPath;
+ }
+ config.dTools.enabled = true;
+ config.dTools.click = function (point) {
+ point = point || {};
+ var pointOption = point.options || {};
+ self.fireEvent(BI.MapChart.EVENT_CLICK_DTOOL, pointOption);
+ };
+ config.chartType = "areaMap";
+ delete config.xAxis;
+ delete config.yAxis;
+
+ var find = BI.find(items, function (idx, item) {
+ return BI.has(item, "type") && item.type === "areaMap";
+ });
+ if (BI.isNull(find)) {
+ items.push({
+ type: "areaMap",
+ data: []
+ })
+ }
+
+ return [items, config];
+
+ function formatRangeLegend() {
+ config.rangeLegend.enabled = true;
+ switch (self.config.chartLegend) {
+ case BICst.CHART_LEGENDS.BOTTOM:
+ config.rangeLegend.visible = true;
+ config.rangeLegend.position = "bottom";
+ break;
+ case BICst.CHART_LEGENDS.RIGHT:
+ config.rangeLegend.visible = true;
+ config.rangeLegend.position = "right";
+ break;
+ case BICst.CHART_LEGENDS.NOT_SHOW:
+ config.rangeLegend.visible = false;
+ break;
+ }
+ config.rangeLegend.continuous = false;
+ config.rangeLegend.range = getRangeStyle(self.config.mapStyles, self.config.autoCustom, self.config.themeColor);
+ config.rangeLegend.formatter = function () {
+ var to = this.to;
+ if (BI.isNotEmptyArray(items) && BI.has(items[0], "settings")) {
+ var settings = items[0].settings;
+ var legendFormat = formatToolTipAndDataLabel(settings.format || c.NORMAL, settings.num_level || c.NORMAL,
+ settings.unit || "", settings.numSeparators || c.NUM_SEPARATORS);
+ to = BI.contentFormat(to, legendFormat)
+ }
+ return to
+ };
+ }
+
+ function formatToolTipAndDataLabel(format, numberLevel, unit, numSeparators) {
+ var formatter = '#.##';
+ switch (format) {
+ case self.constants.NORMAL:
+ formatter = '#.##';
+ if (numSeparators) formatter = '#,###.##';
+ break;
+ case self.constants.ZERO2POINT:
+ formatter = '#0';
+ if (numSeparators) formatter = '#,###';
+ break;
+ case self.constants.ONE2POINT:
+ formatter = '#0.0';
+ if (numSeparators) formatter = '#,###.0';
+ break;
+ case self.constants.TWO2POINT:
+ formatter = '#0.00';
+ if (numSeparators) formatter = '#,###.00';
+ break;
+ }
+
+ switch (numberLevel) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ formatter += '';
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ formatter += BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ formatter += BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ formatter += BI.i18nText("BI-Yi");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.PERCENT:
+ formatter += '%';
+ break;
+ }
+
+ return formatter + unit;
+ }
+
+ function getRangeStyle(styles, change, defaultColor) {
+ var range = [], color = null, defaultStyle = {};
+ var conditionMax = null, conditionMin = null, min = null;
+
+ BI.each(items, function (idx, item) {
+ BI.each(item.data, function (id, it) {
+ if (BI.isNull(min) || BI.parseFloat(min) > BI.parseFloat(it.y)) {
+ min = it.y
+ }
+ })
+ });
+
+ switch (change) {
+ case BICst.SCALE_SETTING.AUTO:
+ defaultStyle.color = defaultColor;
+ return defaultStyle;
+ case BICst.SCALE_SETTING.CUSTOM:
+ if (styles.length !== 0) {
+ var maxScale = _calculateValueNiceDomain(0, self.max)[1];
+ BI.each(styles, function (idx, style) {
+ if (style.range.max) {
+ range.push({
+ color: style.color || "rgba(255,255,255,0)",
+ from: style.range.min,
+ to: style.range.max
+ });
+ } else {
+ var to = style.range.min < maxScale ? maxScale : 266396;
+ range.push({
+ color: style.color || "rgba(255,255,255,0)",
+ from: style.range.min,
+ to: to,
+ });
+ }
+ color = style.color;
+ conditionMax = style.range.max
+ });
+
+ conditionMin = BI.parseFloat(styles[0].range.min);
+ if (conditionMin !== 0) {
+ range.push({
+ color: "#808080",
+ from: 0,
+ to: conditionMin
+ });
+ }
+
+ if (conditionMax && conditionMax < maxScale) {
+ range.push({
+ color: color || "rgba(255,255,255,0)",
+ from: conditionMax,
+ to: maxScale
+ });
+ }
+ return range;
+ } else {
+ defaultStyle.color = defaultColor;
+ return defaultStyle;
+ }
+ }
+ }
+
+ function _calculateValueNiceDomain(minValue, maxValue) {
+ minValue = Math.min(0, minValue);
+ var tickInterval = _linearTickInterval(minValue, maxValue);
+
+ return _linearNiceDomain(minValue, maxValue, tickInterval);
+ }
+
+ function _linearTickInterval(minValue, maxValue, m) {
+ m = m || 5;
+ var span = maxValue - minValue;
+ var step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10));
+ var err = m / span * step;
+
+ if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
+
+ return step;
+ }
+
+ function _linearNiceDomain(minValue, maxValue, tickInterval) {
+ minValue = VanUtils.accMul(Math.floor(minValue / tickInterval), tickInterval);
+ maxValue = VanUtils.accMul(Math.ceil(maxValue / tickInterval), tickInterval);
+
+ return [minValue, maxValue];
+ }
+ },
+
+ _formatDrillItems: function (items) {
+ var self = this;
+ BI.each(items.series, function (idx, da) {
+ var hasArea = false;
+ BI.each(da.data, function (idx, data) {
+ data.y = self.formatXYDataWithMagnify(data.y, 1);
+ if (BI.has(da, "settings")) {
+ data.y = self.formatXYDataWithMagnify(data.y, self.calcMagnify(da.settings.num_level || self.constants.NORMAL));
+ }
+ if (BI.has(da, "type") && da.type == "bubble") {
+ data.name = data.x;
+ data.size = data.y;
+ } else {
+ data.name = data.x;
+ data.value = data.y;
+ }
+ if (BI.has(da, "type") && da.type === "areaMap") {
+ hasArea = true;
+ }
+ if (BI.has(data, "drilldown")) {
+ self._formatDrillItems(data.drilldown);
+ }
+ });
+ if (hasArea === false) {
+ items.series.push({
+ type: "areaMap",
+ data: []
+ });
+ }
+ });
+ },
+
+ _formatItems: function (items) {
+ var self = this;
+ this.max = null;
+ this.min = null;
+ BI.each(items, function (idx, item) {
+ BI.each(item, function (id, it) {
+ BI.each(it.data, function (i, da) {
+ da.y = self.formatXYDataWithMagnify(da.y, 1);
+ if (BI.has(it, "settings")) {
+ da.y = self.formatXYDataWithMagnify(da.y, self.calcMagnify(it.settings.num_level || self.constants.NORMAL));
+ }
+ if ((BI.isNull(self.max) || BI.parseFloat(da.y) > BI.parseFloat(self.max)) && id === 0) {
+ self.max = da.y;
+ }
+ if ((BI.isNull(self.min) || BI.parseFloat(da.y) < BI.parseFloat(self.min)) && id === 0) {
+ self.min = da.y;
+ }
+ if (BI.has(it, "type") && it.type == "bubble") {
+ da.name = da.x;
+ da.size = da.y;
+ } else {
+ da.name = da.x;
+ da.value = da.y;
+ }
+ if (BI.has(da, "drilldown")) {
+ self._formatDrillItems(da.drilldown);
+ }
+ });
+ })
+ });
+ return items;
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ geo: options.geo,
+ initDrillPath: options.initDrillPath || [],
+ tooltip: options.tooltip || "",
+ themeColor: options.themeColor || "#65bce7",
+ mapStyles: options.mapStyles || [],
+ autoCustom: options.autoCustom || c.AUTO_CUSTOM,
+ showBackgroundLayer: options.showBackgroundLayer || false,
+ backgroundLayerInfo: options.backgroundLayerInfo,
+ chartFont: options.chartFont || c.FONT_STYLE
+ };
+ this.options.items = items;
+
+ var types = [];
+ BI.each(items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function (id, item) {
+ type.push(BICst.WIDGET.MAP);
+ });
+ types.push(type);
+ });
+
+ this.combineChart.populate(this._formatItems(items), types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.MapChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.MapChart.EVENT_CLICK_DTOOL = "EVENT_CLICK_DTOOL";
+BI.shortcut('bi.map_chart', BI.MapChart);/**
+ * 图表控件
+ * @class BI.MultiAxisChart
+ * @extends BI.Widget
+ * leftYxis 左值轴属性
+ * rightYxis 右值轴属性
+ * xAxis 分类轴属性
+ */
+BI.MultiAxisChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.MultiAxisChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-multi-axis-chart"
+ })
+ },
+
+ _init: function () {
+ BI.MultiAxisChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.xAxis = [{
+ type: "category",
+ title: {
+ style: {"fontFamily": "inherit", "color": "#808080", "fontSize": "12px", "fontWeight": ""}
+ },
+ labelStyle: {
+ "fontFamily": "inherit", "color": "#808080", "fontSize": "12px"
+ },
+ position: "bottom",
+ gridLineWidth: 0
+ }];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.MultiAxisChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this, o = this.options;
+ config.colors = this.config.chartColor;
+ config.style = this.formatChartStyle();
+ this.formatCordon();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.plotOptions.connectNulls = this.config.nullContinue;
+ config.dataSheet.enabled = this.config.showDataTable;
+ config.xAxis[0].showLabel = !config.dataSheet.enabled;
+ config.zoom.zoomTool.enabled = this.config.showZoom;
+ if (this.config.showZoom === true) {
+ delete config.dataSheet;
+ delete config.zoom.zoomType;
+ }
+
+ config.yAxis = this.yAxis;
+ BI.each(config.yAxis, function (idx, axis) {
+ var title = "";
+ switch (axis.axisIndex) {
+ case self.constants.LEFT_AXIS:
+ title = self.getXYAxisUnit(self.config.leftYAxisNumberLevel, self.constants.LEFT_AXIS);
+ axis.title.text = self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + title : title;
+ axis.title.rotation = self.constants.ROTATION;
+ BI.extend(axis, {
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ reversed: self.config.leftYAxisReversed,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)
+ });
+ self.formatNumberLevelInYaxis(config, items, self.config.leftYAxisNumberLevel, idx, axis.formatter);
+ break;
+ case self.constants.RIGHT_AXIS:
+ title = self.getXYAxisUnit(self.config.rightYAxisNumberLevel, self.constants.RIGHT_AXIS);
+ axis.title.text = self.config.showRightYAxisTitle === true ? self.config.rightYAxisTitle + title : title;
+ axis.title.rotation = self.constants.ROTATION;
+ BI.extend(axis, {
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ reversed: self.config.rightYAxisReversed,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators)
+ });
+ self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisNumberLevel, idx, axis.formatter);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ title = self.getXYAxisUnit(self.config.rightYAxisSecondNumberLevel, self.constants.RIGHT_AXIS_SECOND);
+ axis.title.text = self.config.showRightYAxisSecondTitle === true ? self.config.rightYAxisSecondTitle + title : title;
+ axis.title.rotation = self.constants.ROTATION;
+ BI.extend(axis, {
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ reversed: self.config.rightYAxisSecondReversed,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.rightYAxisSecondStyle, self.config.rightYAxisSecondNumberLevel, self.config.rightNumSeparators)
+ });
+ self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisSecondNumberLevel, idx, axis.formatter);
+ break;
+ default:
+ break;
+ }
+ });
+ config.xAxis[0].title.align = "center";
+ config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
+ BI.extend(config.xAxis[0], {
+ lineWidth: this.config.lineWidth,
+ enableTick: this.config.enableTick,
+ labelRotation: this.config.textDirection,
+ enableMinorTick: this.config.enableMinorTick,
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ maxHeight: '40%'
+ });
+
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
+
+ //全局样式的图表文字
+ if (config.dataSheet) {
+ config.dataSheet.style = this.config.chartFont;
+ }
+ config.xAxis[0].title.style = config.xAxis[0].labelStyle = this.config.chartFont;
+ config.legend.style = this.config.chartFont;
+ config.plotOptions.dataLabels.style = this.config.chartFont;
+ BI.each(config.yAxis, function (idx, axis) {
+ axis.title.style = self.config.chartFont;
+ });
+
+ return [items, config];
+ },
+
+ formatChartStyle: function () {
+ switch (this.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ },
+
+ formatCordon: function () {
+ var self = this;
+ var magnify = 1;
+ BI.each(this.config.cordon, function (idx, cor) {
+ if (idx === 0 && self.xAxis.length > 0) {
+ magnify = self.calcMagnify(self.config.xAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style": {
+ "fontFamily": "inherit",
+ "color": "#808080",
+ "fontSize": "12px",
+ "fontWeight": ""
+ },
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if (idx > 0 && self.yAxis.length >= idx) {
+ magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
+ break;
+ default:
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style": {
+ "fontFamily": "inherit",
+ "color": "#808080",
+ "fontSize": "12px",
+ "fontWeight": ""
+ },
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ },
+
+ getXYAxisUnit: function (numberLevelType, position) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ default:
+ break;
+ }
+ if (position === this.constants.X_AXIS) {
+ this.config.xAxisUnit !== "" && (unit = unit + this.config.xAxisUnit)
+ }
+ if (position === this.constants.LEFT_AXIS) {
+ this.config.leftYAxisUnit !== "" && (unit = unit + this.config.leftYAxisUnit)
+ }
+ if (position === this.constants.RIGHT_AXIS) {
+ this.config.rightYAxisUnit !== "" && (unit = unit + this.config.rightYAxisUnit)
+ }
+ if (position === this.constants.RIGHT_AXIS_SECOND) {
+ this.config.rightYAxisSecondUnit !== "" && (unit = unit + this.config.rightYAxisSecondUnit)
+ }
+ return unit === "" ? unit : "(" + unit + ")";
+ },
+
+ populate: function (items, options, types) {
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ rightYAxisTitle: options.rightYAxisTitle || "",
+ rightYAxisSecondTitle: options.rightYAxisSecondTitle || "",
+ chartColor: options.chartColor || ["#5caae4", "#70cc7f", "#ebbb67", "#e97e7b", "#6ed3c9"],
+ chartStyle: options.chartStyle || c.NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
+ rightYAxisSecondStyle: options.rightYAxisSecondStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ showRightYAxisTitle: options.showRightYAxisTitle || false,
+ showRightYAxisSecondTitle: options.showRightYAxisSecondTitle || false,
+ leftYAxisReversed: options.leftYAxisReversed || false,
+ rightYAxisReversed: options.rightYAxisReversed || false,
+ rightYAxisSecondReversed: options.rightYAxisSecondReversed || false,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
+ rightYAxisSecondNumberLevel: options.rightYAxisSecondNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ rightYAxisUnit: options.rightYAxisUnit || "",
+ rightYAxisSecondUnit: options.rightYAxisSecondUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showDataTable: options.showDataTable || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ showZoom: options.showZoom || false,
+ textDirection: options.textDirection || 0,
+ cordon: options.cordon || [],
+ lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
+ showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
+ enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
+ enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
+ numSeparators: options.numSeparators || false,
+ rightNumSeparators: options.rightNumSeparators || false,
+ rightNumSeparators: options.rightNumSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE,
+ nullContinue: options.nullContinue || false
+ };
+ this.options.items = items;
+
+ this.yAxis = [];
+ BI.each(types, function (idx, type) {
+ if (BI.isEmptyArray(type)) {
+ return;
+ }
+ var newYAxis = {
+ type: "value",
+ title: {
+ style: {"fontFamily": "inherit", "color": "#808080", "fontSize": "12px", "fontWeight": ""}
+ },
+ labelStyle: {
+ "fontFamily": "inherit", "color": "#808080", "fontSize": "12px"
+ },
+ position: idx > 0 ? "right" : "left",
+ lineWidth: 1,
+ axisIndex: idx,
+ gridLineWidth: 0
+ };
+ self.yAxis.push(newYAxis);
+ });
+
+ this.combineChart.populate(items, types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.MultiAxisChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.multi_axis_chart', BI.MultiAxisChart);/**
+ * 图表控件
+ * @class BI.MultiAxisChart
+ * @extends BI.Widget
+ * leftYxis 左值轴属性
+ * rightYxis 右值轴属性
+ * xAxis 分类轴属性
+ */
+BI.MultiAxisCombineChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.MultiAxisCombineChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-multi-axis-combine-chart"
+ })
+ },
+
+ _init: function () {
+ BI.MultiAxisCombineChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.xAxis = [{
+ type: "category",
+ title: {
+ style: {"fontFamily": "inherit", "color": "#808080", "fontSize": "12px", "fontWeight": ""}
+ },
+ labelStyle: {
+ "fontFamily": "inherit", "color": "#808080", "fontSize": "12px"
+ },
+ position: "bottom",
+ gridLineWidth: 0
+ }];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.MultiAxisCombineChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this, o = this.options;
+ config.colors = this.config.chartColor;
+ config.style = this.formatChartStyle();
+ this.formatCordon();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.plotOptions.connectNulls = this.config.nullContinue;
+ config.dataSheet.enabled = this.config.showDataTable;
+ config.xAxis[0].showLabel = !config.dataSheet.enabled;
+ config.zoom.zoomTool.enabled = this.config.showZoom;
+ if (this.config.showZoom === true) {
+ delete config.dataSheet;
+ delete config.zoom.zoomType;
+ }
+
+ config.yAxis = this.yAxis;
+ BI.each(config.yAxis, function (idx, axis) {
+ var title = "";
+ switch (axis.axisIndex) {
+ case self.constants.LEFT_AXIS:
+ title = self.getXYAxisUnit(self.config.leftYAxisNumberLevel, self.constants.LEFT_AXIS);
+ axis.title.text = self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + title : title;
+ axis.title.rotation = self.constants.ROTATION;
+ axis.labelStyle.color = axis.lineColor = axis.tickColor = config.colors[0];
+ BI.extend(axis, {
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ reversed: self.config.leftYAxisReversed,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)
+ });
+ self.formatNumberLevelInYaxis(config, items, self.config.leftYAxisNumberLevel, idx, axis.formatter);
+ break;
+ case self.constants.RIGHT_AXIS:
+ title = self.getXYAxisUnit(self.config.rightYAxisNumberLevel, self.constants.RIGHT_AXIS);
+ axis.title.text = self.config.showRightYAxisTitle === true ? self.config.rightYAxisTitle + title : title;
+ axis.title.rotation = self.constants.ROTATION;
+ axis.labelStyle.color = axis.lineColor = axis.tickColor = config.colors[1];
+ BI.extend(axis, {
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ reversed: self.config.rightYAxisReversed,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.rightYAxisStyle, self.config.rightYAxisNumberLevel, self.config.rightNumSeparators)
+ });
+ self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisNumberLevel, idx, axis.formatter);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ title = self.getXYAxisUnit(self.config.rightYAxisSecondNumberLevel, self.constants.RIGHT_AXIS_SECOND);
+ axis.title.text = self.config.showRightYAxisSecondTitle === true ? self.config.rightYAxisSecondTitle + title : title;
+ axis.title.rotation = self.constants.ROTATION;
+ axis.labelStyle.color = axis.lineColor = axis.tickColor = config.colors[2];
+ BI.extend(axis, {
+ lineWidth: self.config.lineWidth,
+ showLabel: self.config.showLabel,
+ enableTick: self.config.enableTick,
+ reversed: self.config.rightYAxisSecondReversed,
+ enableMinorTick: self.config.enableMinorTick,
+ gridLineWidth: self.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(self.config.rightYAxisSecondStyle, self.config.rightYAxisSecondNumberLevel, self.config.rightNumSeparators)
+ });
+ self.formatNumberLevelInYaxis(config, items, self.config.rightYAxisSecondNumberLevel, idx, axis.formatter);
+ break;
+ default:
+ break;
+ }
+ });
+ config.xAxis[0].title.align = "center";
+ config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
+ BI.extend(config.xAxis[0], {
+ lineWidth: this.config.lineWidth,
+ enableTick: this.config.enableTick,
+ labelRotation: this.config.textDirection,
+ enableMinorTick: this.config.enableMinorTick,
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ maxHeight: '40%'
+ });
+
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ this.formatDataLabel(config.plotOptions.dataLabels.enabled, items, config, this.config.chartFont);
+
+ //全局样式的图表文字
+ if (config.dataSheet) {
+ config.dataSheet.style = this.config.chartFont;
+ }
+ config.xAxis[0].title.style = config.xAxis[0].labelStyle = this.config.chartFont;
+ config.legend.style = this.config.chartFont;
+ config.plotOptions.dataLabels.style = this.config.chartFont;
+ BI.each(config.yAxis, function (idx, axis) {
+ axis.title.style = self.config.chartFont;
+ });
+
+ return [items, config];
+ },
+
+ formatChartStyle: function () {
+ switch (this.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ },
+
+ formatCordon: function () {
+ var self = this;
+ var magnify = 1;
+ BI.each(this.config.cordon, function (idx, cor) {
+ if (idx === 0 && self.xAxis.length > 0) {
+ magnify = self.calcMagnify(self.config.xAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style": {
+ "fontFamily": "inherit",
+ "color": "#808080",
+ "fontSize": "12px",
+ "fontWeight": ""
+ },
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if (idx > 0 && self.yAxis.length >= idx) {
+ magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
+ break;
+ default:
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style": {
+ "fontFamily": "inherit",
+ "color": "#808080",
+ "fontSize": "12px",
+ "fontWeight": ""
+ },
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ },
+
+ getXYAxisUnit: function (numberLevelType, position) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ default:
+ break;
+ }
+ if (position === this.constants.X_AXIS) {
+ this.config.xAxisUnit !== "" && (unit = unit + this.config.xAxisUnit)
+ }
+ if (position === this.constants.LEFT_AXIS) {
+ this.config.leftYAxisUnit !== "" && (unit = unit + this.config.leftYAxisUnit)
+ }
+ if (position === this.constants.RIGHT_AXIS) {
+ this.config.rightYAxisUnit !== "" && (unit = unit + this.config.rightYAxisUnit)
+ }
+ if (position === this.constants.RIGHT_AXIS_SECOND) {
+ this.config.rightYAxisSecondUnit !== "" && (unit = unit + this.config.rightYAxisSecondUnit)
+ }
+ return unit === "" ? unit : "(" + unit + ")";
+ },
+
+ populate: function (items, options, types) {
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ rightYAxisTitle: options.rightYAxisTitle || "",
+ rightYAxisSecondTitle: options.rightYAxisSecondTitle || "",
+ chartColor: options.chartColor || ["#5caae4", "#70cc7f", "#ebbb67", "#e97e7b", "#6ed3c9"],
+ chartStyle: options.chartStyle || c.NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ rightYAxisStyle: options.rightYAxisStyle || c.NORMAL,
+ rightYAxisSecondStyle: options.rightYAxisSecondStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ showRightYAxisTitle: options.showRightYAxisTitle || false,
+ showRightYAxisSecondTitle: options.showRightYAxisSecondTitle || false,
+ leftYAxisReversed: options.leftYAxisReversed || false,
+ rightYAxisReversed: options.rightYAxisReversed || false,
+ rightYAxisSecondReversed: options.rightYAxisSecondReversed || false,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ rightYAxisNumberLevel: options.rightYAxisNumberLevel || c.NORMAL,
+ rightYAxisSecondNumberLevel: options.rightYAxisSecondNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ rightYAxisUnit: options.rightYAxisUnit || "",
+ rightYAxisSecondUnit: options.rightYAxisSecondUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showDataTable: options.showDataTable || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ showZoom: options.showZoom || false,
+ textDirection: options.textDirection || 0,
+ cordon: options.cordon || [],
+ lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
+ showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
+ enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
+ enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
+ numSeparators: options.numSeparators || false,
+ rightNumSeparators: options.rightNumSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE,
+ nullContinue: options.nullContinue || false
+ };
+ this.options.items = items;
+
+ this.yAxis = [];
+ BI.each(types, function (idx, type) {
+ if (BI.isEmptyArray(type)) {
+ return;
+ }
+ var newYAxis = {
+ type: "value",
+ title: {
+ style: {"fontFamily": "inherit", "color": "#808080", "fontSize": "12px", "fontWeight": ""}
+ },
+ labelStyle: {
+ "fontFamily": "inherit", "color": "#808080", "fontSize": "12px"
+ },
+ position: idx > 0 ? "right" : "left",
+ lineWidth: 1,
+ axisIndex: idx,
+ gridLineWidth: 0
+ };
+ self.yAxis.push(newYAxis);
+ });
+
+ this.combineChart.populate(items, types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.MultiAxisCombineChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.multi_axis_combine_chart', BI.MultiAxisCombineChart);/**
+ * 图表控件
+ * @class BI.PercentAccumulateAreaChart
+ * @extends BI.Widget
+ */
+BI.PercentAccumulateAreaChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.PercentAccumulateAreaChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-percent-accumulate-area-chart"
+ })
+ },
+
+ _init: function () {
+ BI.PercentAccumulateAreaChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.xAxis = [{
+ type: "category",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ position: "bottom",
+ gridLineWidth: 0
+ }];
+ this.yAxis = [{
+ type: "value",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ position: "left",
+ gridLineWidth: 0
+ }];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.PercentAccumulateAreaChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this;
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ formatCordon();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.plotOptions.connectNulls = this.config.nullContinue;
+ config.dataSheet.enabled = this.config.showDataTable;
+ config.xAxis[0].showLabel = !config.dataSheet.enabled;
+ config.zoom.zoomTool.enabled = this.config.showZoom;
+ if (this.config.showZoom === true) {
+ delete config.dataSheet;
+ delete config.zoom.zoomType;
+ }
+
+ config.yAxis = this.yAxis;
+ config.yAxis[0].title.text = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
+ config.yAxis[0].title.rotation = this.constants.ROTATION;
+ BI.extend(config.yAxis[0], {
+ lineWidth: this.config.lineWidth,
+ showLabel: this.config.showLabel,
+ enableTick: this.config.enableTick,
+ reversed: this.config.leftYAxisReversed,
+ enableMinorTick: this.config.enableMinorTick,
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators)
+ });
+ self.formatNumberLevelInYaxis(config, items, this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS, config.yAxis[0].formatter, true);
+
+ config.xAxis[0].title.align = "center";
+ config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
+ BI.extend(config.xAxis[0], {
+ lineWidth: this.config.lineWidth,
+ enableTick: this.config.enableTick,
+ labelRotation: this.config.textDirection,
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ maxHeight: '40%'
+ });
+
+ config.chartType = "area";
+
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ this.formatDataLabelForAxis(config.plotOptions.dataLabels.enabled, items, config.yAxis[0].formatter, this.config.chartFont, true);
+
+ //全局样式的图表文字
+ this.setFontStyle(this.config.chartFont, config);
+
+ return [items, config];
+
+ function formatChartStyle() {
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatCordon() {
+ BI.each(self.config.cordon, function (idx, cor) {
+ if (idx === 0 && self.xAxis.length > 0) {
+ var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style": self.config.chartFont,
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if (idx > 0 && self.yAxis.length >= idx) {
+ var magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style": self.config.chartFont,
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ }
+
+ function getXYAxisUnit(numberLevelType, position) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if (position === self.constants.X_AXIS) {
+ self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
+ }
+ if (position === self.constants.LEFT_AXIS) {
+ self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
+ }
+
+ unit = unit === "" ? unit : "(" + unit + ")";
+
+ return self.config.showLeftYAxisTitle === true ? self.config.leftYAxisTitle + unit : unit
+ }
+ },
+
+ _formatItems: function (items) {
+ return BI.map(items, function (idx, item) {
+ var i = BI.UUID();
+ return BI.map(item, function (id, it) {
+ return BI.extend({}, it, {stack: i, stackByPercent: true});
+ });
+ });
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ chartColor: options.chartColor || [],
+ chartStyle: options.chartStyle || c.NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ leftYAxisReversed: options.leftYAxisReversed || false,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showDataTable: options.showDataTable || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ showZoom: options.showZoom || false,
+ textDirection: options.textDirection || 0,
+ cordon: options.cordon || [],
+ lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
+ showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
+ enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
+ enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
+ numSeparators: options.numSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE,
+ nullContinue: options.nullContinue || false
+ };
+ this.options.items = items;
+
+ var types = [];
+ BI.each(items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function (id, item) {
+ type.push(BICst.WIDGET.AREA);
+ });
+ types.push(type);
+ });
+
+ this.combineChart.populate(this._formatItems(items), types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.PercentAccumulateAreaChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.percent_accumulate_area_chart', BI.PercentAccumulateAreaChart);/**
+ * 图表控件 百分比堆积柱状
+ * @class BI.PercentAccumulateAxisChart
+ * @extends BI.Widget
+ */
+BI.PercentAccumulateAxisChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.PercentAccumulateAxisChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-percent-accumulate-axis-chart"
+ })
+ },
+
+ _init: function () {
+ BI.PercentAccumulateAxisChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.xAxis = [{
+ type: "category",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ position: "bottom",
+ gridLineWidth: 0
+ }];
+ this.yAxis = [{
+ type: "value",
+ title: {
+ style: self.constants.FONT_STYLE
+ },
+ labelStyle: self.constants.FONT_STYLE,
+ position: "left",
+ gridLineWidth: 0
+ }];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.PercentAccumulateAxisChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this, o = this.options;
+ var yTitle = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ formatCordon();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.dataSheet.enabled = this.config.showDataTable;
+ config.xAxis[0].showLabel = !config.dataSheet.enabled;
+ config.zoom.zoomTool.enabled = this.config.showZoom;
+ if (this.config.showZoom === true) {
+ delete config.dataSheet;
+ delete config.zoom.zoomType;
+ }
+
+ config.yAxis = this.yAxis;
+ config.yAxis[0].title.rotation = this.constants.ROTATION;
+ config.yAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + yTitle : yTitle;
+ BI.extend(config.yAxis[0], {
+ lineWidth: this.config.lineWidth,
+ showLabel: this.config.showLabel,
+ enableTick: this.config.enableTick,
+ reversed: this.config.leftYAxisReversed,
+ enableMinorTick: this.config.enableMinorTick,
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ formatter: self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators)
+ });
+ self.formatNumberLevelInYaxis(config, items, this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS, config.yAxis[0].formatter, true);
+
+ config.xAxis[0].title.align = "center";
+ config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
+ BI.extend(config.xAxis[0], {
+ lineWidth: this.config.lineWidth,
+ enableTick: this.config.enableTick,
+ labelRotation: this.config.textDirection,
+ enableMinorTick: this.config.enableMinorTick,
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ maxHeight: '40%'
+ });
+
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ this.formatDataLabelForAxis(config.plotOptions.dataLabels.enabled, items, config.yAxis[0].formatter, this.config.chartFont, true);
+
+ //全局样式的图表文字
+ this.setFontStyle(this.config.chartFont, config);
+
+ return [items, config];
+
+ function formatChartStyle() {
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatCordon() {
+ BI.each(self.config.cordon, function (idx, cor) {
+ if (idx === 0 && self.xAxis.length > 0) {
+ var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if (idx > 0 && self.yAxis.length >= idx) {
+ var magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ }
+
+ function getXYAxisUnit(numberLevelType, position) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if (position === self.constants.X_AXIS) {
+ self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
+ }
+ if (position === self.constants.LEFT_AXIS) {
+ self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
+ }
+ return unit === "" ? unit : "(" + unit + ")";
+ }
+ },
+
+ _formatItems: function (items) {
+ return BI.map(items, function (idx, item) {
+ var i = BI.UUID();
+ return BI.map(item, function (id, it) {
+ return BI.extend({}, it, {stack: i, stackByPercent: true});
+ });
+ });
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ chartColor: options.chartColor || [],
+ chartStyle: options.chartStyle || c.NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ leftYAxisReversed: options.leftYAxisReversed || false,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showDataTable: options.showDataTable || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ showZoom: options.showZoom || false,
+ textDirection: options.textDirection || 0,
+ cordon: options.cordon || [],
+ lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
+ showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
+ enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
+ enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
+ numSeparators: options.numSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE
+ };
+ this.options.items = items;
+
+ var types = [];
+ BI.each(items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function (id, item) {
+ type.push(BICst.WIDGET.AXIS);
+ });
+ types.push(type);
+ });
+
+ this.combineChart.populate(this._formatItems(items), types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.PercentAccumulateAxisChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.percent_accumulate_axis_chart', BI.PercentAccumulateAxisChart);/**
+ * 图表控件
+ * @class BI.PieChart
+ * @extends BI.Widget
+ */
+BI.PieChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.PieChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-pie-chart"
+ })
+ },
+
+ _init: function () {
+ BI.PieChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.PieChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function(config, items){
+ var self = this, o = this.options;
+ delete config.zoom;
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ formatChartPieStyle();
+
+ this.formatChartLegend(config, this.config.chartLegend);
+
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.plotOptions.tooltip.formatter.identifier = "${CATEGORY}${SERIES}${VALUE}${PERCENT}";
+
+ config.chartType = "pie";
+ delete config.xAxis;
+ delete config.yAxis;
+ config.plotOptions.dataLabels.align = "outside";
+ config.plotOptions.dataLabels.connectorWidth = "outside";
+ config.plotOptions.dataLabels.formatter.identifier = "${VALUE}${PERCENT}";
+ config.plotOptions.dataLabels.style = this.config.chartFont;
+ BI.each(items, function (idx, item) {
+ BI.each(item.data, function (id, da) {
+ da.y = self.formatXYDataWithMagnify(da.y, 1);
+ })
+ });
+
+ config.legend.style = this.config.chartFont;
+
+ return [items, config];
+
+ function formatChartStyle(){
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatChartPieStyle(){
+ switch (self.config.chartPieType){
+ case BICst.CHART_SHAPE.EQUAL_ARC_ROSE:
+ config.plotOptions.roseType = "sameArc";
+ break;
+ case BICst.CHART_SHAPE.NOT_EQUAL_ARC_ROSE:
+ config.plotOptions.roseType = "differentArc";
+ break;
+ case BICst.CHART_SHAPE.NORMAL:
+ default:
+ delete config.plotOptions.roseType;
+ break;
+ }
+ config.plotOptions.innerRadius = self.config.chartInnerRadius + "%";
+ config.plotOptions.endAngle = self.config.chartTotalAngle;
+ }
+
+ },
+
+ //目前饼图不会有多个系列,如果有多个就要把它们合并在一起
+ _isNeedConvert: function(items){
+ var result = BI.find(items, function(idx, item){
+ return item.length > 1;
+ });
+ return BI.isNotNull(result);
+ },
+
+ _formatItems: function(items){
+ if(this._isNeedConvert(items)){
+ //把每个坐标轴所有的多个系列合并成一个系列
+ return BI.map(items, function(idx, item){
+ var seriesItem = [];
+ var obj = {data: [], name: ""};
+ seriesItem.push(obj);
+ BI.each(item, function(id, series){
+ BI.each(series.data, function(i, da){
+ obj.data.push(BI.extend({}, da, {x: series.name}));
+ });
+ });
+ return seriesItem;
+ })
+ }else{
+ return items;
+ }
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ chartColor: options.chartColor || [],
+ chartStyle: options.chartStyle || c.NORMAL,
+ chartPieType: options.chartPieType || c.NORMAL,
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ chartInnerRadius: options.chartInnerRadius || 0,
+ chartTotalAngle: options.chartTotalAngle || BICst.PIE_ANGLES.TOTAL,
+ chartFont: options.chartFont || c.FONT_STYLE
+ };
+ this.options.items = items;
+
+ var types = [];
+ BI.each(items, function(idx, axisItems){
+ var type = [];
+ BI.each(axisItems, function(id, item){
+ type.push(BICst.WIDGET.PIE);
+ });
+ types.push(type);
+ });
+
+ this.combineChart.populate(this._formatItems(items), types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function(){
+ this.combineChart.magnify();
+ }
+});
+BI.PieChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.pie_chart', BI.PieChart);
+
+/**
+ * 图表控件
+ * @class BI.RadarChart
+ * @extends BI.Widget
+ */
+BI.RadarChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.RadarChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-radar-chart"
+ })
+ },
+
+ _init: function () {
+ BI.RadarChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.radiusAxis = [{
+ type: "value",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ formatter: function () {
+ return this > 0 ? this : (-1) * this
+ },
+ gridLineWidth: 0,
+ position: "bottom"
+ }];
+
+ this.angleAxis = [{
+ type: "category",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE
+ }];
+
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.RadarChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this;
+
+ delete config.zoom;
+
+ var title = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
+
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ formatChartRadarStyle();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.plotOptions.connectNulls = this.config.nullContinue;
+
+ config.radiusAxis = this.radiusAxis;
+ config.angleAxis = this.angleAxis;
+ config.radiusAxis[0].formatter = self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators);
+ formatNumberLevelInYaxis(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS, config.radiusAxis[0].formatter);
+ config.radiusAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + title : title;
+ config.radiusAxis[0].gridLineWidth = this.config.showGridLine === true ? 1 : 0;
+ config.chartType = "radar";
+ delete config.xAxis;
+ delete config.yAxis;
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ this.formatDataLabelForAxis(config.plotOptions.dataLabels.enabled, items, config.radiusAxis[0].formatter, this.config.chartFont);
+
+ //全局样式
+ config.legend.style = this.config.chartFont;
+ config.radiusAxis[0].title.style = config.radiusAxis[0].labelStyle = this.config.chartFont;
+ config.angleAxis[0].title.style = config.angleAxis[0].labelStyle = this.config.chartFont;
+
+ return [items, config];
+
+ function formatChartStyle() {
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatChartRadarStyle() {
+ switch (self.config.chartRadarType) {
+ case BICst.CHART_SHAPE.POLYGON:
+ config.plotOptions.shape = "polygon";
+ break;
+ case BICst.CHART_SHAPE.CIRCLE:
+ config.plotOptions.shape = "circle";
+ break;
+ }
+ }
+
+ function formatNumberLevelInYaxis(type, position, formatter) {
+ var magnify = self.calcMagnify(type);
+ BI.each(items, function (idx, item) {
+ BI.each(item.data, function (id, da) {
+ if (position === item.yAxis) {
+ da.y = self.formatXYDataWithMagnify(da.y, magnify);
+ }
+ })
+ });
+ config.plotOptions.tooltip.formatter.valueFormat = formatter;
+ }
+
+ function getXYAxisUnit(numberLevelType, position) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if (position === self.constants.X_AXIS) {
+ self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
+ }
+ if (position === self.constants.LEFT_AXIS) {
+ self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
+ }
+ if (position === self.constants.RIGHT_AXIS) {
+ self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
+ }
+ return unit === "" ? unit : "(" + unit + ")";
+ }
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ chartRadarType: options.chartRadarType || c.POLYGON,
+ chartColor: options.chartColor || [],
+ chartStyle: options.chartStyle || c.STYLE_NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ cordon: options.cordon || [],
+ numSeparators: options.numSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE,
+ nullContinue: options.nullContinue || false
+ };
+ this.options.items = items;
+ var types = [];
+ BI.each(items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function (id, item) {
+ type.push(BICst.WIDGET.RADAR);
+ });
+ types.push(type);
+ });
+ this.combineChart.populate(items, types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.RadarChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.radar_chart', BI.RadarChart);/**
+ * 图表控件
+ * @class BI.RangeAreaChart
+ * @extends BI.Widget
+ * 范围面积图的构造范围的两组item的必须有对应y值item1完全大于item2
+ */
+BI.RangeAreaChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.RangeAreaChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-range-area-chart"
+ })
+ },
+
+ _init: function () {
+ BI.RangeAreaChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.xAxis = [{
+ type: "category",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ position: "bottom",
+ gridLineWidth: 0
+ }];
+ this.yAxis = [{
+ type: "value",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ position: "left",
+ gridLineWidth: 0
+ }];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.RangeAreaChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+ _formatConfig: function (config, items) {
+ var self = this;
+ var title = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ formatCordon();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.plotOptions.connectNulls = this.config.nullContinue;
+
+ config.yAxis = this.yAxis;
+ config.yAxis[0].title.rotation = this.constants.ROTATION;
+ config.yAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + title : title;
+ BI.extend(config.yAxis[0], {
+ lineWidth: this.config.lineWidth,
+ showLabel: this.config.showLabel,
+ enableTick: this.config.enableTick,
+ enableMinorTick: this.config.enableMinorTick,
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ reversed: config.yAxis[0].reversed = this.config.leftYAxisReversed,
+ formatter: self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators)
+ });
+ formatNumberLevelInYaxis(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS, config.yAxis[0].formatter);
+
+ config.xAxis[0].title.align = "center";
+ config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle : "";
+ BI.extend(config.xAxis[0], {
+ lineWidth: this.config.lineWidth,
+ enableTick: this.config.enableTick,
+ labelRotation: this.config.textDirection,
+ gridLineWidth: this.config.showGridLine === true ? 1 : 0,
+ maxHeight: '40%'
+ });
+
+ config.chartType = "area";
+ config.plotOptions.tooltip.formatter.identifier = "${CATEGORY}${VALUE}";
+
+ //为了给数据标签加个%,还要遍历所有的系列,唉
+ this.formatDataLabelForAxis(config.plotOptions.dataLabels.enabled, items, config.yAxis[0].formatter, this.config.chartFont);
+
+ //全局样式的图表文字
+ this.setFontStyle(this.config.chartFont, config);
+
+ return [items, config];
+
+ function formatChartStyle() {
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatCordon() {
+ BI.each(self.config.cordon, function (idx, cor) {
+ if (idx === 0 && self.xAxis.length > 0) {
+ var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if (idx > 0 && self.yAxis.length >= idx) {
+ var magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style" : self.config.chartFont,
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ }
+
+ function formatNumberLevelInYaxis(type, position, formatter) {
+ var magnify = self.calcMagnify(type);
+ BI.each(items, function (idx, item) {
+ BI.each(item.data, function (id, da) {
+ if (position === item.yAxis) {
+ da.y = self.formatXYDataWithMagnify(da.y, magnify);
+ }
+ })
+ });
+ config.plotOptions.tooltip.formatter.valueFormat = formatter;
+ }
+
+ function getXYAxisUnit(numberLevelType, position) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if (position === self.constants.X_AXIS) {
+ self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
+ }
+ if (position === self.constants.LEFT_AXIS) {
+ self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
+ }
+ return unit === "" ? unit : "(" + unit + ")";
+ }
+ },
+
+ _formatItems: function (data) {
+ var o = this.options;
+ var items = [];
+ BI.each(data, function (idx, item) {
+ items = BI.concat(items, item);
+ });
+ if (BI.isEmptyArray(items)) {
+ return [];
+ }
+ if (items.length === 1) {
+ return [items];
+ }
+ var colors = this.config.chartColor || [];
+ if (BI.isEmptyArray(colors)) {
+ colors = ["#5caae4"];
+ }
+ var seriesMinus = [];
+ BI.each(items[0].data, function (idx, item) {
+ var res = items[1].data[idx].y - item.y;
+ seriesMinus.push({
+ x: items[1].data[idx].x,
+ y: res,
+ targetIds: items[1].data[idx].targetIds
+ });
+ });
+ items[1] = {
+ data: seriesMinus,
+ name: items[1].name,
+ stack: "stackedArea",
+ fillColor: colors[0]
+ };
+ BI.each(items, function (idx, item) {
+ if (idx === 0) {
+ BI.extend(item, {
+ name: items[0].name,
+ fillColorOpacity: 0,
+ stack: "stackedArea",
+ marker: {enabled: false},
+ fillColor: "#000000"
+ });
+ }
+ });
+ return [items];
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ chartColor: options.chartColor || [],
+ chartStyle: options.chartStyle || c.NORMAL,
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ leftYAxisReversed: options.leftYAxisReversed || false,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ textDirection: options.textDirection || 0,
+ cordon: options.cordon || [],
+ lineWidth: BI.isNull(options.lineWidth) ? 1 : options.lineWidth,
+ showLabel: BI.isNull(options.showLabel) ? true : options.showLabel,
+ enableTick: BI.isNull(options.enableTick) ? true : options.enableTick,
+ enableMinorTick: BI.isNull(options.enableMinorTick) ? true : options.enableMinorTick,
+ numSeparators: options.numSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE,
+ nullContinue: options.nullContinue || false
+ };
+ this.options.items = items;
+
+ var types = [];
+ var type = [];
+ BI.each(items, function (idx, axisItems) {
+ type.push(BICst.WIDGET.AREA);
+ });
+ if (BI.isNotEmptyArray(type)) {
+ types.push(type);
+ }
+
+ this.combineChart.populate(this._formatItems(items), types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.RangeAreaChart.EVENT_CHANGE = "EVENT_CHANGE";
+BI.shortcut('bi.range_area_chart', BI.RangeAreaChart);/**
+ * 图表控件
+ * @class BI.ScatterChart
+ * @extends BI.Widget
+ */
+BI.ScatterChart = BI.inherit(BI.AbstractChart, {
+
+ _defaultConfig: function () {
+ return BI.extend(BI.ScatterChart.superclass._defaultConfig.apply(this, arguments), {
+ baseCls: "bi-scatter-chart"
+ })
+ },
+
+ _init: function () {
+ BI.ScatterChart.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ this.xAxis = [{
+ type: "value",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ position: "bottom",
+ gridLineWidth: 0
+ }];
+ this.yAxis = [{
+ type: "value",
+ title: {
+ style: this.constants.FONT_STYLE
+ },
+ labelStyle: this.constants.FONT_STYLE,
+ position: "left",
+ gridLineWidth: 0
+ }];
+ this.combineChart = BI.createWidget({
+ type: "bi.combine_chart",
+ xAxis: this.xAxis,
+ popupItemsGetter: o.popupItemsGetter,
+ formatConfig: BI.bind(this._formatConfig, this),
+ element: this.element
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_CHANGE, function (obj) {
+ self.fireEvent(BI.ScatterChart.EVENT_CHANGE, obj);
+ });
+ this.combineChart.on(BI.CombineChart.EVENT_ITEM_CLICK, function (obj) {
+ self.fireEvent(BI.AbstractChart.EVENT_ITEM_CLICK, obj)
+ });
+ },
+
+
+ _formatConfig: function (config, items) {
+ var self = this;
+ delete config.zoom;
+ config.colors = this.config.chartColor;
+ config.style = formatChartStyle();
+ config.plotOptions.marker = {"symbol": "circle", "radius": 4.5, "enabled": true};
+ formatCordon();
+ this.formatChartLegend(config, this.config.chartLegend);
+ config.plotOptions.dataLabels.enabled = this.config.showDataLabel;
+ config.plotOptions.dataLabels.formatter.identifier = "${X}${Y}";
+
+ config.yAxis = this.yAxis;
+ config.xAxis = this.xAxis;
+
+ config.yAxis[0].formatter = self.formatTickInXYaxis(this.config.leftYAxisStyle, this.config.leftYAxisNumberLevel, this.config.numSeparators);
+ formatNumberLevelInYaxis(this.config.leftYAxisNumberLevel);
+ config.yAxis[0].title.text = getXYAxisUnit(this.config.leftYAxisNumberLevel, this.constants.LEFT_AXIS);
+ config.yAxis[0].title.text = this.config.showLeftYAxisTitle === true ? this.config.leftYAxisTitle + config.yAxis[0].title.text : config.yAxis[0].title.text;
+ config.yAxis[0].gridLineWidth = this.config.showGridLine === true ? 1 : 0;
+ config.yAxis[0].title.rotation = this.constants.ROTATION;
+ config.yAxis[0].maxWidth = '40%';
+
+ config.xAxis[0].formatter = self.formatTickInXYaxis(this.config.xAxisStyle, this.config.xAxisNumberLevel, this.config.rightNumSeparators);
+ formatNumberLevelInXaxis(this.config.xAxisNumberLevel);
+ config.xAxis[0].title.text = getXYAxisUnit(this.config.xAxisNumberLevel, this.constants.X_AXIS);
+ config.xAxis[0].title.text = this.config.showXAxisTitle === true ? this.config.xAxisTitle + config.xAxis[0].title.text : config.xAxis[0].title.text;
+ config.xAxis[0].title.align = "center";
+ config.xAxis[0].gridLineWidth = this.config.showGridLine === true ? 1 : 0;
+ config.xAxis[0].maxHeight = '40%';
+ config.chartType = "scatter";
+
+ if (BI.isNotEmptyArray(this.config.tooltip)) {
+ config.plotOptions.tooltip.formatter = function () {
+ var y = self.formatTickInXYaxis(self.config.leftYAxisStyle, self.config.leftYAxisNumberLevel, self.config.numSeparators)(this.y);
+ var x = self.formatTickInXYaxis(self.config.xAxisStyle, self.config.xAxisNumberLevel, self.config.rightNumSeparators)(this.x);
+ return this.seriesName + '
(X)' + self.config.tooltip[0]
+ + ':' + x + '
(Y)' + self.config.tooltip[1] + ':' + y + '
'
+ };
+ }
+
+ if (config.plotOptions.dataLabels.enabled === true) {
+ BI.each(items, function (idx, item) {
+ item.dataLabels = {
+ "style": self.config.chartFont,
+ "align": "outside",
+ "autoAdjust": true,
+ enabled: true,
+ formatter: {
+ identifier: "${X}${Y}",
+ "XFormat": function () {
+ return BI.contentFormat(arguments[0], '#.##;-#.##')
+ },
+ "YFormat": function () {
+ return BI.contentFormat(arguments[0], '#.##;-#.##')
+ }
+ }
+ };
+ item.dataLabels.formatter.XFormat = config.xAxis[0].formatter;
+ item.dataLabels.formatter.YFormat = config.yAxis[0].formatter;
+ });
+ }
+
+ //全局样式图表文字
+ config.legend.style = this.config.chartFont;
+ config.yAxis[0].title.style = config.yAxis[0].labelStyle = this.config.chartFont;
+ config.xAxis[0].title.style = config.xAxis[0].labelStyle = this.config.chartFont;
+
+ return [items, config];
+
+ function formatChartStyle() {
+ switch (self.config.chartStyle) {
+ case BICst.CHART_STYLE.STYLE_GRADUAL:
+ return "gradual";
+ case BICst.CHART_STYLE.STYLE_NORMAL:
+ default:
+ return "normal";
+ }
+ }
+
+ function formatCordon() {
+ BI.each(self.config.cordon, function (idx, cor) {
+ if (idx === 0 && self.xAxis.length > 0) {
+ var magnify = self.calcMagnify(self.config.xAxisNumberLevel);
+ self.xAxis[0].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style": self.config.chartFont,
+ "text": t.text,
+ "align": "top"
+ }
+ });
+ });
+ }
+ if (idx > 0 && self.yAxis.length >= idx) {
+ var magnify = 1;
+ switch (idx - 1) {
+ case self.constants.LEFT_AXIS:
+ magnify = self.calcMagnify(self.config.leftYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS:
+ magnify = self.calcMagnify(self.config.rightYAxisNumberLevel);
+ break;
+ case self.constants.RIGHT_AXIS_SECOND:
+ magnify = self.calcMagnify(self.config.rightYAxisSecondNumberLevel);
+ break;
+ }
+ self.yAxis[idx - 1].plotLines = BI.map(cor, function (i, t) {
+ return BI.extend(t, {
+ value: t.value.div(magnify),
+ width: 1,
+ label: {
+ "style": self.config.chartFont,
+ "text": t.text,
+ "align": "left"
+ }
+ });
+ });
+ }
+ })
+ }
+
+ function formatNumberLevelInXaxis(type) {
+ var magnify = self.calcMagnify(type);
+ BI.each(items, function (idx, item) {
+ BI.each(item.data, function (id, da) {
+ da.x = self.formatXYDataWithMagnify(da.x, magnify);
+ })
+ })
+ }
+
+ function formatNumberLevelInYaxis(type) {
+ var magnify = self.calcMagnify(type);
+ BI.each(items, function (idx, item) {
+ BI.each(item.data, function (id, da) {
+ da.y = self.formatXYDataWithMagnify(da.y, magnify);
+ })
+ });
+ }
+
+ function getXYAxisUnit(numberLevelType, position) {
+ var unit = "";
+ switch (numberLevelType) {
+ case BICst.TARGET_STYLE.NUM_LEVEL.NORMAL:
+ unit = "";
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.TEN_THOUSAND:
+ unit = BI.i18nText("BI-Wan");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.MILLION:
+ unit = BI.i18nText("BI-Million");
+ break;
+ case BICst.TARGET_STYLE.NUM_LEVEL.YI:
+ unit = BI.i18nText("BI-Yi");
+ break;
+ }
+ if (position === self.constants.X_AXIS) {
+ self.config.xAxisUnit !== "" && (unit = unit + self.config.xAxisUnit)
+ }
+ if (position === self.constants.LEFT_AXIS) {
+ self.config.leftYAxisUnit !== "" && (unit = unit + self.config.leftYAxisUnit)
+ }
+ if (position === self.constants.RIGHT_AXIS) {
+ self.config.rightYAxisUnit !== "" && (unit = unit + self.config.rightYAxisUnit)
+ }
+ return unit === "" ? unit : "(" + unit + ")";
+ }
+ },
+
+ populate: function (items, options) {
+ options || (options = {});
+ var self = this, c = this.constants;
+ this.config = {
+ leftYAxisTitle: options.leftYAxisTitle || "",
+ chartColor: options.chartColor || [],
+ leftYAxisStyle: options.leftYAxisStyle || c.NORMAL,
+ xAxisStyle: options.xAxisStyle || c.NORMAL,
+ showXAxisTitle: options.showXAxisTitle || false,
+ showLeftYAxisTitle: options.showLeftYAxisTitle || false,
+ xAxisNumberLevel: options.xAxisNumberLevel || c.NORMAL,
+ leftYAxisNumberLevel: options.leftYAxisNumberLevel || c.NORMAL,
+ xAxisUnit: options.xAxisUnit || "",
+ leftYAxisUnit: options.leftYAxisUnit || "",
+ xAxisTitle: options.xAxisTitle || "",
+ chartLegend: options.chartLegend || c.LEGEND_BOTTOM,
+ showDataLabel: options.showDataLabel || false,
+ showGridLine: BI.isNull(options.showGridLine) ? true : options.showGridLine,
+ cordon: options.cordon || [],
+ tooltip: options.tooltip || [],
+ numSeparators: options.numSeparators || false,
+ rightNumSeparators: options.rightNumSeparators || false,
+ chartFont: options.chartFont || c.FONT_STYLE
+ };
+ this.options.items = items;
+ var types = [];
+ BI.each(items, function (idx, axisItems) {
+ var type = [];
+ BI.each(axisItems, function (id, item) {
+ type.push(BICst.WIDGET.SCATTER);
+ });
+ types.push(type);
+ });
+ this.combineChart.populate(items, types);
+ },
+
+ resize: function () {
+ this.combineChart.resize();
+ },
+
+ magnify: function () {
+ this.combineChart.magnify();
+ }
+});
+BI.ScatterChart.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut('bi.scatter_chart', BI.ScatterChart);
\ No newline at end of file
diff --git a/docs/core.css b/docs/core.css
index a77c93b59..151794401 100644
--- a/docs/core.css
+++ b/docs/core.css
@@ -3181,6 +3181,9 @@ i {
.base-disabled .bi-input {
color: #cccccc !important;
}
+.base-disabled .bi-textarea {
+ color: #cccccc !important;
+}
.base-disabled .b-font:before {
color: #cccccc !important;
}
@@ -3190,6 +3193,9 @@ i {
.bi-theme-dark .base-disabled .bi-input {
color: #666666 !important;
}
+.bi-theme-dark .base-disabled .bi-textarea {
+ color: #666666 !important;
+}
.bi-theme-dark .base-disabled .b-font:before {
color: #666666 !important;
}
@@ -3215,6 +3221,9 @@ i {
.bi-background .bi-input {
color: #666666;
}
+.bi-background .bi-textarea {
+ color: #666666;
+}
.bi-theme-dark .bi-background {
background-color: #191b2b;
color: #cccccc;
@@ -3222,6 +3231,9 @@ i {
.bi-theme-dark .bi-background .bi-input {
color: #cccccc;
}
+.bi-theme-dark .bi-background .bi-textarea {
+ color: #cccccc;
+}
.bi-card {
background-color: #ffffff;
color: #666666;
@@ -3229,6 +3241,9 @@ i {
.bi-card .bi-input {
color: #666666;
}
+.bi-card .bi-textarea {
+ color: #666666;
+}
.bi-theme-dark .bi-card {
background-color: #242640;
color: #cccccc;
@@ -3236,24 +3251,36 @@ i {
.bi-theme-dark .bi-card .bi-input {
color: #cccccc;
}
+.bi-theme-dark .bi-card .bi-textarea {
+ color: #cccccc;
+}
.bi-disabled {
color: #cccccc;
}
.bi-disabled .bi-input {
color: #cccccc;
}
+.bi-disabled .bi-textarea {
+ color: #cccccc;
+}
.bi-theme-dark .bi-disabled {
color: #666666;
}
.bi-theme-dark .bi-disabled .bi-input {
color: #666666;
}
+.bi-theme-dark .bi-disabled .bi-textarea {
+ color: #666666;
+}
.bi-tips {
color: #999999;
}
.bi-tips .bi-input {
color: #999999;
}
+.bi-tips .bi-textarea {
+ color: #999999;
+}
.bi-border {
border: 1px solid #d4dadd;
}
@@ -3290,12 +3317,18 @@ i {
.bi-keyword-red-mark .bi-input {
color: #f07d0a;
}
+.bi-keyword-red-mark .bi-textarea {
+ color: #f07d0a;
+}
.bi-high-light {
color: #3f8ce8;
}
.bi-high-light .bi-input {
color: #3f8ce8;
}
+.bi-high-light .bi-textarea {
+ color: #3f8ce8;
+}
.bi-high-light-background {
background-color: #3f8ce8;
color: #ffffff;
@@ -3303,6 +3336,9 @@ i {
.bi-high-light-background .bi-input {
color: #ffffff;
}
+.bi-high-light-background .bi-textarea {
+ color: #ffffff;
+}
.bi-high-light-border {
border-color: #178cdf;
}
@@ -3313,12 +3349,18 @@ i {
.bi-water-mark .bi-input {
color: #cccccc;
}
+.bi-water-mark .bi-textarea {
+ color: #cccccc;
+}
.bi-theme-dark .bi-water-mark {
color: #666666;
}
.bi-theme-dark .bi-water-mark .bi-input {
color: #666666;
}
+.bi-theme-dark .bi-water-mark .bi-textarea {
+ color: #666666;
+}
.bi-resizer {
background: #1a1a1a;
opacity: 0.2;
@@ -3336,6 +3378,9 @@ i {
.bi-mask .bi-input {
color: #ffffff;
}
+.bi-mask .bi-textarea {
+ color: #ffffff;
+}
.bi-theme-dark .bi-mask {
color: #242640;
background-color: rgba(255, 255, 255, 0.2);
@@ -3344,6 +3389,9 @@ i {
.bi-theme-dark .bi-mask .bi-input {
color: #242640;
}
+.bi-theme-dark .bi-mask .bi-textarea {
+ color: #242640;
+}
.bi-z-index-mask {
color: #ffffff;
background-color: rgba(26, 26, 26, 0.5);
@@ -3352,6 +3400,9 @@ i {
.bi-z-index-mask .bi-input {
color: #ffffff;
}
+.bi-z-index-mask .bi-textarea {
+ color: #ffffff;
+}
.bi-list-item:hover,
.bi-list-item.hover {
color: #1a1a1a;
@@ -3362,6 +3413,10 @@ i {
.bi-list-item.hover .bi-input {
color: #1a1a1a;
}
+.bi-list-item:hover .bi-textarea,
+.bi-list-item.hover .bi-textarea {
+ color: #1a1a1a;
+}
.bi-list-item.disabled,
.bi-list-item.disabled:hover,
.bi-list-item.disabled:active {
@@ -3373,6 +3428,11 @@ i {
.bi-list-item.disabled:active .bi-input {
color: #cccccc !important;
}
+.bi-list-item.disabled .bi-textarea,
+.bi-list-item.disabled:hover .bi-textarea,
+.bi-list-item.disabled:active .bi-textarea {
+ color: #cccccc !important;
+}
.bi-list-item.disabled .bi-high-light,
.bi-list-item.disabled:hover .bi-high-light,
.bi-list-item.disabled:active .bi-high-light {
@@ -3388,6 +3448,10 @@ i {
.bi-theme-dark .bi-list-item.hover .bi-input {
color: #ffffff;
}
+.bi-theme-dark .bi-list-item:hover .bi-textarea,
+.bi-theme-dark .bi-list-item.hover .bi-textarea {
+ color: #ffffff;
+}
.bi-theme-dark .bi-list-item.disabled,
.bi-theme-dark .bi-list-item.disabled:hover,
.bi-theme-dark .bi-list-item.disabled:active {
@@ -3399,6 +3463,11 @@ i {
.bi-theme-dark .bi-list-item.disabled:active .bi-input {
color: #666666 !important;
}
+.bi-theme-dark .bi-list-item.disabled .bi-textarea,
+.bi-theme-dark .bi-list-item.disabled:hover .bi-textarea,
+.bi-theme-dark .bi-list-item.disabled:active .bi-textarea {
+ color: #666666 !important;
+}
.bi-theme-dark .bi-list-item.disabled .bi-high-light,
.bi-theme-dark .bi-list-item.disabled:hover .bi-high-light,
.bi-theme-dark .bi-list-item.disabled:active .bi-high-light {
@@ -3414,6 +3483,9 @@ i {
.bi-list-item-simple .bi-input {
color: #999999;
}
+.bi-list-item-simple .bi-textarea {
+ color: #999999;
+}
.bi-list-item-simple:hover,
.bi-list-item-simple.hover {
color: #3f8ce8;
@@ -3422,6 +3494,10 @@ i {
.bi-list-item-simple.hover .bi-input {
color: #3f8ce8;
}
+.bi-list-item-simple:hover .bi-textarea,
+.bi-list-item-simple.hover .bi-textarea {
+ color: #3f8ce8;
+}
.bi-list-item-simple.disabled,
.bi-list-item-simple.disabled:hover,
.bi-list-item-simple.disabled:active {
@@ -3432,6 +3508,11 @@ i {
.bi-list-item-simple.disabled:active .bi-input {
color: #cccccc !important;
}
+.bi-list-item-simple.disabled .bi-textarea,
+.bi-list-item-simple.disabled:hover .bi-textarea,
+.bi-list-item-simple.disabled:active .bi-textarea {
+ color: #cccccc !important;
+}
.bi-list-item-simple.disabled .bi-high-light,
.bi-list-item-simple.disabled:hover .bi-high-light,
.bi-list-item-simple.disabled:active .bi-high-light {
@@ -3443,6 +3524,9 @@ i {
.bi-list-item-effect:hover .bi-input {
color: #1a1a1a;
}
+.bi-list-item-effect:hover .bi-textarea {
+ color: #1a1a1a;
+}
.bi-list-item-effect.active,
.bi-list-item-effect:active {
color: #3f8ce8;
@@ -3451,6 +3535,10 @@ i {
.bi-list-item-effect:active .bi-input {
color: #3f8ce8;
}
+.bi-list-item-effect.active .bi-textarea,
+.bi-list-item-effect:active .bi-textarea {
+ color: #3f8ce8;
+}
.bi-list-item-effect.disabled,
.bi-list-item-effect.disabled:hover,
.bi-list-item-effect.disabled:active {
@@ -3461,6 +3549,11 @@ i {
.bi-list-item-effect.disabled:active .bi-input {
color: #cccccc !important;
}
+.bi-list-item-effect.disabled .bi-textarea,
+.bi-list-item-effect.disabled:hover .bi-textarea,
+.bi-list-item-effect.disabled:active .bi-textarea {
+ color: #cccccc !important;
+}
.bi-list-item-effect.disabled .bi-high-light,
.bi-list-item-effect.disabled:hover .bi-high-light,
.bi-list-item-effect.disabled:active .bi-high-light {
@@ -3472,6 +3565,9 @@ i {
.bi-theme-dark .bi-list-item-effect:hover .bi-input {
color: #ffffff;
}
+.bi-theme-dark .bi-list-item-effect:hover .bi-textarea {
+ color: #ffffff;
+}
.bi-theme-dark .bi-list-item-effect.active,
.bi-theme-dark .bi-list-item-effect:active {
color: #3f8ce8;
@@ -3480,6 +3576,10 @@ i {
.bi-theme-dark .bi-list-item-effect:active .bi-input {
color: #3f8ce8;
}
+.bi-theme-dark .bi-list-item-effect.active .bi-textarea,
+.bi-theme-dark .bi-list-item-effect:active .bi-textarea {
+ color: #3f8ce8;
+}
.bi-theme-dark .bi-list-item-effect.disabled,
.bi-theme-dark .bi-list-item-effect.disabled:hover,
.bi-theme-dark .bi-list-item-effect.disabled:active {
@@ -3491,6 +3591,11 @@ i {
.bi-theme-dark .bi-list-item-effect.disabled:active .bi-input {
color: #666666 !important;
}
+.bi-theme-dark .bi-list-item-effect.disabled .bi-textarea,
+.bi-theme-dark .bi-list-item-effect.disabled:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-effect.disabled:active .bi-textarea {
+ color: #666666 !important;
+}
.bi-theme-dark .bi-list-item-effect.disabled .bi-high-light,
.bi-theme-dark .bi-list-item-effect.disabled:hover .bi-high-light,
.bi-theme-dark .bi-list-item-effect.disabled:active .bi-high-light {
@@ -3506,6 +3611,10 @@ i {
.bi-list-item-active.hover .bi-input {
color: #1a1a1a;
}
+.bi-list-item-active:hover .bi-textarea,
+.bi-list-item-active.hover .bi-textarea {
+ color: #1a1a1a;
+}
.bi-list-item-active.active,
.bi-list-item-active:active {
color: #3f8ce8;
@@ -3516,6 +3625,10 @@ i {
.bi-list-item-active:active .bi-input {
color: #3f8ce8;
}
+.bi-list-item-active.active .bi-textarea,
+.bi-list-item-active:active .bi-textarea {
+ color: #3f8ce8;
+}
.bi-list-item-active.disabled,
.bi-list-item-active.disabled:hover,
.bi-list-item-active.disabled:active {
@@ -3527,6 +3640,11 @@ i {
.bi-list-item-active.disabled:active .bi-input {
color: #cccccc !important;
}
+.bi-list-item-active.disabled .bi-textarea,
+.bi-list-item-active.disabled:hover .bi-textarea,
+.bi-list-item-active.disabled:active .bi-textarea {
+ color: #cccccc !important;
+}
.bi-list-item-active.disabled .bi-high-light,
.bi-list-item-active.disabled:hover .bi-high-light,
.bi-list-item-active.disabled:active .bi-high-light {
@@ -3542,6 +3660,10 @@ i {
.bi-theme-dark .bi-list-item-active.hover .bi-input {
color: #ffffff;
}
+.bi-theme-dark .bi-list-item-active:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-active.hover .bi-textarea {
+ color: #ffffff;
+}
.bi-theme-dark .bi-list-item-active.active,
.bi-theme-dark .bi-list-item-active:active {
color: #3f8ce8;
@@ -3552,6 +3674,10 @@ i {
.bi-theme-dark .bi-list-item-active:active .bi-input {
color: #3f8ce8;
}
+.bi-theme-dark .bi-list-item-active.active .bi-textarea,
+.bi-theme-dark .bi-list-item-active:active .bi-textarea {
+ color: #3f8ce8;
+}
.bi-theme-dark .bi-list-item-active.disabled,
.bi-theme-dark .bi-list-item-active.disabled:hover,
.bi-theme-dark .bi-list-item-active.disabled:active {
@@ -3563,6 +3689,11 @@ i {
.bi-theme-dark .bi-list-item-active.disabled:active .bi-input {
color: #666666 !important;
}
+.bi-theme-dark .bi-list-item-active.disabled .bi-textarea,
+.bi-theme-dark .bi-list-item-active.disabled:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-active.disabled:active .bi-textarea {
+ color: #666666 !important;
+}
.bi-theme-dark .bi-list-item-active.disabled .bi-high-light,
.bi-theme-dark .bi-list-item-active.disabled:hover .bi-high-light,
.bi-theme-dark .bi-list-item-active.disabled:active .bi-high-light {
@@ -3577,6 +3708,10 @@ i {
.bi-list-item-active2.hover .bi-input {
color: #1a1a1a;
}
+.bi-list-item-active2:hover .bi-textarea,
+.bi-list-item-active2.hover .bi-textarea {
+ color: #1a1a1a;
+}
.bi-list-item-active2.active,
.bi-list-item-active2:active {
color: #3f8ce8;
@@ -3586,6 +3721,10 @@ i {
.bi-list-item-active2:active .bi-input {
color: #3f8ce8;
}
+.bi-list-item-active2.active .bi-textarea,
+.bi-list-item-active2:active .bi-textarea {
+ color: #3f8ce8;
+}
.bi-list-item-active2.disabled,
.bi-list-item-active2.disabled:hover,
.bi-list-item-active2.disabled:active {
@@ -3597,6 +3736,11 @@ i {
.bi-list-item-active2.disabled:active .bi-input {
color: #cccccc !important;
}
+.bi-list-item-active2.disabled .bi-textarea,
+.bi-list-item-active2.disabled:hover .bi-textarea,
+.bi-list-item-active2.disabled:active .bi-textarea {
+ color: #cccccc !important;
+}
.bi-list-item-active2.disabled .bi-high-light,
.bi-list-item-active2.disabled:hover .bi-high-light,
.bi-list-item-active2.disabled:active .bi-high-light {
@@ -3611,6 +3755,10 @@ i {
.bi-theme-dark .bi-list-item-active2.hover .bi-input {
color: #ffffff;
}
+.bi-theme-dark .bi-list-item-active2:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-active2.hover .bi-textarea {
+ color: #ffffff;
+}
.bi-theme-dark .bi-list-item-active2.active,
.bi-theme-dark .bi-list-item-active2:active {
color: #3f8ce8;
@@ -3620,6 +3768,10 @@ i {
.bi-theme-dark .bi-list-item-active2:active .bi-input {
color: #3f8ce8;
}
+.bi-theme-dark .bi-list-item-active2.active .bi-textarea,
+.bi-theme-dark .bi-list-item-active2:active .bi-textarea {
+ color: #3f8ce8;
+}
.bi-theme-dark .bi-list-item-active2.disabled,
.bi-theme-dark .bi-list-item-active2.disabled:hover,
.bi-theme-dark .bi-list-item-active2.disabled:active {
@@ -3631,6 +3783,11 @@ i {
.bi-theme-dark .bi-list-item-active2.disabled:active .bi-input {
color: #666666 !important;
}
+.bi-theme-dark .bi-list-item-active2.disabled .bi-textarea,
+.bi-theme-dark .bi-list-item-active2.disabled:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-active2.disabled:active .bi-textarea {
+ color: #666666 !important;
+}
.bi-theme-dark .bi-list-item-active2.disabled .bi-high-light,
.bi-theme-dark .bi-list-item-active2.disabled:hover .bi-high-light,
.bi-theme-dark .bi-list-item-active2.disabled:active .bi-high-light {
@@ -3646,6 +3803,10 @@ i {
.bi-list-item-select.hover .bi-input {
color: #1a1a1a;
}
+.bi-list-item-select:hover .bi-textarea,
+.bi-list-item-select.hover .bi-textarea {
+ color: #1a1a1a;
+}
.bi-list-item-select:active,
.bi-list-item-select.active {
color: #ffffff;
@@ -3655,6 +3816,10 @@ i {
.bi-list-item-select.active .bi-input {
color: #ffffff;
}
+.bi-list-item-select:active .bi-textarea,
+.bi-list-item-select.active .bi-textarea {
+ color: #ffffff;
+}
.bi-list-item-select:active .bi-high-light,
.bi-list-item-select.active .bi-high-light {
color: #ffffff;
@@ -3670,6 +3835,11 @@ i {
.bi-list-item-select.disabled:active .bi-input {
color: #cccccc !important;
}
+.bi-list-item-select.disabled .bi-textarea,
+.bi-list-item-select.disabled:hover .bi-textarea,
+.bi-list-item-select.disabled:active .bi-textarea {
+ color: #cccccc !important;
+}
.bi-list-item-select.disabled .bi-high-light,
.bi-list-item-select.disabled:hover .bi-high-light,
.bi-list-item-select.disabled:active .bi-high-light {
@@ -3685,6 +3855,10 @@ i {
.bi-theme-dark .bi-list-item-select.hover .bi-input {
color: #ffffff;
}
+.bi-theme-dark .bi-list-item-select:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-select.hover .bi-textarea {
+ color: #ffffff;
+}
.bi-theme-dark .bi-list-item-select:active,
.bi-theme-dark .bi-list-item-select.active {
color: #ffffff;
@@ -3694,6 +3868,10 @@ i {
.bi-theme-dark .bi-list-item-select.active .bi-input {
color: #ffffff;
}
+.bi-theme-dark .bi-list-item-select:active .bi-textarea,
+.bi-theme-dark .bi-list-item-select.active .bi-textarea {
+ color: #ffffff;
+}
.bi-theme-dark .bi-list-item-select:active .bi-high-light,
.bi-theme-dark .bi-list-item-select.active .bi-high-light {
color: #ffffff;
@@ -3709,6 +3887,11 @@ i {
.bi-theme-dark .bi-list-item-select.disabled:active .bi-input {
color: #666666 !important;
}
+.bi-theme-dark .bi-list-item-select.disabled .bi-textarea,
+.bi-theme-dark .bi-list-item-select.disabled:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-select.disabled:active .bi-textarea {
+ color: #666666 !important;
+}
.bi-theme-dark .bi-list-item-select.disabled .bi-high-light,
.bi-theme-dark .bi-list-item-select.disabled:hover .bi-high-light,
.bi-theme-dark .bi-list-item-select.disabled:active .bi-high-light {
@@ -3723,6 +3906,10 @@ i {
.bi-list-item-none.hover .bi-input {
color: inherit;
}
+.bi-list-item-none:hover .bi-textarea,
+.bi-list-item-none.hover .bi-textarea {
+ color: inherit;
+}
.bi-list-item-none:active,
.bi-list-item-none.active {
color: inherit;
@@ -3732,6 +3919,10 @@ i {
.bi-list-item-none.active .bi-input {
color: inherit;
}
+.bi-list-item-none:active .bi-textarea,
+.bi-list-item-none.active .bi-textarea {
+ color: inherit;
+}
.bi-list-item-none:active .bi-high-light,
.bi-list-item-none.active .bi-high-light {
color: inherit;
@@ -3747,6 +3938,11 @@ i {
.bi-list-item-none.disabled:active .bi-input {
color: #cccccc !important;
}
+.bi-list-item-none.disabled .bi-textarea,
+.bi-list-item-none.disabled:hover .bi-textarea,
+.bi-list-item-none.disabled:active .bi-textarea {
+ color: #cccccc !important;
+}
.bi-list-item-none.disabled .bi-high-light,
.bi-list-item-none.disabled:hover .bi-high-light,
.bi-list-item-none.disabled:active .bi-high-light {
@@ -3761,6 +3957,10 @@ i {
.bi-theme-dark .bi-list-item-none.hover .bi-input {
color: inherit;
}
+.bi-theme-dark .bi-list-item-none:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-none.hover .bi-textarea {
+ color: inherit;
+}
.bi-theme-dark .bi-list-item-none:active,
.bi-theme-dark .bi-list-item-none.active {
color: inherit;
@@ -3770,6 +3970,10 @@ i {
.bi-theme-dark .bi-list-item-none.active .bi-input {
color: inherit;
}
+.bi-theme-dark .bi-list-item-none:active .bi-textarea,
+.bi-theme-dark .bi-list-item-none.active .bi-textarea {
+ color: inherit;
+}
.bi-theme-dark .bi-list-item-none:active .bi-high-light,
.bi-theme-dark .bi-list-item-none.active .bi-high-light {
color: inherit;
@@ -3785,6 +3989,11 @@ i {
.bi-theme-dark .bi-list-item-none.disabled:active .bi-input {
color: #666666 !important;
}
+.bi-theme-dark .bi-list-item-none.disabled .bi-textarea,
+.bi-theme-dark .bi-list-item-none.disabled:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-none.disabled:active .bi-textarea {
+ color: #666666 !important;
+}
.bi-theme-dark .bi-list-item-none.disabled .bi-high-light,
.bi-theme-dark .bi-list-item-none.disabled:hover .bi-high-light,
.bi-theme-dark .bi-list-item-none.disabled:active .bi-high-light {
diff --git a/docs/core.js b/docs/core.js
index 7fb8e8680..1658c3c94 100644
--- a/docs/core.js
+++ b/docs/core.js
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
/*!
* jQuery JavaScript Library v1.9.1
* http://jquery.com/
@@ -28676,4 +28677,28698 @@ $(function () {
if (BI.isIE9Below()) {
BI.GridTableScrollbar.SIZE = 18;
}
+=======
+/*!
+ * jQuery JavaScript Library v1.9.1
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2013-2-4
+ */
+(function( window, undefined ) {
+
+// Can't do this because several apps including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+// Support: Firefox 18+
+//"use strict";
+var
+ // The deferred used on DOM ready
+ readyList,
+
+ // A central reference to the root jQuery(document)
+ rootjQuery,
+
+ // Support: IE<9
+ // For `typeof node.method` instead of `node.method !== undefined`
+ core_strundefined = typeof undefined,
+
+ // Use the correct document accordingly with window argument (sandbox)
+ document = window.document,
+ location = window.location,
+
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$,
+
+ // [[Class]] -> type pairs
+ class2type = {},
+
+ // List of deleted data cache ids, so we can reuse them
+ core_deletedIds = [],
+
+ core_version = "1.9.1",
+
+ // Save a reference to some core methods
+ core_concat = core_deletedIds.concat,
+ core_push = core_deletedIds.push,
+ core_slice = core_deletedIds.slice,
+ core_indexOf = core_deletedIds.indexOf,
+ core_toString = class2type.toString,
+ core_hasOwn = class2type.hasOwnProperty,
+ core_trim = core_version.trim,
+
+ // Define a local copy of jQuery
+ jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context, rootjQuery );
+ },
+
+ // Used for matching numbers
+ core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,
+
+ // Used for splitting on whitespace
+ core_rnotwhite = /\S+/g,
+
+ // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+ // A simple way to check for HTML strings
+ // Prioritize #id over
to avoid XSS via location.hash (#9521)
+ // Strict HTML recognition (#11290: must start with <)
+ rquickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+
+ // Match a standalone tag
+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
+
+ // JSON RegExp
+ rvalidchars = /^[\],:{}\s]*$/,
+ rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+ rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
+ rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,
+
+ // Matches dashed string for camelizing
+ rmsPrefix = /^-ms-/,
+ rdashAlpha = /-([\da-z])/gi,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return letter.toUpperCase();
+ },
+
+ // The ready event handler
+ completed = function( event ) {
+
+ // readyState === "complete" is good enough for us to call the dom ready in oldIE
+ if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
+ detach();
+ jQuery.ready();
+ }
+ },
+ // Clean-up method for dom ready events
+ detach = function() {
+ if ( document.addEventListener ) {
+ document.removeEventListener( "DOMContentLoaded", completed, false );
+ window.removeEventListener( "load", completed, false );
+
+ } else {
+ document.detachEvent( "onreadystatechange", completed );
+ window.detachEvent( "onload", completed );
+ }
+ };
+
+jQuery.fn = jQuery.prototype = {
+ // The current version of jQuery being used
+ jquery: core_version,
+
+ constructor: jQuery,
+ init: function( selector, context, rootjQuery ) {
+ var match, elem;
+
+ // HANDLE: $(""), $(null), $(undefined), $(false)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = rquickExpr.exec( selector );
+ }
+
+ // Match html or make sure no context is specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] ) {
+ context = context instanceof jQuery ? context[0] : context;
+
+ // scripts is true for back-compat
+ jQuery.merge( this, jQuery.parseHTML(
+ match[1],
+ context && context.nodeType ? context.ownerDocument || context : document,
+ true
+ ) );
+
+ // HANDLE: $(html, props)
+ if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+ for ( match in context ) {
+ // Properties of context are called as methods if possible
+ if ( jQuery.isFunction( this[ match ] ) ) {
+ this[ match ]( context[ match ] );
+
+ // ...and otherwise set as attributes
+ } else {
+ this.attr( match, context[ match ] );
+ }
+ }
+ }
+
+ return this;
+
+ // HANDLE: $(#id)
+ } else {
+ elem = document.getElementById( match[2] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id !== match[2] ) {
+ return rootjQuery.find( selector );
+ }
+
+ // Otherwise, we inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || rootjQuery ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(DOMElement)
+ } else if ( selector.nodeType ) {
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return rootjQuery.ready( selector );
+ }
+
+ if ( selector.selector !== undefined ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ },
+
+ // Start with an empty selector
+ selector: "",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ // The number of elements contained in the matched element set
+ size: function() {
+ return this.length;
+ },
+
+ toArray: function() {
+ return core_slice.call( this );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num == null ?
+
+ // Return a 'clean' array
+ this.toArray() :
+
+ // Return just the object
+ ( num < 0 ? this[ this.length + num ] : this[ num ] );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems ) {
+
+ // Build a new jQuery matched element set
+ var ret = jQuery.merge( this.constructor(), elems );
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+ ret.context = this.context;
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ ready: function( fn ) {
+ // Add the callback
+ jQuery.ready.promise().done( fn );
+
+ return this;
+ },
+
+ slice: function() {
+ return this.pushStack( core_slice.apply( this, arguments ) );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ eq: function( i ) {
+ var len = this.length,
+ j = +i + ( i < 0 ? len : 0 );
+ return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor(null);
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: core_push,
+ sort: [].sort,
+ splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+ var src, copyIsArray, copy, name, options, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+ target = arguments[1] || {};
+ // skip the boolean and the target
+ i = 2;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
+
+ // extend jQuery itself if only one argument is passed
+ if ( length === i ) {
+ target = this;
+ --i;
+ }
+
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray(src) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject(src) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend({
+ noConflict: function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+ },
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Hold (or release) the ready event
+ holdReady: function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+ },
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+
+ // Abort if there are pending holds or we're already ready
+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+ return;
+ }
+
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( !document.body ) {
+ return setTimeout( jQuery.ready );
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ readyList.resolveWith( document, [ jQuery ] );
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.trigger ) {
+ jQuery( document ).trigger("ready").off("ready");
+ }
+ },
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return jQuery.type(obj) === "function";
+ },
+
+ isArray: Array.isArray || function( obj ) {
+ return jQuery.type(obj) === "array";
+ },
+
+ isWindow: function( obj ) {
+ return obj != null && obj == obj.window;
+ },
+
+ isNumeric: function( obj ) {
+ return !isNaN( parseFloat(obj) ) && isFinite( obj );
+ },
+
+ type: function( obj ) {
+ if ( obj == null ) {
+ return String( obj );
+ }
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[ core_toString.call(obj) ] || "object" :
+ typeof obj;
+ },
+
+ isPlainObject: function( obj ) {
+ // Must be an Object.
+ // Because of IE, we also have to check the presence of the constructor property.
+ // Make sure that DOM nodes and window objects don't pass through, as well
+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ try {
+ // Not own constructor property must be Object
+ if ( obj.constructor &&
+ !core_hasOwn.call(obj, "constructor") &&
+ !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+ return false;
+ }
+ } catch ( e ) {
+ // IE8,9 Will throw exceptions on certain host objects #9897
+ return false;
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own.
+
+ var key;
+ for ( key in obj ) {}
+
+ return key === undefined || core_hasOwn.call( obj, key );
+ },
+
+ isEmptyObject: function( obj ) {
+ var name;
+ for ( name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ // data: string of html
+ // context (optional): If specified, the fragment will be created in this context, defaults to document
+ // keepScripts (optional): If true, will include scripts passed in the html string
+ parseHTML: function( data, context, keepScripts ) {
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+ if ( typeof context === "boolean" ) {
+ keepScripts = context;
+ context = false;
+ }
+ context = context || document;
+
+ var parsed = rsingleTag.exec( data ),
+ scripts = !keepScripts && [];
+
+ // Single tag
+ if ( parsed ) {
+ return [ context.createElement( parsed[1] ) ];
+ }
+
+ parsed = jQuery.buildFragment( [ data ], context, scripts );
+ if ( scripts ) {
+ jQuery( scripts ).remove();
+ }
+ return jQuery.merge( [], parsed.childNodes );
+ },
+
+ parseJSON: function( data ) {
+ // Attempt to parse using the native JSON parser first
+ if ( window.JSON && window.JSON.parse ) {
+ return window.JSON.parse( data );
+ }
+
+ if ( data === null ) {
+ return data;
+ }
+
+ if ( typeof data === "string" ) {
+
+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
+ data = jQuery.trim( data );
+
+ if ( data ) {
+ // Make sure the incoming data is actual JSON
+ // Logic borrowed from http://json.org/json2.js
+ if ( rvalidchars.test( data.replace( rvalidescape, "@" )
+ .replace( rvalidtokens, "]" )
+ .replace( rvalidbraces, "")) ) {
+
+ return ( new Function( "return " + data ) )();
+ }
+ }
+ }
+
+ jQuery.error( "Invalid JSON: " + data );
+ },
+
+ // Cross-browser xml parsing
+ parseXML: function( data ) {
+ var xml, tmp;
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+ try {
+ if ( window.DOMParser ) { // Standard
+ tmp = new DOMParser();
+ xml = tmp.parseFromString( data , "text/xml" );
+ } else { // IE
+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
+ xml.async = "false";
+ xml.loadXML( data );
+ }
+ } catch( e ) {
+ xml = undefined;
+ }
+ if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+ },
+
+ noop: function() {},
+
+ // Evaluates a script in a global context
+ // Workarounds based on findings by Jim Driscoll
+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+ globalEval: function( data ) {
+ if ( data && jQuery.trim( data ) ) {
+ // We use execScript on Internet Explorer
+ // We use an anonymous function so that context is window
+ // rather than jQuery in Firefox
+ ( window.execScript || function( data ) {
+ window[ "eval" ].call( window, data );
+ } )( data );
+ }
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+ },
+
+ // args is for internal usage only
+ each: function( obj, callback, args ) {
+ var value,
+ i = 0,
+ length = obj.length,
+ isArray = isArraylike( obj );
+
+ if ( args ) {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+ }
+
+ return obj;
+ },
+
+ // Use native String.trim function wherever possible
+ trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
+ function( text ) {
+ return text == null ?
+ "" :
+ core_trim.call( text );
+ } :
+
+ // Otherwise use our own trimming functionality
+ function( text ) {
+ return text == null ?
+ "" :
+ ( text + "" ).replace( rtrim, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( arr, results ) {
+ var ret = results || [];
+
+ if ( arr != null ) {
+ if ( isArraylike( Object(arr) ) ) {
+ jQuery.merge( ret,
+ typeof arr === "string" ?
+ [ arr ] : arr
+ );
+ } else {
+ core_push.call( ret, arr );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, arr, i ) {
+ var len;
+
+ if ( arr ) {
+ if ( core_indexOf ) {
+ return core_indexOf.call( arr, elem, i );
+ }
+
+ len = arr.length;
+ i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+ for ( ; i < len; i++ ) {
+ // Skip accessing in sparse arrays
+ if ( i in arr && arr[ i ] === elem ) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+ },
+
+ merge: function( first, second ) {
+ var l = second.length,
+ i = first.length,
+ j = 0;
+
+ if ( typeof l === "number" ) {
+ for ( ; j < l; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+ } else {
+ while ( second[j] !== undefined ) {
+ first[ i++ ] = second[ j++ ];
+ }
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, inv ) {
+ var retVal,
+ ret = [],
+ i = 0,
+ length = elems.length;
+ inv = !!inv;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( ; i < length; i++ ) {
+ retVal = !!callback( elems[ i ], i );
+ if ( inv !== retVal ) {
+ ret.push( elems[ i ] );
+ }
+ }
+
+ return ret;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var value,
+ i = 0,
+ length = elems.length,
+ isArray = isArraylike( elems ),
+ ret = [];
+
+ // Go through the array, translating each of the items to their
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( i in elems ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return core_concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ var args, proxy, tmp;
+
+ if ( typeof context === "string" ) {
+ tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ args = core_slice.call( arguments, 2 );
+ proxy = function() {
+ return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ // Multifunctional method to get and set values of a collection
+ // The value/s can optionally be executed if it's a function
+ access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
+ var i = 0,
+ length = elems.length,
+ bulk = key == null;
+
+ // Sets many values
+ if ( jQuery.type( key ) === "object" ) {
+ chainable = true;
+ for ( i in key ) {
+ jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
+ }
+
+ // Sets one value
+ } else if ( value !== undefined ) {
+ chainable = true;
+
+ if ( !jQuery.isFunction( value ) ) {
+ raw = true;
+ }
+
+ if ( bulk ) {
+ // Bulk operations run against the entire set
+ if ( raw ) {
+ fn.call( elems, value );
+ fn = null;
+
+ // ...except when executing function values
+ } else {
+ bulk = fn;
+ fn = function( elem, key, value ) {
+ return bulk.call( jQuery( elem ), value );
+ };
+ }
+ }
+
+ if ( fn ) {
+ for ( ; i < length; i++ ) {
+ fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
+ }
+ }
+ }
+
+ return chainable ?
+ elems :
+
+ // Gets
+ bulk ?
+ fn.call( elems ) :
+ length ? fn( elems[0], key ) : emptyGet;
+ },
+
+ now: function() {
+ return ( new Date() ).getTime();
+ }
+});
+
+jQuery.ready.promise = function( obj ) {
+ if ( !readyList ) {
+
+ readyList = jQuery.Deferred();
+
+ // Catch cases where $(document).ready() is called after the browser event has already occurred.
+ // we once tried to use readyState "interactive" here, but it caused issues like the one
+ // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+ if ( document.readyState === "complete" ) {
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ setTimeout( jQuery.ready );
+
+ // Standards-based browsers support DOMContentLoaded
+ } else if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", completed, false );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", completed, false );
+
+ // If IE event model is used
+ } else {
+ // Ensure firing before onload, maybe late but safe also for iframes
+ document.attachEvent( "onreadystatechange", completed );
+
+ // A fallback to window.onload, that will always work
+ window.attachEvent( "onload", completed );
+
+ // If IE and not a frame
+ // continually check to see if the document is ready
+ var top = false;
+
+ try {
+ top = window.frameElement == null && document.documentElement;
+ } catch(e) {}
+
+ if ( top && top.doScroll ) {
+ (function doScrollCheck() {
+ if ( !jQuery.isReady ) {
+
+ try {
+ // Use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ top.doScroll("left");
+ } catch(e) {
+ return setTimeout( doScrollCheck, 50 );
+ }
+
+ // detach all dom ready events
+ detach();
+
+ // and execute any waiting functions
+ jQuery.ready();
+ }
+ })();
+ }
+ }
+ }
+ return readyList.promise( obj );
+};
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+function isArraylike( obj ) {
+ var length = obj.length,
+ type = jQuery.type( obj );
+
+ if ( jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ if ( obj.nodeType === 1 && length ) {
+ return true;
+ }
+
+ return type === "array" || type !== "function" &&
+ ( length === 0 ||
+ typeof length === "number" && length > 0 && ( length - 1 ) in obj );
+}
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+// String to Object options format cache
+var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+ var object = optionsCache[ options ] = {};
+ jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {
+ object[ flag ] = true;
+ });
+ return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ * options: an optional list of space-separated options that will change how
+ * the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+ // Convert options from String-formatted to Object-formatted if needed
+ // (we check in cache first)
+ options = typeof options === "string" ?
+ ( optionsCache[ options ] || createOptions( options ) ) :
+ jQuery.extend( {}, options );
+
+ var // Flag to know if list is currently firing
+ firing,
+ // Last fire value (for non-forgettable lists)
+ memory,
+ // Flag to know if list was already fired
+ fired,
+ // End of the loop when firing
+ firingLength,
+ // Index of currently firing callback (modified by remove if needed)
+ firingIndex,
+ // First callback to fire (used internally by add and fireWith)
+ firingStart,
+ // Actual callback list
+ list = [],
+ // Stack of fire calls for repeatable lists
+ stack = !options.once && [],
+ // Fire callbacks
+ fire = function( data ) {
+ memory = options.memory && data;
+ fired = true;
+ firingIndex = firingStart || 0;
+ firingStart = 0;
+ firingLength = list.length;
+ firing = true;
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+ if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+ memory = false; // To prevent further calls using add
+ break;
+ }
+ }
+ firing = false;
+ if ( list ) {
+ if ( stack ) {
+ if ( stack.length ) {
+ fire( stack.shift() );
+ }
+ } else if ( memory ) {
+ list = [];
+ } else {
+ self.disable();
+ }
+ }
+ },
+ // Actual Callbacks object
+ self = {
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+ // First, we save the current length
+ var start = list.length;
+ (function add( args ) {
+ jQuery.each( args, function( _, arg ) {
+ var type = jQuery.type( arg );
+ if ( type === "function" ) {
+ if ( !options.unique || !self.has( arg ) ) {
+ list.push( arg );
+ }
+ } else if ( arg && arg.length && type !== "string" ) {
+ // Inspect recursively
+ add( arg );
+ }
+ });
+ })( arguments );
+ // Do we need to add the callbacks to the
+ // current firing batch?
+ if ( firing ) {
+ firingLength = list.length;
+ // With memory, if we're not firing then
+ // we should call right away
+ } else if ( memory ) {
+ firingStart = start;
+ fire( memory );
+ }
+ }
+ return this;
+ },
+ // Remove a callback from the list
+ remove: function() {
+ if ( list ) {
+ jQuery.each( arguments, function( _, arg ) {
+ var index;
+ while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+ list.splice( index, 1 );
+ // Handle firing indexes
+ if ( firing ) {
+ if ( index <= firingLength ) {
+ firingLength--;
+ }
+ if ( index <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ }
+ });
+ }
+ return this;
+ },
+ // Check if a given callback is in the list.
+ // If no argument is given, return whether or not list has callbacks attached.
+ has: function( fn ) {
+ return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
+ },
+ // Remove all callbacks from the list
+ empty: function() {
+ list = [];
+ return this;
+ },
+ // Have the list do nothing anymore
+ disable: function() {
+ list = stack = memory = undefined;
+ return this;
+ },
+ // Is it disabled?
+ disabled: function() {
+ return !list;
+ },
+ // Lock the list in its current state
+ lock: function() {
+ stack = undefined;
+ if ( !memory ) {
+ self.disable();
+ }
+ return this;
+ },
+ // Is it locked?
+ locked: function() {
+ return !stack;
+ },
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ args = args || [];
+ args = [ context, args.slice ? args.slice() : args ];
+ if ( list && ( !fired || stack ) ) {
+ if ( firing ) {
+ stack.push( args );
+ } else {
+ fire( args );
+ }
+ }
+ return this;
+ },
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!fired;
+ }
+ };
+
+ return self;
+};
+jQuery.extend({
+
+ Deferred: function( func ) {
+ var tuples = [
+ // action, add listener, listener list, final state
+ [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+ [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+ [ "notify", "progress", jQuery.Callbacks("memory") ]
+ ],
+ state = "pending",
+ promise = {
+ state: function() {
+ return state;
+ },
+ always: function() {
+ deferred.done( arguments ).fail( arguments );
+ return this;
+ },
+ then: function( /* fnDone, fnFail, fnProgress */ ) {
+ var fns = arguments;
+ return jQuery.Deferred(function( newDefer ) {
+ jQuery.each( tuples, function( i, tuple ) {
+ var action = tuple[ 0 ],
+ fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+ // deferred[ done | fail | progress ] for forwarding actions to newDefer
+ deferred[ tuple[1] ](function() {
+ var returned = fn && fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise()
+ .done( newDefer.resolve )
+ .fail( newDefer.reject )
+ .progress( newDefer.notify );
+ } else {
+ newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
+ }
+ });
+ });
+ fns = null;
+ }).promise();
+ },
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ return obj != null ? jQuery.extend( obj, promise ) : promise;
+ }
+ },
+ deferred = {};
+
+ // Keep pipe for back-compat
+ promise.pipe = promise.then;
+
+ // Add list-specific methods
+ jQuery.each( tuples, function( i, tuple ) {
+ var list = tuple[ 2 ],
+ stateString = tuple[ 3 ];
+
+ // promise[ done | fail | progress ] = list.add
+ promise[ tuple[1] ] = list.add;
+
+ // Handle state
+ if ( stateString ) {
+ list.add(function() {
+ // state = [ resolved | rejected ]
+ state = stateString;
+
+ // [ reject_list | resolve_list ].disable; progress_list.lock
+ }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+ }
+
+ // deferred[ resolve | reject | notify ]
+ deferred[ tuple[0] ] = function() {
+ deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
+ return this;
+ };
+ deferred[ tuple[0] + "With" ] = list.fireWith;
+ });
+
+ // Make the deferred a promise
+ promise.promise( deferred );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( subordinate /* , ..., subordinateN */ ) {
+ var i = 0,
+ resolveValues = core_slice.call( arguments ),
+ length = resolveValues.length,
+
+ // the count of uncompleted subordinates
+ remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+ // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+ deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+ // Update function for both resolve and progress values
+ updateFunc = function( i, contexts, values ) {
+ return function( value ) {
+ contexts[ i ] = this;
+ values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
+ if( values === progressValues ) {
+ deferred.notifyWith( contexts, values );
+ } else if ( !( --remaining ) ) {
+ deferred.resolveWith( contexts, values );
+ }
+ };
+ },
+
+ progressValues, progressContexts, resolveContexts;
+
+ // add listeners to Deferred subordinates; treat others as resolved
+ if ( length > 1 ) {
+ progressValues = new Array( length );
+ progressContexts = new Array( length );
+ resolveContexts = new Array( length );
+ for ( ; i < length; i++ ) {
+ if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+ resolveValues[ i ].promise()
+ .done( updateFunc( i, resolveContexts, resolveValues ) )
+ .fail( deferred.reject )
+ .progress( updateFunc( i, progressContexts, progressValues ) );
+ } else {
+ --remaining;
+ }
+ }
+ }
+
+ // if we're not waiting on anything, resolve the master
+ if ( !remaining ) {
+ deferred.resolveWith( resolveContexts, resolveValues );
+ }
+
+ return deferred.promise();
+ }
+});
+jQuery.support = (function() {
+
+ var support, all, a,
+ input, select, fragment,
+ opt, eventName, isSupported, i,
+ div = document.createElement("div");
+
+ // Setup
+ div.setAttribute( "className", "t" );
+ div.innerHTML = " a ";
+
+ // Support tests won't run in some limited or non-browser environments
+ all = div.getElementsByTagName("*");
+ a = div.getElementsByTagName("a")[ 0 ];
+ if ( !all || !a || !all.length ) {
+ return {};
+ }
+
+ // First batch of tests
+ select = document.createElement("select");
+ opt = select.appendChild( document.createElement("option") );
+ input = div.getElementsByTagName("input")[ 0 ];
+
+ a.style.cssText = "top:1px;float:left;opacity:.5";
+ support = {
+ // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+ getSetAttribute: div.className !== "t",
+
+ // IE strips leading whitespace when .innerHTML is used
+ leadingWhitespace: div.firstChild.nodeType === 3,
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ tbody: !div.getElementsByTagName("tbody").length,
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ htmlSerialize: !!div.getElementsByTagName("link").length,
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText instead)
+ style: /top/.test( a.getAttribute("style") ),
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ hrefNormalized: a.getAttribute("href") === "/a",
+
+ // Make sure that element opacity exists
+ // (IE uses filter instead)
+ // Use a regex to work around a WebKit issue. See #5145
+ opacity: /^0.5/.test( a.style.opacity ),
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ cssFloat: !!a.style.cssFloat,
+
+ // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
+ checkOn: !!input.value,
+
+ // Make sure that a selected-by-default option has a working selected property.
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+ optSelected: opt.selected,
+
+ // Tests for enctype support on a form (#6743)
+ enctype: !!document.createElement("form").enctype,
+
+ // Makes sure cloning an html5 element does not cause problems
+ // Where outerHTML is undefined, this still works
+ html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>",
+
+ // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
+ boxModel: document.compatMode === "CSS1Compat",
+
+ // Will be defined later
+ deleteExpando: true,
+ noCloneEvent: true,
+ inlineBlockNeedsLayout: false,
+ shrinkWrapBlocks: false,
+ reliableMarginRight: true,
+ boxSizingReliable: true,
+ pixelPosition: false
+ };
+
+ // Make sure checked status is properly cloned
+ input.checked = true;
+ support.noCloneChecked = input.cloneNode( true ).checked;
+
+ // Make sure that the options inside disabled selects aren't marked as disabled
+ // (WebKit marks them as disabled)
+ select.disabled = true;
+ support.optDisabled = !opt.disabled;
+
+ // Support: IE<9
+ try {
+ delete div.test;
+ } catch( e ) {
+ support.deleteExpando = false;
+ }
+
+ // Check if we can trust getAttribute("value")
+ input = document.createElement("input");
+ input.setAttribute( "value", "" );
+ support.input = input.getAttribute( "value" ) === "";
+
+ // Check if an input maintains its value after becoming a radio
+ input.value = "t";
+ input.setAttribute( "type", "radio" );
+ support.radioValue = input.value === "t";
+
+ // #11217 - WebKit loses check when the name is after the checked attribute
+ input.setAttribute( "checked", "t" );
+ input.setAttribute( "name", "t" );
+
+ fragment = document.createDocumentFragment();
+ fragment.appendChild( input );
+
+ // Check if a disconnected checkbox will retain its checked
+ // value of true after appended to the DOM (IE6/7)
+ support.appendChecked = input.checked;
+
+ // WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Support: IE<9
+ // Opera does not clone events (and typeof div.attachEvent === undefined).
+ // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
+ if ( div.attachEvent ) {
+ div.attachEvent( "onclick", function() {
+ support.noCloneEvent = false;
+ });
+
+ div.cloneNode( true ).click();
+ }
+
+ // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)
+ // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php
+ for ( i in { submit: true, change: true, focusin: true }) {
+ div.setAttribute( eventName = "on" + i, "t" );
+
+ support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false;
+ }
+
+ div.style.backgroundClip = "content-box";
+ div.cloneNode( true ).style.backgroundClip = "";
+ support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+ // Run tests that need a body at doc ready
+ jQuery(function() {
+ var container, marginDiv, tds,
+ divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",
+ body = document.getElementsByTagName("body")[0];
+
+ if ( !body ) {
+ // Return for frameset docs that don't have a body
+ return;
+ }
+
+ container = document.createElement("div");
+ container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
+
+ body.appendChild( container ).appendChild( div );
+
+ // Support: IE8
+ // Check if table cells still have offsetWidth/Height when they are set
+ // to display:none and there are still other visible table cells in a
+ // table row; if so, offsetWidth/Height are not reliable for use when
+ // determining if an element has been hidden directly using
+ // display:none (it is still safe to use offsets if a parent element is
+ // hidden; don safety goggles and see bug #4512 for more information).
+ div.innerHTML = "";
+ tds = div.getElementsByTagName("td");
+ tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
+ isSupported = ( tds[ 0 ].offsetHeight === 0 );
+
+ tds[ 0 ].style.display = "";
+ tds[ 1 ].style.display = "none";
+
+ // Support: IE8
+ // Check if empty table cells still have offsetWidth/Height
+ support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
+
+ // Check box-sizing and margin behavior
+ div.innerHTML = "";
+ div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
+ support.boxSizing = ( div.offsetWidth === 4 );
+ support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
+
+ // Use window.getComputedStyle because jsdom on node.js will break without it.
+ if ( window.getComputedStyle ) {
+ support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
+ support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
+
+ // Check if div with explicit width and no margin-right incorrectly
+ // gets computed margin-right based on width of container. (#3333)
+ // Fails in WebKit before Feb 2011 nightlies
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ marginDiv = div.appendChild( document.createElement("div") );
+ marginDiv.style.cssText = div.style.cssText = divReset;
+ marginDiv.style.marginRight = marginDiv.style.width = "0";
+ div.style.width = "1px";
+
+ support.reliableMarginRight =
+ !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
+ }
+
+ if ( typeof div.style.zoom !== core_strundefined ) {
+ // Support: IE<8
+ // Check if natively block-level elements act like inline-block
+ // elements when setting their display to 'inline' and giving
+ // them layout
+ div.innerHTML = "";
+ div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
+ support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
+
+ // Support: IE6
+ // Check if elements with layout shrink-wrap their children
+ div.style.display = "block";
+ div.innerHTML = "
";
+ div.firstChild.style.width = "5px";
+ support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
+
+ if ( support.inlineBlockNeedsLayout ) {
+ // Prevent IE 6 from affecting layout for positioned elements #11048
+ // Prevent IE from shrinking the body in IE 7 mode #12869
+ // Support: IE<8
+ body.style.zoom = 1;
+ }
+ }
+
+ body.removeChild( container );
+
+ // Null elements to avoid leaks in IE
+ container = div = tds = marginDiv = null;
+ });
+
+ // Null elements to avoid leaks in IE
+ all = select = fragment = opt = a = input = null;
+
+ return support;
+})();
+
+var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
+ rmultiDash = /([A-Z])/g;
+
+function internalData( elem, name, data, pvt /* Internal Use Only */ ){
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var thisCache, ret,
+ internalKey = jQuery.expando,
+ getByName = typeof name === "string",
+
+ // We have to handle DOM nodes and JS objects differently because IE6-7
+ // can't GC object references properly across the DOM-JS boundary
+ isNode = elem.nodeType,
+
+ // Only DOM nodes need the global jQuery cache; JS object data is
+ // attached directly to the object so GC can occur automatically
+ cache = isNode ? jQuery.cache : elem,
+
+ // Only defining an ID for JS objects if its cache already exists allows
+ // the code to shortcut on the same path as a DOM node with no cache
+ id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
+
+ // Avoid doing any more work than we need to when trying to get data on an
+ // object that has no data at all
+ if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
+ return;
+ }
+
+ if ( !id ) {
+ // Only DOM nodes need a new unique ID for each element since their data
+ // ends up in the global cache
+ if ( isNode ) {
+ elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;
+ } else {
+ id = internalKey;
+ }
+ }
+
+ if ( !cache[ id ] ) {
+ cache[ id ] = {};
+
+ // Avoids exposing jQuery metadata on plain JS objects when the object
+ // is serialized using JSON.stringify
+ if ( !isNode ) {
+ cache[ id ].toJSON = jQuery.noop;
+ }
+ }
+
+ // An object can be passed to jQuery.data instead of a key/value pair; this gets
+ // shallow copied over onto the existing cache
+ if ( typeof name === "object" || typeof name === "function" ) {
+ if ( pvt ) {
+ cache[ id ] = jQuery.extend( cache[ id ], name );
+ } else {
+ cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+ }
+ }
+
+ thisCache = cache[ id ];
+
+ // jQuery data() is stored in a separate object inside the object's internal data
+ // cache in order to avoid key collisions between internal data and user-defined
+ // data.
+ if ( !pvt ) {
+ if ( !thisCache.data ) {
+ thisCache.data = {};
+ }
+
+ thisCache = thisCache.data;
+ }
+
+ if ( data !== undefined ) {
+ thisCache[ jQuery.camelCase( name ) ] = data;
+ }
+
+ // Check for both converted-to-camel and non-converted data property names
+ // If a data property was specified
+ if ( getByName ) {
+
+ // First Try to find as-is property data
+ ret = thisCache[ name ];
+
+ // Test for null|undefined property data
+ if ( ret == null ) {
+
+ // Try to find the camelCased property
+ ret = thisCache[ jQuery.camelCase( name ) ];
+ }
+ } else {
+ ret = thisCache;
+ }
+
+ return ret;
+}
+
+function internalRemoveData( elem, name, pvt ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var i, l, thisCache,
+ isNode = elem.nodeType,
+
+ // See jQuery.data for more information
+ cache = isNode ? jQuery.cache : elem,
+ id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+
+ // If there is already no cache entry for this object, there is no
+ // purpose in continuing
+ if ( !cache[ id ] ) {
+ return;
+ }
+
+ if ( name ) {
+
+ thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+ if ( thisCache ) {
+
+ // Support array or space separated string names for data keys
+ if ( !jQuery.isArray( name ) ) {
+
+ // try the string as a key before any manipulation
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+
+ // split the camel cased version by spaces unless a key with the spaces exists
+ name = jQuery.camelCase( name );
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+ name = name.split(" ");
+ }
+ }
+ } else {
+ // If "name" is an array of keys...
+ // When data is initially created, via ("key", "val") signature,
+ // keys will be converted to camelCase.
+ // Since there is no way to tell _how_ a key was added, remove
+ // both plain key and camelCase key. #12786
+ // This will only penalize the array argument path.
+ name = name.concat( jQuery.map( name, jQuery.camelCase ) );
+ }
+
+ for ( i = 0, l = name.length; i < l; i++ ) {
+ delete thisCache[ name[i] ];
+ }
+
+ // If there is no data left in the cache, we want to continue
+ // and let the cache object itself get destroyed
+ if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
+ return;
+ }
+ }
+ }
+
+ // See jQuery.data for more information
+ if ( !pvt ) {
+ delete cache[ id ].data;
+
+ // Don't destroy the parent cache unless the internal data object
+ // had been the only thing left in it
+ if ( !isEmptyDataObject( cache[ id ] ) ) {
+ return;
+ }
+ }
+
+ // Destroy the cache
+ if ( isNode ) {
+ jQuery.cleanData( [ elem ], true );
+
+ // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
+ } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
+ delete cache[ id ];
+
+ // When all else fails, null
+ } else {
+ cache[ id ] = null;
+ }
+}
+
+jQuery.extend({
+ cache: {},
+
+ // Unique for each copy of jQuery on the page
+ // Non-digits removed to match rinlinejQuery
+ expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),
+
+ // The following elements throw uncatchable exceptions if you
+ // attempt to add expando properties to them.
+ noData: {
+ "embed": true,
+ // Ban all objects except for Flash (which handle expandos)
+ "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+ "applet": true
+ },
+
+ hasData: function( elem ) {
+ elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+ return !!elem && !isEmptyDataObject( elem );
+ },
+
+ data: function( elem, name, data ) {
+ return internalData( elem, name, data );
+ },
+
+ removeData: function( elem, name ) {
+ return internalRemoveData( elem, name );
+ },
+
+ // For internal use only.
+ _data: function( elem, name, data ) {
+ return internalData( elem, name, data, true );
+ },
+
+ _removeData: function( elem, name ) {
+ return internalRemoveData( elem, name, true );
+ },
+
+ // A method for determining if a DOM node can handle the data expando
+ acceptData: function( elem ) {
+ // Do not set data on non-element because it will not be cleared (#8335).
+ if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {
+ return false;
+ }
+
+ var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+ // nodes accept data unless otherwise specified; rejection can be conditional
+ return !noData || noData !== true && elem.getAttribute("classid") === noData;
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ) {
+ var attrs, name,
+ elem = this[0],
+ i = 0,
+ data = null;
+
+ // Gets all values
+ if ( key === undefined ) {
+ if ( this.length ) {
+ data = jQuery.data( elem );
+
+ if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+ attrs = elem.attributes;
+ for ( ; i < attrs.length; i++ ) {
+ name = attrs[i].name;
+
+ if ( !name.indexOf( "data-" ) ) {
+ name = jQuery.camelCase( name.slice(5) );
+
+ dataAttr( elem, name, data[ name ] );
+ }
+ }
+ jQuery._data( elem, "parsedAttrs", true );
+ }
+ }
+
+ return data;
+ }
+
+ // Sets multiple values
+ if ( typeof key === "object" ) {
+ return this.each(function() {
+ jQuery.data( this, key );
+ });
+ }
+
+ return jQuery.access( this, function( value ) {
+
+ if ( value === undefined ) {
+ // Try to fetch any internally stored data first
+ return elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;
+ }
+
+ this.each(function() {
+ jQuery.data( this, key, value );
+ });
+ }, null, value, arguments.length > 1, null, true );
+ },
+
+ removeData: function( key ) {
+ return this.each(function() {
+ jQuery.removeData( this, key );
+ });
+ }
+});
+
+function dataAttr( elem, key, data ) {
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+
+ var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
+ // Only convert to a number if it doesn't change the string
+ +data + "" === data ? +data :
+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
+ data;
+ } catch( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ jQuery.data( elem, key, data );
+
+ } else {
+ data = undefined;
+ }
+ }
+
+ return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+ var name;
+ for ( name in obj ) {
+
+ // if the public data object is empty, the private is still empty
+ if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+ continue;
+ }
+ if ( name !== "toJSON" ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+jQuery.extend({
+ queue: function( elem, type, data ) {
+ var queue;
+
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ queue = jQuery._data( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !queue || jQuery.isArray(data) ) {
+ queue = jQuery._data( elem, type, jQuery.makeArray(data) );
+ } else {
+ queue.push( data );
+ }
+ }
+ return queue || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ startLength = queue.length,
+ fn = queue.shift(),
+ hooks = jQuery._queueHooks( elem, type ),
+ next = function() {
+ jQuery.dequeue( elem, type );
+ };
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ startLength--;
+ }
+
+ hooks.cur = fn;
+ if ( fn ) {
+
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ // clear up the last queue stop function
+ delete hooks.stop;
+ fn.call( elem, next, hooks );
+ }
+
+ if ( !startLength && hooks ) {
+ hooks.empty.fire();
+ }
+ },
+
+ // not intended for public consumption - generates a queueHooks object, or returns the current one
+ _queueHooks: function( elem, type ) {
+ var key = type + "queueHooks";
+ return jQuery._data( elem, key ) || jQuery._data( elem, key, {
+ empty: jQuery.Callbacks("once memory").add(function() {
+ jQuery._removeData( elem, type + "queue" );
+ jQuery._removeData( elem, key );
+ })
+ });
+ }
+});
+
+jQuery.fn.extend({
+ queue: function( type, data ) {
+ var setter = 2;
+
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ setter--;
+ }
+
+ if ( arguments.length < setter ) {
+ return jQuery.queue( this[0], type );
+ }
+
+ return data === undefined ?
+ this :
+ this.each(function() {
+ var queue = jQuery.queue( this, type, data );
+
+ // ensure a hooks for this queue
+ jQuery._queueHooks( this, type );
+
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ dequeue: function( type ) {
+ return this.each(function() {
+ jQuery.dequeue( this, type );
+ });
+ },
+ // Based off of the plugin by Clint Helfers, with permission.
+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
+ delay: function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function( next, hooks ) {
+ var timeout = setTimeout( next, time );
+ hooks.stop = function() {
+ clearTimeout( timeout );
+ };
+ });
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, obj ) {
+ var tmp,
+ count = 1,
+ defer = jQuery.Deferred(),
+ elements = this,
+ i = this.length,
+ resolve = function() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ };
+
+ if ( typeof type !== "string" ) {
+ obj = type;
+ type = undefined;
+ }
+ type = type || "fx";
+
+ while( i-- ) {
+ tmp = jQuery._data( elements[ i ], type + "queueHooks" );
+ if ( tmp && tmp.empty ) {
+ count++;
+ tmp.empty.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise( obj );
+ }
+});
+var nodeHook, boolHook,
+ rclass = /[\t\r\n]/g,
+ rreturn = /\r/g,
+ rfocusable = /^(?:input|select|textarea|button|object)$/i,
+ rclickable = /^(?:a|area)$/i,
+ rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,
+ ruseDefault = /^(?:checked|selected)$/i,
+ getSetAttribute = jQuery.support.getSetAttribute,
+ getSetInput = jQuery.support.input;
+
+jQuery.fn.extend({
+ attr: function( name, value ) {
+ return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
+ },
+
+ removeAttr: function( name ) {
+ return this.each(function() {
+ jQuery.removeAttr( this, name );
+ });
+ },
+
+ prop: function( name, value ) {
+ return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
+ },
+
+ removeProp: function( name ) {
+ name = jQuery.propFix[ name ] || name;
+ return this.each(function() {
+ // try/catch handles cases where IE balks (such as removing a property on window)
+ try {
+ this[ name ] = undefined;
+ delete this[ name ];
+ } catch( e ) {}
+ });
+ },
+
+ addClass: function( value ) {
+ var classes, elem, cur, clazz, j,
+ i = 0,
+ len = this.length,
+ proceed = typeof value === "string" && value;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).addClass( value.call( this, j, this.className ) );
+ });
+ }
+
+ if ( proceed ) {
+ // The disjunction here is for better compressibility (see removeClass)
+ classes = ( value || "" ).match( core_rnotwhite ) || [];
+
+ for ( ; i < len; i++ ) {
+ elem = this[ i ];
+ cur = elem.nodeType === 1 && ( elem.className ?
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
+ " "
+ );
+
+ if ( cur ) {
+ j = 0;
+ while ( (clazz = classes[j++]) ) {
+ if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+ cur += clazz + " ";
+ }
+ }
+ elem.className = jQuery.trim( cur );
+
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var classes, elem, cur, clazz, j,
+ i = 0,
+ len = this.length,
+ proceed = arguments.length === 0 || typeof value === "string" && value;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).removeClass( value.call( this, j, this.className ) );
+ });
+ }
+ if ( proceed ) {
+ classes = ( value || "" ).match( core_rnotwhite ) || [];
+
+ for ( ; i < len; i++ ) {
+ elem = this[ i ];
+ // This expression is here for better compressibility (see addClass)
+ cur = elem.nodeType === 1 && ( elem.className ?
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
+ ""
+ );
+
+ if ( cur ) {
+ j = 0;
+ while ( (clazz = classes[j++]) ) {
+ // Remove *all* instances
+ while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
+ cur = cur.replace( " " + clazz + " ", " " );
+ }
+ }
+ elem.className = value ? jQuery.trim( cur ) : "";
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value,
+ isBool = typeof stateVal === "boolean";
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( i ) {
+ jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+ });
+ }
+
+ return this.each(function() {
+ if ( type === "string" ) {
+ // toggle individual class names
+ var className,
+ i = 0,
+ self = jQuery( this ),
+ state = stateVal,
+ classNames = value.match( core_rnotwhite ) || [];
+
+ while ( (className = classNames[ i++ ]) ) {
+ // check each className given, space separated list
+ state = isBool ? state : !self.hasClass( className );
+ self[ state ? "addClass" : "removeClass" ]( className );
+ }
+
+ // Toggle whole class name
+ } else if ( type === core_strundefined || type === "boolean" ) {
+ if ( this.className ) {
+ // store className if set
+ jQuery._data( this, "__className__", this.className );
+ }
+
+ // If the element has a class name or if we're passed "false",
+ // then remove the whole classname (if there was one, the above saved it).
+ // Otherwise bring back whatever was previously saved (if anything),
+ // falling back to the empty string if nothing was stored.
+ this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+ }
+ });
+ },
+
+ hasClass: function( selector ) {
+ var className = " " + selector + " ",
+ i = 0,
+ l = this.length;
+ for ( ; i < l; i++ ) {
+ if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ val: function( value ) {
+ var ret, hooks, isFunction,
+ elem = this[0];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ return typeof ret === "string" ?
+ // handle most common string cases
+ ret.replace(rreturn, "") :
+ // handle cases where value is null/undef or number
+ ret == null ? "" : ret;
+ }
+
+ return;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each(function( i ) {
+ var val,
+ self = jQuery(this);
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, self.val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+ } else if ( typeof val === "number" ) {
+ val += "";
+ } else if ( jQuery.isArray( val ) ) {
+ val = jQuery.map(val, function ( value ) {
+ return value == null ? "" : value + "";
+ });
+ }
+
+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ valHooks: {
+ option: {
+ get: function( elem ) {
+ // attributes.value is undefined in Blackberry 4.7 but
+ // uses .value. See #6932
+ var val = elem.attributes.value;
+ return !val || val.specified ? elem.value : elem.text;
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, option,
+ options = elem.options,
+ index = elem.selectedIndex,
+ one = elem.type === "select-one" || index < 0,
+ values = one ? null : [],
+ max = one ? index + 1 : options.length,
+ i = index < 0 ?
+ max :
+ one ? index : 0;
+
+ // Loop through all the selected options
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // oldIE doesn't update selected after form reset (#2551)
+ if ( ( option.selected || i === index ) &&
+ // Don't return options that are disabled or in a disabled optgroup
+ ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
+ ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var values = jQuery.makeArray( value );
+
+ jQuery(elem).find("option").each(function() {
+ this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+ });
+
+ if ( !values.length ) {
+ elem.selectedIndex = -1;
+ }
+ return values;
+ }
+ }
+ },
+
+ attr: function( elem, name, value ) {
+ var hooks, notxml, ret,
+ nType = elem.nodeType;
+
+ // don't get/set attributes on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( typeof elem.getAttribute === core_strundefined ) {
+ return jQuery.prop( elem, name, value );
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ // All attributes are lowercase
+ // Grab necessary hook if one is defined
+ if ( notxml ) {
+ name = name.toLowerCase();
+ hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
+ }
+
+ if ( value !== undefined ) {
+
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+
+ } else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ elem.setAttribute( name, value + "" );
+ return value;
+ }
+
+ } else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+
+ // In IE9+, Flash objects don't have .getAttribute (#12945)
+ // Support: IE9+
+ if ( typeof elem.getAttribute !== core_strundefined ) {
+ ret = elem.getAttribute( name );
+ }
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret == null ?
+ undefined :
+ ret;
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var name, propName,
+ i = 0,
+ attrNames = value && value.match( core_rnotwhite );
+
+ if ( attrNames && elem.nodeType === 1 ) {
+ while ( (name = attrNames[i++]) ) {
+ propName = jQuery.propFix[ name ] || name;
+
+ // Boolean attributes get special treatment (#10870)
+ if ( rboolean.test( name ) ) {
+ // Set corresponding property to false for boolean attributes
+ // Also clear defaultChecked/defaultSelected (if appropriate) for IE<8
+ if ( !getSetAttribute && ruseDefault.test( name ) ) {
+ elem[ jQuery.camelCase( "default-" + name ) ] =
+ elem[ propName ] = false;
+ } else {
+ elem[ propName ] = false;
+ }
+
+ // See #9699 for explanation of this approach (setting first, then removal)
+ } else {
+ jQuery.attr( elem, name, "" );
+ }
+
+ elem.removeAttribute( getSetAttribute ? name : propName );
+ }
+ }
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+ // Setting the type on a radio button after the value resets the value in IE6-9
+ // Reset value to default in case type is set after value during creation
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ }
+ },
+
+ propFix: {
+ tabindex: "tabIndex",
+ readonly: "readOnly",
+ "for": "htmlFor",
+ "class": "className",
+ maxlength: "maxLength",
+ cellspacing: "cellSpacing",
+ cellpadding: "cellPadding",
+ rowspan: "rowSpan",
+ colspan: "colSpan",
+ usemap: "useMap",
+ frameborder: "frameBorder",
+ contenteditable: "contentEditable"
+ },
+
+ prop: function( elem, name, value ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set properties on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ if ( notxml ) {
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ return ( elem[ name ] = value );
+ }
+
+ } else {
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+ return elem[ name ];
+ }
+ }
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ var attributeNode = elem.getAttributeNode("tabindex");
+
+ return attributeNode && attributeNode.specified ?
+ parseInt( attributeNode.value, 10 ) :
+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ undefined;
+ }
+ }
+ }
+});
+
+// Hook for boolean attributes
+boolHook = {
+ get: function( elem, name ) {
+ var
+ // Use .prop to determine if this attribute is understood as boolean
+ prop = jQuery.prop( elem, name ),
+
+ // Fetch it accordingly
+ attr = typeof prop === "boolean" && elem.getAttribute( name ),
+ detail = typeof prop === "boolean" ?
+
+ getSetInput && getSetAttribute ?
+ attr != null :
+ // oldIE fabricates an empty string for missing boolean attributes
+ // and conflates checked/selected into attroperties
+ ruseDefault.test( name ) ?
+ elem[ jQuery.camelCase( "default-" + name ) ] :
+ !!attr :
+
+ // fetch an attribute node for properties not recognized as boolean
+ elem.getAttributeNode( name );
+
+ return detail && detail.value !== false ?
+ name.toLowerCase() :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ if ( value === false ) {
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
+ // IE<8 needs the *property* name
+ elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
+
+ // Use defaultChecked and defaultSelected for oldIE
+ } else {
+ elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
+ }
+
+ return name;
+ }
+};
+
+// fix oldIE value attroperty
+if ( !getSetInput || !getSetAttribute ) {
+ jQuery.attrHooks.value = {
+ get: function( elem, name ) {
+ var ret = elem.getAttributeNode( name );
+ return jQuery.nodeName( elem, "input" ) ?
+
+ // Ignore the value *property* by using defaultValue
+ elem.defaultValue :
+
+ ret && ret.specified ? ret.value : undefined;
+ },
+ set: function( elem, value, name ) {
+ if ( jQuery.nodeName( elem, "input" ) ) {
+ // Does not return so that setAttribute is also used
+ elem.defaultValue = value;
+ } else {
+ // Use nodeHook if defined (#1954); otherwise setAttribute is fine
+ return nodeHook && nodeHook.set( elem, value, name );
+ }
+ }
+ };
+}
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+ // Use this for any attribute in IE6/7
+ // This fixes almost every IE6/7 issue
+ nodeHook = jQuery.valHooks.button = {
+ get: function( elem, name ) {
+ var ret = elem.getAttributeNode( name );
+ return ret && ( name === "id" || name === "name" || name === "coords" ? ret.value !== "" : ret.specified ) ?
+ ret.value :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ // Set the existing or create a new attribute node
+ var ret = elem.getAttributeNode( name );
+ if ( !ret ) {
+ elem.setAttributeNode(
+ (ret = elem.ownerDocument.createAttribute( name ))
+ );
+ }
+
+ ret.value = value += "";
+
+ // Break association with cloned elements by also using setAttribute (#9646)
+ return name === "value" || value === elem.getAttribute( name ) ?
+ value :
+ undefined;
+ }
+ };
+
+ // Set contenteditable to false on removals(#10429)
+ // Setting to empty string throws an error as an invalid value
+ jQuery.attrHooks.contenteditable = {
+ get: nodeHook.get,
+ set: function( elem, value, name ) {
+ nodeHook.set( elem, value === "" ? false : value, name );
+ }
+ };
+
+ // Set width and height to auto instead of 0 on empty string( Bug #8150 )
+ // This is for removals
+ jQuery.each([ "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ set: function( elem, value ) {
+ if ( value === "" ) {
+ elem.setAttribute( name, "auto" );
+ return value;
+ }
+ }
+ });
+ });
+}
+
+
+// Some attributes require a special call on IE
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !jQuery.support.hrefNormalized ) {
+ jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ get: function( elem ) {
+ var ret = elem.getAttribute( name, 2 );
+ return ret == null ? undefined : ret;
+ }
+ });
+ });
+
+ // href/src property should get the full normalized URL (#10299/#12915)
+ jQuery.each([ "href", "src" ], function( i, name ) {
+ jQuery.propHooks[ name ] = {
+ get: function( elem ) {
+ return elem.getAttribute( name, 4 );
+ }
+ };
+ });
+}
+
+if ( !jQuery.support.style ) {
+ jQuery.attrHooks.style = {
+ get: function( elem ) {
+ // Return undefined in the case of empty string
+ // Note: IE uppercases css property names, but if we were to .toLowerCase()
+ // .cssText, that would destroy case senstitivity in URL's, like in "background"
+ return elem.style.cssText || undefined;
+ },
+ set: function( elem, value ) {
+ return ( elem.style.cssText = value + "" );
+ }
+ };
+}
+
+// Safari mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !jQuery.support.optSelected ) {
+ jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
+ get: function( elem ) {
+ var parent = elem.parentNode;
+
+ if ( parent ) {
+ parent.selectedIndex;
+
+ // Make sure that it also works with optgroups, see #5701
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ return null;
+ }
+ });
+}
+
+// IE6/7 call enctype encoding
+if ( !jQuery.support.enctype ) {
+ jQuery.propFix.enctype = "encoding";
+}
+
+// Radios and checkboxes getter/setter
+if ( !jQuery.support.checkOn ) {
+ jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ get: function( elem ) {
+ // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+ return elem.getAttribute("value") === null ? "on" : elem.value;
+ }
+ };
+ });
+}
+jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
+ set: function( elem, value ) {
+ if ( jQuery.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+ }
+ }
+ });
+});
+var rformElems = /^(?:input|select|textarea)$/i,
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|contextmenu)|click/,
+ rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+ rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
+
+function returnTrue() {
+ return true;
+}
+
+function returnFalse() {
+ return false;
+}
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+ global: {},
+
+ add: function( elem, types, handler, data, selector ) {
+ var tmp, events, t, handleObjIn,
+ special, eventHandle, handleObj,
+ handlers, type, namespaces, origType,
+ elemData = jQuery._data( elem );
+
+ // Don't attach events to noData or text/comment nodes (but allow plain objects)
+ if ( !elemData ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ selector = handleObjIn.selector;
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ if ( !(events = elemData.events) ) {
+ events = elemData.events = {};
+ }
+ if ( !(eventHandle = elemData.handle) ) {
+ eventHandle = elemData.handle = function( e ) {
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
+ jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+ undefined;
+ };
+ // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+ eventHandle.elem = elem;
+ }
+
+ // Handle multiple events separated by a space
+ // jQuery(...).bind("mouseover mouseout", fn);
+ types = ( types || "" ).match( core_rnotwhite ) || [""];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tmp[1];
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend({
+ type: type,
+ origType: origType,
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+ namespace: namespaces.join(".")
+ }, handleObjIn );
+
+ // Init the event handler queue if we're the first
+ if ( !(handlers = events[ type ]) ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener/attachEvent if the special events handler returns false
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+ // Bind the global event handler to the element
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector, mappedTypes ) {
+ var j, handleObj, tmp,
+ origCount, t, events,
+ special, handlers, type,
+ namespaces, origType,
+ elemData = jQuery.hasData( elem ) && jQuery._data( elem );
+
+ if ( !elemData || !(events = elemData.events) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = ( types || "" ).match( core_rnotwhite ) || [""];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tmp[1];
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ }
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+ handlers = events[ type ] || [];
+ tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
+
+ // Remove matching events
+ origCount = j = handlers.length;
+ while ( j-- ) {
+ handleObj = handlers[ j ];
+
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
+ ( !handler || handler.guid === handleObj.guid ) &&
+ ( !tmp || tmp.test( handleObj.namespace ) ) &&
+ ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+ handlers.splice( j, 1 );
+
+ if ( handleObj.selector ) {
+ handlers.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( origCount && !handlers.length ) {
+ if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ delete elemData.handle;
+
+ // removeData also checks for emptiness and clears the expando if empty
+ // so use it instead of delete
+ jQuery._removeData( elem, "events" );
+ }
+ },
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+ var handle, ontype, cur,
+ bubbleType, special, tmp, i,
+ eventPath = [ elem || document ],
+ type = core_hasOwn.call( event, "type" ) ? event.type : event,
+ namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
+
+ cur = tmp = elem = elem || document;
+
+ // Don't do events on text and comment nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf(".") >= 0 ) {
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split(".");
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+ ontype = type.indexOf(":") < 0 && "on" + type;
+
+ // Caller can pass in a jQuery.Event object, Object, or just an event type string
+ event = event[ jQuery.expando ] ?
+ event :
+ new jQuery.Event( type, typeof event === "object" && event );
+
+ event.isTrigger = true;
+ event.namespace = namespaces.join(".");
+ event.namespace_re = event.namespace ?
+ new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
+ null;
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data == null ?
+ [ event ] :
+ jQuery.makeArray( data, [ event ] );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ if ( !rfocusMorph.test( bubbleType + type ) ) {
+ cur = cur.parentNode;
+ }
+ for ( ; cur; cur = cur.parentNode ) {
+ eventPath.push( cur );
+ tmp = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( tmp === (elem.ownerDocument || document) ) {
+ eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+ }
+ }
+
+ // Fire handlers on the event path
+ i = 0;
+ while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
+
+ event.type = i > 1 ?
+ bubbleType :
+ special.bindType || type;
+
+ // jQuery handler
+ handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+
+ // Native handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
+ event.preventDefault();
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
+ !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name name as the event.
+ // Can't use an .isFunction() check here because IE6/7 fails that test.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ tmp = elem[ ontype ];
+
+ if ( tmp ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ try {
+ elem[ type ]();
+ } catch ( e ) {
+ // IE<9 dies on focus/blur to hidden element (#1486,#12518)
+ // only reproducible on winXP IE8 native, not IE9 in IE8 mode
+ }
+ jQuery.event.triggered = undefined;
+
+ if ( tmp ) {
+ elem[ ontype ] = tmp;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ dispatch: function( event ) {
+
+ // Make a writable jQuery.Event from the native event object
+ event = jQuery.event.fix( event );
+
+ var i, ret, handleObj, matched, j,
+ handlerQueue = [],
+ args = core_slice.call( arguments ),
+ handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
+ special = jQuery.event.special[ event.type ] || {};
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[0] = event;
+ event.delegateTarget = this;
+
+ // Call the preDispatch hook for the mapped type, and let it bail if desired
+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+ return;
+ }
+
+ // Determine handlers
+ handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+ // Run delegates first; they may want to stop propagation beneath us
+ i = 0;
+ while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
+ event.currentTarget = matched.elem;
+
+ j = 0;
+ while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
+
+ // Triggered event must either 1) have no namespace, or
+ // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+ if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
+
+ event.handleObj = handleObj;
+ event.data = handleObj.data;
+
+ var obj = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler );
+ if(obj.apply){
+ ret = obj.apply( matched.elem, args );
+ }
+
+ if ( ret !== undefined ) {
+ if ( (event.result = ret) === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ // Call the postDispatch hook for the mapped type
+ if ( special.postDispatch ) {
+ special.postDispatch.call( this, event );
+ }
+
+ return event.result;
+ },
+
+ handlers: function( event, handlers ) {
+ var sel, handleObj, matches, i,
+ handlerQueue = [],
+ delegateCount = handlers.delegateCount,
+ cur = event.target;
+
+ // Find delegate handlers
+ // Black-hole SVG instance trees (#13180)
+ // Avoid non-left-click bubbling in Firefox (#3861)
+ if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
+
+ for ( ; cur != this; cur = cur.parentNode || this ) {
+
+ // Don't check non-elements (#13208)
+ // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+ if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
+ matches = [];
+ for ( i = 0; i < delegateCount; i++ ) {
+ handleObj = handlers[ i ];
+
+ // Don't conflict with Object.prototype properties (#13203)
+ sel = handleObj.selector + " ";
+
+ if ( matches[ sel ] === undefined ) {
+ matches[ sel ] = handleObj.needsContext ?
+ jQuery( sel, this ).index( cur ) >= 0 :
+ jQuery.find( sel, this, null, [ cur ] ).length;
+ }
+ if ( matches[ sel ] ) {
+ matches.push( handleObj );
+ }
+ }
+ if ( matches.length ) {
+ handlerQueue.push({ elem: cur, handlers: matches });
+ }
+ }
+ }
+ }
+
+ // Add the remaining (directly-bound) handlers
+ if ( delegateCount < handlers.length ) {
+ handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
+ }
+
+ return handlerQueue;
+ },
+
+ fix: function( event ) {
+ if ( event[ jQuery.expando ] ) {
+ return event;
+ }
+
+ // Create a writable copy of the event object and normalize some properties
+ var i, prop, copy,
+ type = event.type,
+ originalEvent = event,
+ fixHook = this.fixHooks[ type ];
+
+ if ( !fixHook ) {
+ this.fixHooks[ type ] = fixHook =
+ rmouseEvent.test( type ) ? this.mouseHooks :
+ rkeyEvent.test( type ) ? this.keyHooks :
+ {};
+ }
+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+ event = new jQuery.Event( originalEvent );
+
+ i = copy.length;
+ while ( i-- ) {
+ prop = copy[ i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Support: IE<9
+ // Fix target property (#1925)
+ if ( !event.target ) {
+ event.target = originalEvent.srcElement || document;
+ }
+
+ // Support: Chrome 23+, Safari?
+ // Target should not be a text node (#504, #13143)
+ if ( event.target.nodeType === 3 ) {
+ event.target = event.target.parentNode;
+ }
+
+ // Support: IE<9
+ // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
+ event.metaKey = !!event.metaKey;
+
+ return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
+ },
+
+ // Includes some event props shared by KeyEvent and MouseEvent
+ props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+ fixHooks: {},
+
+ keyHooks: {
+ props: "char charCode key keyCode".split(" "),
+ filter: function( event, original ) {
+
+ // Add which for key events
+ if ( event.which == null ) {
+ event.which = original.charCode != null ? original.charCode : original.keyCode;
+ }
+
+ return event;
+ }
+ },
+
+ mouseHooks: {
+ props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+ filter: function( event, original ) {
+ var body, eventDoc, doc,
+ button = original.button,
+ fromElement = original.fromElement;
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && original.clientX != null ) {
+ eventDoc = event.target.ownerDocument || document;
+ doc = eventDoc.documentElement;
+ body = eventDoc.body;
+
+ event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+ event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
+ }
+
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && fromElement ) {
+ event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && button !== undefined ) {
+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+ }
+
+ return event;
+ }
+ },
+
+ special: {
+ load: {
+ // Prevent triggered image.load events from bubbling to window.load
+ noBubble: true
+ },
+ click: {
+ // For checkbox, fire native event so checked state will be right
+ trigger: function() {
+ if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
+ this.click();
+ return false;
+ }
+ }
+ },
+ focus: {
+ // Fire native event if possible so blur/focus sequence is correct
+ trigger: function() {
+ if ( this !== document.activeElement && this.focus ) {
+ try {
+ this.focus();
+ return false;
+ } catch ( e ) {
+ // Support: IE<9
+ // If we error on focus to hidden element (#1486, #12518),
+ // let .trigger() run the handlers
+ }
+ }
+ },
+ delegateType: "focusin"
+ },
+ blur: {
+ trigger: function() {
+ if ( this === document.activeElement && this.blur ) {
+ this.blur();
+ return false;
+ }
+ },
+ delegateType: "focusout"
+ },
+
+ beforeunload: {
+ postDispatch: function( event ) {
+
+ // Even when returnValue equals to undefined Firefox will still show alert
+ if ( event.result !== undefined ) {
+ event.originalEvent.returnValue = event.result;
+ }
+ }
+ }
+ },
+
+ simulate: function( type, elem, event, bubble ) {
+ // Piggyback on a donor event to simulate a different one.
+ // Fake originalEvent to avoid donor's stopPropagation, but if the
+ // simulated event prevents default then we do the same on the donor.
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ { type: type,
+ isSimulated: true,
+ originalEvent: {}
+ }
+ );
+ if ( bubble ) {
+ jQuery.event.trigger( e, null, elem );
+ } else {
+ jQuery.event.dispatch.call( elem, e );
+ }
+ if ( e.isDefaultPrevented() ) {
+ event.preventDefault();
+ }
+ }
+};
+
+jQuery.removeEvent = document.removeEventListener ?
+ function( elem, type, handle ) {
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle, false );
+ }
+ } :
+ function( elem, type, handle ) {
+ var name = "on" + type;
+
+ if ( elem.detachEvent ) {
+
+ // #8545, #7054, preventing memory leaks for custom events in IE6-8
+ // detachEvent needed property on element, by name of that event, to properly expose it to GC
+ if ( typeof elem[ name ] === core_strundefined ) {
+ elem[ name ] = null;
+ }
+
+ elem.detachEvent( name, handle );
+ }
+ };
+
+jQuery.Event = function( src, props ) {
+ // Allow instantiation without the 'new' keyword
+ if ( !(this instanceof jQuery.Event) ) {
+ return new jQuery.Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
+ src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ jQuery.extend( this, props );
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+};
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse,
+
+ preventDefault: function() {
+ var e = this.originalEvent;
+
+ this.isDefaultPrevented = returnTrue;
+ if ( !e ) {
+ return;
+ }
+
+ // If preventDefault exists, run it on the original event
+ if ( e.preventDefault ) {
+ e.preventDefault();
+
+ // Support: IE
+ // Otherwise set the returnValue property of the original event to false
+ } else {
+ e.returnValue = false;
+ }
+ },
+ stopPropagation: function() {
+ var e = this.originalEvent;
+
+ this.isPropagationStopped = returnTrue;
+ if ( !e ) {
+ return;
+ }
+ // If stopPropagation exists, run it on the original event
+ if ( e.stopPropagation ) {
+ e.stopPropagation();
+ }
+
+ // Support: IE
+ // Set the cancelBubble property of the original event to true
+ e.cancelBubble = true;
+ },
+ stopImmediatePropagation: function() {
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ }
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+jQuery.each({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+}, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ delegateType: fix,
+ bindType: fix,
+
+ handle: function( event ) {
+ var ret,
+ target = this,
+ related = event.relatedTarget,
+ handleObj = event.handleObj;
+
+ // For mousenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+ event.type = handleObj.origType;
+ ret = handleObj.handler.apply( this, arguments );
+ event.type = fix;
+ }
+ return ret;
+ }
+ };
+});
+
+// IE submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+ jQuery.event.special.submit = {
+ setup: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Lazy-add a submit handler when a descendant form may potentially be submitted
+ jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+ // Node name check avoids a VML-related crash in IE (#9807)
+ var elem = e.target,
+ form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+ if ( form && !jQuery._data( form, "submitBubbles" ) ) {
+ jQuery.event.add( form, "submit._submit", function( event ) {
+ event._submit_bubble = true;
+ });
+ jQuery._data( form, "submitBubbles", true );
+ }
+ });
+ // return undefined since we don't need an event listener
+ },
+
+ postDispatch: function( event ) {
+ // If form was submitted by the user, bubble the event up the tree
+ if ( event._submit_bubble ) {
+ delete event._submit_bubble;
+ if ( this.parentNode && !event.isTrigger ) {
+ jQuery.event.simulate( "submit", this.parentNode, event, true );
+ }
+ }
+ },
+
+ teardown: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+ jQuery.event.remove( this, "._submit" );
+ }
+ };
+}
+
+// IE change delegation and checkbox/radio fix
+if ( !jQuery.support.changeBubbles ) {
+
+ jQuery.event.special.change = {
+
+ setup: function() {
+
+ if ( rformElems.test( this.nodeName ) ) {
+ // IE doesn't fire change on a check/radio until blur; trigger it on click
+ // after a propertychange. Eat the blur-change in special.change.handle.
+ // This still fires onchange a second time for check/radio after blur.
+ if ( this.type === "checkbox" || this.type === "radio" ) {
+ jQuery.event.add( this, "propertychange._change", function( event ) {
+ if ( event.originalEvent.propertyName === "checked" ) {
+ this._just_changed = true;
+ }
+ });
+ jQuery.event.add( this, "click._change", function( event ) {
+ if ( this._just_changed && !event.isTrigger ) {
+ this._just_changed = false;
+ }
+ // Allow triggered, simulated change events (#11500)
+ jQuery.event.simulate( "change", this, event, true );
+ });
+ }
+ return false;
+ }
+ // Delegated event; lazy-add a change handler on descendant inputs
+ jQuery.event.add( this, "beforeactivate._change", function( e ) {
+ var elem = e.target;
+
+ if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
+ jQuery.event.add( elem, "change._change", function( event ) {
+ if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+ jQuery.event.simulate( "change", this.parentNode, event, true );
+ }
+ });
+ jQuery._data( elem, "changeBubbles", true );
+ }
+ });
+ },
+
+ handle: function( event ) {
+ var elem = event.target;
+
+ // Swallow native change events from checkbox/radio, we already triggered them above
+ if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+ return event.handleObj.handler.apply( this, arguments );
+ }
+ },
+
+ teardown: function() {
+ jQuery.event.remove( this, "._change" );
+
+ return !rformElems.test( this.nodeName );
+ }
+ };
+}
+
+// Create "bubbling" focus and blur events
+if ( !jQuery.support.focusinBubbles ) {
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler while someone wants focusin/focusout
+ var attaches = 0,
+ handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ if ( attaches++ === 0 ) {
+ document.addEventListener( orig, handler, true );
+ }
+ },
+ teardown: function() {
+ if ( --attaches === 0 ) {
+ document.removeEventListener( orig, handler, true );
+ }
+ }
+ };
+ });
+}
+
+jQuery.fn.extend({
+
+ on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+ var type, origFn;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) {
+ // ( types-Object, data )
+ data = data || selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ this.on( type, selector, data, types[ type ], one );
+ }
+ return this;
+ }
+
+ if ( data == null && fn == null ) {
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return this;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return this.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ });
+ },
+ one: function( types, selector, data, fn ) {
+ return this.on( types, selector, data, fn, 1 );
+ },
+ off: function( types, selector, fn ) {
+ var handleObj, type;
+ if ( types && types.preventDefault && types.handleObj ) {
+ // ( event ) dispatched jQuery.Event
+ handleObj = types.handleObj;
+ jQuery( types.delegateTarget ).off(
+ handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+ handleObj.selector,
+ handleObj.handler
+ );
+ return this;
+ }
+ if ( typeof types === "object" ) {
+ // ( types-object [, selector] )
+ for ( type in types ) {
+ this.off( type, selector, types[ type ] );
+ }
+ return this;
+ }
+ if ( selector === false || typeof selector === "function" ) {
+ // ( types [, fn] )
+ fn = selector;
+ selector = undefined;
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ }
+ return this.each(function() {
+ jQuery.event.remove( this, types, fn, selector );
+ });
+ },
+
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function() {
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+ triggerHandler: function( type, data ) {
+ var elem = this[0];
+ if ( elem ) {
+ return jQuery.event.trigger( type, data, elem, true );
+ }
+ }
+});
+/*!
+ * Sizzle CSS Selector Engine
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://sizzlejs.com/
+ */
+(function( window, undefined ) {
+
+var i,
+ cachedruns,
+ Expr,
+ getText,
+ isXML,
+ compile,
+ hasDuplicate,
+ outermostContext,
+
+ // Local document vars
+ setDocument,
+ document,
+ docElem,
+ documentIsXML,
+ rbuggyQSA,
+ rbuggyMatches,
+ matches,
+ contains,
+ sortOrder,
+
+ // Instance-specific data
+ expando = "sizzle" + -(new Date()),
+ preferredDoc = window.document,
+ support = {},
+ dirruns = 0,
+ done = 0,
+ classCache = createCache(),
+ tokenCache = createCache(),
+ compilerCache = createCache(),
+
+ // General-purpose constants
+ strundefined = typeof undefined,
+ MAX_NEGATIVE = 1 << 31,
+
+ // Array methods
+ arr = [],
+ pop = arr.pop,
+ push = arr.push,
+ slice = arr.slice,
+ // Use a stripped-down indexOf if we can't use a native one
+ indexOf = arr.indexOf || function( elem ) {
+ var i = 0,
+ len = this.length;
+ for ( ; i < len; i++ ) {
+ if ( this[i] === elem ) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+
+ // Regular expressions
+
+ // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+ whitespace = "[\\x20\\t\\r\\n\\f]",
+ // http://www.w3.org/TR/css3-syntax/#characters
+ characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+ // Loosely modeled on CSS identifier characters
+ // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
+ // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = characterEncoding.replace( "w", "w#" ),
+
+ // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
+ operators = "([*^$|!~]?=)",
+ attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
+ "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
+
+ // Prefer arguments quoted,
+ // then not containing pseudos/brackets,
+ // then attribute selectors/non-parenthetical expressions,
+ // then anything else
+ // These preferences are here to reduce the number of selectors
+ // needing tokenize in the PSEUDO preFilter
+ pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
+
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+ rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ),
+ rpseudo = new RegExp( pseudos ),
+ ridentifier = new RegExp( "^" + identifier + "$" ),
+
+ matchExpr = {
+ "ID": new RegExp( "^#(" + characterEncoding + ")" ),
+ "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
+ "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),
+ "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+ "ATTR": new RegExp( "^" + attributes ),
+ "PSEUDO": new RegExp( "^" + pseudos ),
+ "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+ // For use in libraries implementing .is()
+ // We use this for POS matching in `select`
+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+ whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+ },
+
+ rsibling = /[\x20\t\r\n\f]*[+~]/,
+
+ rnative = /^[^{]+\{\s*\[native code/,
+
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+ rinputs = /^(?:input|select|textarea|button)$/i,
+ rheader = /^h\d$/i,
+
+ rescape = /'|\\/g,
+ rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
+
+ // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+ runescape = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,
+ funescape = function( _, escaped ) {
+ var high = "0x" + escaped - 0x10000;
+ // NaN means non-codepoint
+ return high !== high ?
+ escaped :
+ // BMP codepoint
+ high < 0 ?
+ String.fromCharCode( high + 0x10000 ) :
+ // Supplemental Plane codepoint (surrogate pair)
+ String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+ };
+
+// Use a stripped-down slice if we can't use a native one
+try {
+ slice.call( preferredDoc.documentElement.childNodes, 0 )[0].nodeType;
+} catch ( e ) {
+ slice = function( i ) {
+ var elem,
+ results = [];
+ while ( (elem = this[i++]) ) {
+ results.push( elem );
+ }
+ return results;
+ };
+}
+
+/**
+ * For feature detection
+ * @param {Function} fn The function to test for native support
+ */
+function isNative( fn ) {
+ return rnative.test( fn + "" );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
+ * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ * deleting the oldest entry
+ */
+function createCache() {
+ var cache,
+ keys = [];
+
+ return (cache = function( key, value ) {
+ // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+ if ( keys.push( key += " " ) > Expr.cacheLength ) {
+ // Only keep the most recent entries
+ delete cache[ keys.shift() ];
+ }
+ return (cache[ key ] = value);
+ });
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+ fn[ expando ] = true;
+ return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+function assert( fn ) {
+ var div = document.createElement("div");
+
+ try {
+ return fn( div );
+ } catch (e) {
+ return false;
+ } finally {
+ // release memory in IE
+ div = null;
+ }
+}
+
+function Sizzle( selector, context, results, seed ) {
+ var match, elem, m, nodeType,
+ // QSA vars
+ i, groups, old, nid, newContext, newSelector;
+
+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+ setDocument( context );
+ }
+
+ context = context || document;
+ results = results || [];
+
+ if ( !selector || typeof selector !== "string" ) {
+ return results;
+ }
+
+ if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
+ return [];
+ }
+
+ if ( !documentIsXML && !seed ) {
+
+ // Shortcuts
+ if ( (match = rquickExpr.exec( selector )) ) {
+ // Speed-up: Sizzle("#ID")
+ if ( (m = match[1]) ) {
+ if ( nodeType === 9 ) {
+ elem = context.getElementById( m );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE, Opera, and Webkit return items
+ // by name instead of ID
+ if ( elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ } else {
+ return results;
+ }
+ } else {
+ // Context is not a document
+ if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
+ contains( context, elem ) && elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ }
+
+ // Speed-up: Sizzle("TAG")
+ } else if ( match[2] ) {
+ push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );
+ return results;
+
+ // Speed-up: Sizzle(".CLASS")
+ } else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) {
+ push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );
+ return results;
+ }
+ }
+
+ // QSA path
+ if ( support.qsa && !rbuggyQSA.test(selector) ) {
+ old = true;
+ nid = expando;
+ newContext = context;
+ newSelector = nodeType === 9 && selector;
+
+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+ groups = tokenize( selector );
+
+ if ( (old = context.getAttribute("id")) ) {
+ nid = old.replace( rescape, "\\$&" );
+ } else {
+ context.setAttribute( "id", nid );
+ }
+ nid = "[id='" + nid + "'] ";
+
+ i = groups.length;
+ while ( i-- ) {
+ groups[i] = nid + toSelector( groups[i] );
+ }
+ newContext = rsibling.test( selector ) && context.parentNode || context;
+ newSelector = groups.join(",");
+ }
+
+ if ( newSelector ) {
+ try {
+ push.apply( results, slice.call( newContext.querySelectorAll(
+ newSelector
+ ), 0 ) );
+ return results;
+ } catch(qsaError) {
+ } finally {
+ if ( !old ) {
+ context.removeAttribute("id");
+ }
+ }
+ }
+ }
+ }
+
+ // All others
+ return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Detect xml
+ * @param {Element|Object} elem An element or a document
+ */
+isXML = Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+ var doc = node ? node.ownerDocument || node : preferredDoc;
+
+ // If no document and documentElement is available, return
+ if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+ return document;
+ }
+
+ // Set our document
+ document = doc;
+ docElem = doc.documentElement;
+
+ // Support tests
+ documentIsXML = isXML( doc );
+
+ // Check if getElementsByTagName("*") returns only elements
+ support.tagNameNoComments = assert(function( div ) {
+ div.appendChild( doc.createComment("") );
+ return !div.getElementsByTagName("*").length;
+ });
+
+ // Check if attributes should be retrieved by attribute nodes
+ support.attributes = assert(function( div ) {
+ div.innerHTML = " ";
+ var type = typeof div.lastChild.getAttribute("multiple");
+ // IE8 returns a string for some attributes even when not present
+ return type !== "boolean" && type !== "string";
+ });
+
+ // Check if getElementsByClassName can be trusted
+ support.getByClassName = assert(function( div ) {
+ // Opera can't find a second classname (in 9.6)
+ div.innerHTML = "
";
+ if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) {
+ return false;
+ }
+
+ // Safari 3.2 caches class attributes and doesn't catch changes
+ div.lastChild.className = "e";
+ return div.getElementsByClassName("e").length === 2;
+ });
+
+ // Check if getElementById returns elements by name
+ // Check if getElementsByName privileges form controls or returns elements by ID
+ support.getByName = assert(function( div ) {
+ // Inject content
+ div.id = expando + 0;
+ div.innerHTML = "
";
+ docElem.insertBefore( div, docElem.firstChild );
+
+ // Test
+ var pass = doc.getElementsByName &&
+ // buggy browsers will return fewer than the correct 2
+ doc.getElementsByName( expando ).length === 2 +
+ // buggy browsers will return more than the correct 0
+ doc.getElementsByName( expando + 0 ).length;
+ support.getIdNotName = !doc.getElementById( expando );
+
+ // Cleanup
+ docElem.removeChild( div );
+
+ return pass;
+ });
+
+ // IE6/7 return modified attributes
+ Expr.attrHandle = assert(function( div ) {
+ div.innerHTML = " ";
+ return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&
+ div.firstChild.getAttribute("href") === "#";
+ }) ?
+ {} :
+ {
+ "href": function( elem ) {
+ return elem.getAttribute( "href", 2 );
+ },
+ "type": function( elem ) {
+ return elem.getAttribute("type");
+ }
+ };
+
+ // ID find and filter
+ if ( support.getIdNotName ) {
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
+ var m = context.getElementById( id );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [m] : [];
+ }
+ };
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ return elem.getAttribute("id") === attrId;
+ };
+ };
+ } else {
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
+ var m = context.getElementById( id );
+
+ return m ?
+ m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?
+ [m] :
+ undefined :
+ [];
+ }
+ };
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
+ return node && node.value === attrId;
+ };
+ };
+ }
+
+ // Tag
+ Expr.find["TAG"] = support.tagNameNoComments ?
+ function( tag, context ) {
+ if ( typeof context.getElementsByTagName !== strundefined ) {
+ return context.getElementsByTagName( tag );
+ }
+ } :
+ function( tag, context ) {
+ var elem,
+ tmp = [],
+ i = 0,
+ results = context.getElementsByTagName( tag );
+
+ // Filter out possible comments
+ if ( tag === "*" ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem.nodeType === 1 ) {
+ tmp.push( elem );
+ }
+ }
+
+ return tmp;
+ }
+ return results;
+ };
+
+ // Name
+ Expr.find["NAME"] = support.getByName && function( tag, context ) {
+ if ( typeof context.getElementsByName !== strundefined ) {
+ return context.getElementsByName( name );
+ }
+ };
+
+ // Class
+ Expr.find["CLASS"] = support.getByClassName && function( className, context ) {
+ if ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) {
+ return context.getElementsByClassName( className );
+ }
+ };
+
+ // QSA and matchesSelector support
+
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+ rbuggyMatches = [];
+
+ // qSa(:focus) reports false when true (Chrome 21),
+ // no need to also add to buggyMatches since matches checks buggyQSA
+ // A support test would require too much code (would include document ready)
+ rbuggyQSA = [ ":focus" ];
+
+ if ( (support.qsa = isNative(doc.querySelectorAll)) ) {
+ // Build QSA regex
+ // Regex strategy adopted from Diego Perini
+ assert(function( div ) {
+ // Select is set to empty string on purpose
+ // This is to test IE's treatment of not explictly
+ // setting a boolean content attribute,
+ // since its presence should be enough
+ // http://bugs.jquery.com/ticket/12359
+ div.innerHTML = " ";
+
+ // IE8 - Some boolean attributes are not treated correctly
+ if ( !div.querySelectorAll("[selected]").length ) {
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );
+ }
+
+ // Webkit/Opera - :checked should return selected option elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":checked").length ) {
+ rbuggyQSA.push(":checked");
+ }
+ });
+
+ assert(function( div ) {
+
+ // Opera 10-12/IE8 - ^= $= *= and empty values
+ // Should not select anything
+ div.innerHTML = " ";
+ if ( div.querySelectorAll("[i^='']").length ) {
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );
+ }
+
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":enabled").length ) {
+ rbuggyQSA.push( ":enabled", ":disabled" );
+ }
+
+ // Opera 10-11 does not throw on post-comma invalid pseudos
+ div.querySelectorAll("*,:x");
+ rbuggyQSA.push(",.*:");
+ });
+ }
+
+ if ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector ||
+ docElem.mozMatchesSelector ||
+ docElem.webkitMatchesSelector ||
+ docElem.oMatchesSelector ||
+ docElem.msMatchesSelector) )) ) {
+
+ assert(function( div ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9)
+ support.disconnectedMatch = matches.call( div, "div" );
+
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( div, "[s!='']:x" );
+ rbuggyMatches.push( "!=", pseudos );
+ });
+ }
+
+ rbuggyQSA = new RegExp( rbuggyQSA.join("|") );
+ rbuggyMatches = new RegExp( rbuggyMatches.join("|") );
+
+ // Element contains another
+ // Purposefully does not implement inclusive descendent
+ // As in, an element does not contain itself
+ contains = isNative(docElem.contains) || docElem.compareDocumentPosition ?
+ function( a, b ) {
+ var adown = a.nodeType === 9 ? a.documentElement : a,
+ bup = b && b.parentNode;
+ return a === bup || !!( bup && bup.nodeType === 1 && (
+ adown.contains ?
+ adown.contains( bup ) :
+ a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+ ));
+ } :
+ function( a, b ) {
+ if ( b ) {
+ while ( (b = b.parentNode) ) {
+ if ( b === a ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ // Document order sorting
+ sortOrder = docElem.compareDocumentPosition ?
+ function( a, b ) {
+ var compare;
+
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ if ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) {
+ if ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) {
+ if ( a === doc || contains( preferredDoc, a ) ) {
+ return -1;
+ }
+ if ( b === doc || contains( preferredDoc, b ) ) {
+ return 1;
+ }
+ return 0;
+ }
+ return compare & 4 ? -1 : 1;
+ }
+
+ return a.compareDocumentPosition ? -1 : 1;
+ } :
+ function( a, b ) {
+ var cur,
+ i = 0,
+ aup = a.parentNode,
+ bup = b.parentNode,
+ ap = [ a ],
+ bp = [ b ];
+
+ // Exit early if the nodes are identical
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+
+ // Parentless nodes are either documents or disconnected
+ } else if ( !aup || !bup ) {
+ return a === doc ? -1 :
+ b === doc ? 1 :
+ aup ? -1 :
+ bup ? 1 :
+ 0;
+
+ // If the nodes are siblings, we can do a quick check
+ } else if ( aup === bup ) {
+ return siblingCheck( a, b );
+ }
+
+ // Otherwise we need full lists of their ancestors for comparison
+ cur = a;
+ while ( (cur = cur.parentNode) ) {
+ ap.unshift( cur );
+ }
+ cur = b;
+ while ( (cur = cur.parentNode) ) {
+ bp.unshift( cur );
+ }
+
+ // Walk down the tree looking for a discrepancy
+ while ( ap[i] === bp[i] ) {
+ i++;
+ }
+
+ return i ?
+ // Do a sibling check if the nodes have a common ancestor
+ siblingCheck( ap[i], bp[i] ) :
+
+ // Otherwise nodes in our document sort first
+ ap[i] === preferredDoc ? -1 :
+ bp[i] === preferredDoc ? 1 :
+ 0;
+ };
+
+ // Always assume the presence of duplicates if sort doesn't
+ // pass them to our comparison function (as in Google Chrome).
+ hasDuplicate = false;
+ [0, 0].sort( sortOrder );
+ support.detectDuplicates = hasDuplicate;
+
+ return document;
+};
+
+Sizzle.matches = function( expr, elements ) {
+ return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace( rattributeQuotes, "='$1']" );
+
+ // rbuggyQSA always contains :focus, so no need for an existence check
+ if ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) {
+ try {
+ var ret = matches.call( elem, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || support.disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9
+ elem.document && elem.document.nodeType !== 11 ) {
+ return ret;
+ }
+ } catch(e) {}
+ }
+
+ return Sizzle( expr, document, null, [elem] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+ // Set document vars if needed
+ if ( ( context.ownerDocument || context ) !== document ) {
+ setDocument( context );
+ }
+ return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+ var val;
+
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ if ( !documentIsXML ) {
+ name = name.toLowerCase();
+ }
+ if ( (val = Expr.attrHandle[ name ]) ) {
+ return val( elem );
+ }
+ if ( documentIsXML || support.attributes ) {
+ return elem.getAttribute( name );
+ }
+ return ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ?
+ name :
+ val && val.specified ? val.value : null;
+};
+
+Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+// Document sorting and removing duplicates
+Sizzle.uniqueSort = function( results ) {
+ var elem,
+ duplicates = [],
+ i = 1,
+ j = 0;
+
+ // Unless we *know* we can detect duplicates, assume their presence
+ hasDuplicate = !support.detectDuplicates;
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ for ( ; (elem = results[i]); i++ ) {
+ if ( elem === results[ i - 1 ] ) {
+ j = duplicates.push( i );
+ }
+ }
+ while ( j-- ) {
+ results.splice( duplicates[ j ], 1 );
+ }
+ }
+
+ return results;
+};
+
+function siblingCheck( a, b ) {
+ var cur = b && a,
+ diff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE );
+
+ // Use IE sourceIndex if available on both nodes
+ if ( diff ) {
+ return diff;
+ }
+
+ // Check if b follows a
+ if ( cur ) {
+ while ( (cur = cur.nextSibling) ) {
+ if ( cur === b ) {
+ return -1;
+ }
+ }
+ }
+
+ return a ? 1 : -1;
+}
+
+// Returns a function to use in pseudos for input types
+function createInputPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === type;
+ };
+}
+
+// Returns a function to use in pseudos for buttons
+function createButtonPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && elem.type === type;
+ };
+}
+
+// Returns a function to use in pseudos for positionals
+function createPositionalPseudo( fn ) {
+ return markFunction(function( argument ) {
+ argument = +argument;
+ return markFunction(function( seed, matches ) {
+ var j,
+ matchIndexes = fn( [], seed.length, argument ),
+ i = matchIndexes.length;
+
+ // Match elements found at the specified indexes
+ while ( i-- ) {
+ if ( seed[ (j = matchIndexes[i]) ] ) {
+ seed[j] = !(matches[j] = seed[j]);
+ }
+ }
+ });
+ });
+}
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+ var node,
+ ret = "",
+ i = 0,
+ nodeType = elem.nodeType;
+
+ if ( !nodeType ) {
+ // If no nodeType, this is expected to be an array
+ for ( ; (node = elem[i]); i++ ) {
+ // Do not traverse comment nodes
+ ret += getText( node );
+ }
+ } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+ // Use textContent for elements
+ // innerText usage removed for consistency of new lines (see #11153)
+ if ( typeof elem.textContent === "string" ) {
+ return elem.textContent;
+ } else {
+ // Traverse its children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ // Do not include comment or processing instruction nodes
+
+ return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+ // Can be adjusted by the user
+ cacheLength: 50,
+
+ createPseudo: markFunction,
+
+ match: matchExpr,
+
+ find: {},
+
+ relative: {
+ ">": { dir: "parentNode", first: true },
+ " ": { dir: "parentNode" },
+ "+": { dir: "previousSibling", first: true },
+ "~": { dir: "previousSibling" }
+ },
+
+ preFilter: {
+ "ATTR": function( match ) {
+ match[1] = match[1].replace( runescape, funescape );
+
+ // Move the given value to match[3] whether quoted or unquoted
+ match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
+
+ if ( match[2] === "~=" ) {
+ match[3] = " " + match[3] + " ";
+ }
+
+ return match.slice( 0, 4 );
+ },
+
+ "CHILD": function( match ) {
+ /* matches from matchExpr["CHILD"]
+ 1 type (only|nth|...)
+ 2 what (child|of-type)
+ 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+ 4 xn-component of xn+y argument ([+-]?\d*n|)
+ 5 sign of xn-component
+ 6 x of xn-component
+ 7 sign of y-component
+ 8 y of y-component
+ */
+ match[1] = match[1].toLowerCase();
+
+ if ( match[1].slice( 0, 3 ) === "nth" ) {
+ // nth-* requires argument
+ if ( !match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // numeric x and y parameters for Expr.filter.CHILD
+ // remember that false/true cast respectively to 0/1
+ match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+ match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+ // other types prohibit arguments
+ } else if ( match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ return match;
+ },
+
+ "PSEUDO": function( match ) {
+ var excess,
+ unquoted = !match[5] && match[2];
+
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
+ return null;
+ }
+
+ // Accept quoted arguments as-is
+ if ( match[4] ) {
+ match[2] = match[4];
+
+ // Strip excess characters from unquoted arguments
+ } else if ( unquoted && rpseudo.test( unquoted ) &&
+ // Get excess from tokenize (recursively)
+ (excess = tokenize( unquoted, true )) &&
+ // advance to the next closing parenthesis
+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+ // excess is a negative index
+ match[0] = match[0].slice( 0, excess );
+ match[2] = unquoted.slice( 0, excess );
+ }
+
+ // Return only captures needed by the pseudo filter method (type and argument)
+ return match.slice( 0, 3 );
+ }
+ },
+
+ filter: {
+
+ "TAG": function( nodeName ) {
+ if ( nodeName === "*" ) {
+ return function() { return true; };
+ }
+
+ nodeName = nodeName.replace( runescape, funescape ).toLowerCase();
+ return function( elem ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+ };
+ },
+
+ "CLASS": function( className ) {
+ var pattern = classCache[ className + " " ];
+
+ return pattern ||
+ (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+ classCache( className, function( elem ) {
+ return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );
+ });
+ },
+
+ "ATTR": function( name, operator, check ) {
+ return function( elem ) {
+ var result = Sizzle.attr( elem, name );
+
+ if ( result == null ) {
+ return operator === "!=";
+ }
+ if ( !operator ) {
+ return true;
+ }
+
+ result += "";
+
+ return operator === "=" ? result === check :
+ operator === "!=" ? result !== check :
+ operator === "^=" ? check && result.indexOf( check ) === 0 :
+ operator === "*=" ? check && result.indexOf( check ) > -1 :
+ operator === "$=" ? check && result.slice( -check.length ) === check :
+ operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
+ operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+ false;
+ };
+ },
+
+ "CHILD": function( type, what, argument, first, last ) {
+ var simple = type.slice( 0, 3 ) !== "nth",
+ forward = type.slice( -4 ) !== "last",
+ ofType = what === "of-type";
+
+ return first === 1 && last === 0 ?
+
+ // Shortcut for :nth-*(n)
+ function( elem ) {
+ return !!elem.parentNode;
+ } :
+
+ function( elem, context, xml ) {
+ var cache, outerCache, node, diff, nodeIndex, start,
+ dir = simple !== forward ? "nextSibling" : "previousSibling",
+ parent = elem.parentNode,
+ name = ofType && elem.nodeName.toLowerCase(),
+ useCache = !xml && !ofType;
+
+ if ( parent ) {
+
+ // :(first|last|only)-(child|of-type)
+ if ( simple ) {
+ while ( dir ) {
+ node = elem;
+ while ( (node = node[ dir ]) ) {
+ if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
+ return false;
+ }
+ }
+ // Reverse direction for :only-* (if we haven't yet done so)
+ start = dir = type === "only" && !start && "nextSibling";
+ }
+ return true;
+ }
+
+ start = [ forward ? parent.firstChild : parent.lastChild ];
+
+ // non-xml :nth-child(...) stores cache data on `parent`
+ if ( forward && useCache ) {
+ // Seek `elem` from a previously-cached index
+ outerCache = parent[ expando ] || (parent[ expando ] = {});
+ cache = outerCache[ type ] || [];
+ nodeIndex = cache[0] === dirruns && cache[1];
+ diff = cache[0] === dirruns && cache[2];
+ node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+ // Fallback to seeking `elem` from the start
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ // When found, cache indexes on `parent` and break
+ if ( node.nodeType === 1 && ++diff && node === elem ) {
+ outerCache[ type ] = [ dirruns, nodeIndex, diff ];
+ break;
+ }
+ }
+
+ // Use previously-cached element index if available
+ } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
+ diff = cache[1];
+
+ // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
+ } else {
+ // Use the same loop as above to seek `elem` from the start
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
+ // Cache the index of each encountered element
+ if ( useCache ) {
+ (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
+ }
+
+ if ( node === elem ) {
+ break;
+ }
+ }
+ }
+ }
+
+ // Incorporate the offset, then check against cycle size
+ diff -= last;
+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
+ }
+ };
+ },
+
+ "PSEUDO": function( pseudo, argument ) {
+ // pseudo-class names are case-insensitive
+ // http://www.w3.org/TR/selectors/#pseudo-classes
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+ // Remember that setFilters inherits from pseudos
+ var args,
+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+ Sizzle.error( "unsupported pseudo: " + pseudo );
+
+ // The user may use createPseudo to indicate that
+ // arguments are needed to create the filter function
+ // just as Sizzle does
+ if ( fn[ expando ] ) {
+ return fn( argument );
+ }
+
+ // But maintain support for old signatures
+ if ( fn.length > 1 ) {
+ args = [ pseudo, pseudo, "", argument ];
+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+ markFunction(function( seed, matches ) {
+ var idx,
+ matched = fn( seed, argument ),
+ i = matched.length;
+ while ( i-- ) {
+ idx = indexOf.call( seed, matched[i] );
+ seed[ idx ] = !( matches[ idx ] = matched[i] );
+ }
+ }) :
+ function( elem ) {
+ return fn( elem, 0, args );
+ };
+ }
+
+ return fn;
+ }
+ },
+
+ pseudos: {
+ // Potentially complex pseudos
+ "not": markFunction(function( selector ) {
+ // Trim the selector passed to compile
+ // to avoid treating leading and trailing
+ // spaces as combinators
+ var input = [],
+ results = [],
+ matcher = compile( selector.replace( rtrim, "$1" ) );
+
+ return matcher[ expando ] ?
+ markFunction(function( seed, matches, context, xml ) {
+ var elem,
+ unmatched = matcher( seed, null, xml, [] ),
+ i = seed.length;
+
+ // Match elements unmatched by `matcher`
+ while ( i-- ) {
+ if ( (elem = unmatched[i]) ) {
+ seed[i] = !(matches[i] = elem);
+ }
+ }
+ }) :
+ function( elem, context, xml ) {
+ input[0] = elem;
+ matcher( input, null, xml, results );
+ return !results.pop();
+ };
+ }),
+
+ "has": markFunction(function( selector ) {
+ return function( elem ) {
+ return Sizzle( selector, elem ).length > 0;
+ };
+ }),
+
+ "contains": markFunction(function( text ) {
+ return function( elem ) {
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+ };
+ }),
+
+ // "Whether an element is represented by a :lang() selector
+ // is based solely on the element's language value
+ // being equal to the identifier C,
+ // or beginning with the identifier C immediately followed by "-".
+ // The matching of C against the element's language value is performed case-insensitively.
+ // The identifier C does not have to be a valid language name."
+ // http://www.w3.org/TR/selectors/#lang-pseudo
+ "lang": markFunction( function( lang ) {
+ // lang value must be a valid identifider
+ if ( !ridentifier.test(lang || "") ) {
+ Sizzle.error( "unsupported lang: " + lang );
+ }
+ lang = lang.replace( runescape, funescape ).toLowerCase();
+ return function( elem ) {
+ var elemLang;
+ do {
+ if ( (elemLang = documentIsXML ?
+ elem.getAttribute("xml:lang") || elem.getAttribute("lang") :
+ elem.lang) ) {
+
+ elemLang = elemLang.toLowerCase();
+ return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+ }
+ } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+ return false;
+ };
+ }),
+
+ // Miscellaneous
+ "target": function( elem ) {
+ var hash = window.location && window.location.hash;
+ return hash && hash.slice( 1 ) === elem.id;
+ },
+
+ "root": function( elem ) {
+ return elem === docElem;
+ },
+
+ "focus": function( elem ) {
+ return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+ },
+
+ // Boolean properties
+ "enabled": function( elem ) {
+ return elem.disabled === false;
+ },
+
+ "disabled": function( elem ) {
+ return elem.disabled === true;
+ },
+
+ "checked": function( elem ) {
+ // In CSS3, :checked should return both checked and selected elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ var nodeName = elem.nodeName.toLowerCase();
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+ },
+
+ "selected": function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ // Contents
+ "empty": function( elem ) {
+ // http://www.w3.org/TR/selectors/#empty-pseudo
+ // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
+ // not comment, processing instructions, or others
+ // Thanks to Diego Perini for the nodeName shortcut
+ // Greater than "@" means alpha characters (specifically not starting with "#" or "?")
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ "parent": function( elem ) {
+ return !Expr.pseudos["empty"]( elem );
+ },
+
+ // Element/input types
+ "header": function( elem ) {
+ return rheader.test( elem.nodeName );
+ },
+
+ "input": function( elem ) {
+ return rinputs.test( elem.nodeName );
+ },
+
+ "button": function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === "button" || name === "button";
+ },
+
+ "text": function( elem ) {
+ var attr;
+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
+ // use getAttribute instead to test this case
+ return elem.nodeName.toLowerCase() === "input" &&
+ elem.type === "text" &&
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type );
+ },
+
+ // Position-in-collection
+ "first": createPositionalPseudo(function() {
+ return [ 0 ];
+ }),
+
+ "last": createPositionalPseudo(function( matchIndexes, length ) {
+ return [ length - 1 ];
+ }),
+
+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ return [ argument < 0 ? argument + length : argument ];
+ }),
+
+ "even": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 0;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "odd": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 1;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; --i >= 0; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; ++i < length; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ })
+ }
+};
+
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+ Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+ Expr.pseudos[ i ] = createButtonPseudo( i );
+}
+
+function tokenize( selector, parseOnly ) {
+ var matched, match, tokens, type,
+ soFar, groups, preFilters,
+ cached = tokenCache[ selector + " " ];
+
+ if ( cached ) {
+ return parseOnly ? 0 : cached.slice( 0 );
+ }
+
+ soFar = selector;
+ groups = [];
+ preFilters = Expr.preFilter;
+
+ while ( soFar ) {
+
+ // Comma and first run
+ if ( !matched || (match = rcomma.exec( soFar )) ) {
+ if ( match ) {
+ // Don't consume trailing commas as valid
+ soFar = soFar.slice( match[0].length ) || soFar;
+ }
+ groups.push( tokens = [] );
+ }
+
+ matched = false;
+
+ // Combinators
+ if ( (match = rcombinators.exec( soFar )) ) {
+ matched = match.shift();
+ tokens.push( {
+ value: matched,
+ // Cast descendant combinators to space
+ type: match[0].replace( rtrim, " " )
+ } );
+ soFar = soFar.slice( matched.length );
+ }
+
+ // Filters
+ for ( type in Expr.filter ) {
+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+ (match = preFilters[ type ]( match ))) ) {
+ matched = match.shift();
+ tokens.push( {
+ value: matched,
+ type: type,
+ matches: match
+ } );
+ soFar = soFar.slice( matched.length );
+ }
+ }
+
+ if ( !matched ) {
+ break;
+ }
+ }
+
+ // Return the length of the invalid excess
+ // if we're just parsing
+ // Otherwise, throw an error or return tokens
+ return parseOnly ?
+ soFar.length :
+ soFar ?
+ Sizzle.error( selector ) :
+ // Cache the tokens
+ tokenCache( selector, groups ).slice( 0 );
+}
+
+function toSelector( tokens ) {
+ var i = 0,
+ len = tokens.length,
+ selector = "";
+ for ( ; i < len; i++ ) {
+ selector += tokens[i].value;
+ }
+ return selector;
+}
+
+function addCombinator( matcher, combinator, base ) {
+ var dir = combinator.dir,
+ checkNonElements = base && dir === "parentNode",
+ doneName = done++;
+
+ return combinator.first ?
+ // Check against closest ancestor/preceding element
+ function( elem, context, xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ return matcher( elem, context, xml );
+ }
+ }
+ } :
+
+ // Check against all ancestor/preceding elements
+ function( elem, context, xml ) {
+ var data, cache, outerCache,
+ dirkey = dirruns + " " + doneName;
+
+ // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+ if ( xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ if ( matcher( elem, context, xml ) ) {
+ return true;
+ }
+ }
+ }
+ } else {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ outerCache = elem[ expando ] || (elem[ expando ] = {});
+ if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {
+ if ( (data = cache[1]) === true || data === cachedruns ) {
+ return data === true;
+ }
+ } else {
+ cache = outerCache[ dir ] = [ dirkey ];
+ cache[1] = matcher( elem, context, xml ) || cachedruns;
+ if ( cache[1] === true ) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ };
+}
+
+function elementMatcher( matchers ) {
+ return matchers.length > 1 ?
+ function( elem, context, xml ) {
+ var i = matchers.length;
+ while ( i-- ) {
+ if ( !matchers[i]( elem, context, xml ) ) {
+ return false;
+ }
+ }
+ return true;
+ } :
+ matchers[0];
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+ var elem,
+ newUnmatched = [],
+ i = 0,
+ len = unmatched.length,
+ mapped = map != null;
+
+ for ( ; i < len; i++ ) {
+ if ( (elem = unmatched[i]) ) {
+ if ( !filter || filter( elem, context, xml ) ) {
+ newUnmatched.push( elem );
+ if ( mapped ) {
+ map.push( i );
+ }
+ }
+ }
+ }
+
+ return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+ if ( postFilter && !postFilter[ expando ] ) {
+ postFilter = setMatcher( postFilter );
+ }
+ if ( postFinder && !postFinder[ expando ] ) {
+ postFinder = setMatcher( postFinder, postSelector );
+ }
+ return markFunction(function( seed, results, context, xml ) {
+ var temp, i, elem,
+ preMap = [],
+ postMap = [],
+ preexisting = results.length,
+
+ // Get initial elements from seed or context
+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
+ matcherIn = preFilter && ( seed || !selector ) ?
+ condense( elems, preMap, preFilter, context, xml ) :
+ elems,
+
+ matcherOut = matcher ?
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+ // ...intermediate processing is necessary
+ [] :
+
+ // ...otherwise use results directly
+ results :
+ matcherIn;
+
+ // Find primary matches
+ if ( matcher ) {
+ matcher( matcherIn, matcherOut, context, xml );
+ }
+
+ // Apply postFilter
+ if ( postFilter ) {
+ temp = condense( matcherOut, postMap );
+ postFilter( temp, [], context, xml );
+
+ // Un-match failing elements by moving them back to matcherIn
+ i = temp.length;
+ while ( i-- ) {
+ if ( (elem = temp[i]) ) {
+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+ }
+ }
+ }
+
+ if ( seed ) {
+ if ( postFinder || preFilter ) {
+ if ( postFinder ) {
+ // Get the final matcherOut by condensing this intermediate into postFinder contexts
+ temp = [];
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) ) {
+ // Restore matcherIn since elem is not yet a final match
+ temp.push( (matcherIn[i] = elem) );
+ }
+ }
+ postFinder( null, (matcherOut = []), temp, xml );
+ }
+
+ // Move matched elements from seed to results to keep them synchronized
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) &&
+ (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
+
+ seed[temp] = !(results[temp] = elem);
+ }
+ }
+ }
+
+ // Add elements to results, through postFinder if defined
+ } else {
+ matcherOut = condense(
+ matcherOut === results ?
+ matcherOut.splice( preexisting, matcherOut.length ) :
+ matcherOut
+ );
+ if ( postFinder ) {
+ postFinder( null, results, matcherOut, xml );
+ } else {
+ push.apply( results, matcherOut );
+ }
+ }
+ });
+}
+
+function matcherFromTokens( tokens ) {
+ var checkContext, matcher, j,
+ len = tokens.length,
+ leadingRelative = Expr.relative[ tokens[0].type ],
+ implicitRelative = leadingRelative || Expr.relative[" "],
+ i = leadingRelative ? 1 : 0,
+
+ // The foundational matcher ensures that elements are reachable from top-level context(s)
+ matchContext = addCombinator( function( elem ) {
+ return elem === checkContext;
+ }, implicitRelative, true ),
+ matchAnyContext = addCombinator( function( elem ) {
+ return indexOf.call( checkContext, elem ) > -1;
+ }, implicitRelative, true ),
+ matchers = [ function( elem, context, xml ) {
+ return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+ (checkContext = context).nodeType ?
+ matchContext( elem, context, xml ) :
+ matchAnyContext( elem, context, xml ) );
+ } ];
+
+ for ( ; i < len; i++ ) {
+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+ matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+ } else {
+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+ // Return special upon seeing a positional matcher
+ if ( matcher[ expando ] ) {
+ // Find the next relative operator (if any) for proper handling
+ j = ++i;
+ for ( ; j < len; j++ ) {
+ if ( Expr.relative[ tokens[j].type ] ) {
+ break;
+ }
+ }
+ return setMatcher(
+ i > 1 && elementMatcher( matchers ),
+ i > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, "$1" ),
+ matcher,
+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+ j < len && toSelector( tokens )
+ );
+ }
+ matchers.push( matcher );
+ }
+ }
+
+ return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+ // A counter to specify which element is currently being matched
+ var matcherCachedRuns = 0,
+ bySet = setMatchers.length > 0,
+ byElement = elementMatchers.length > 0,
+ superMatcher = function( seed, context, xml, results, expandContext ) {
+ var elem, j, matcher,
+ setMatched = [],
+ matchedCount = 0,
+ i = "0",
+ unmatched = seed && [],
+ outermost = expandContext != null,
+ contextBackup = outermostContext,
+ // We must always have either seed elements or context
+ elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
+ // Use integer dirruns iff this is the outermost matcher
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);
+
+ if ( outermost ) {
+ outermostContext = context !== document && context;
+ cachedruns = matcherCachedRuns;
+ }
+
+ // Add elements passing elementMatchers directly to results
+ // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
+ for ( ; (elem = elems[i]) != null; i++ ) {
+ if ( byElement && elem ) {
+ j = 0;
+ while ( (matcher = elementMatchers[j++]) ) {
+ if ( matcher( elem, context, xml ) ) {
+ results.push( elem );
+ break;
+ }
+ }
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ cachedruns = ++matcherCachedRuns;
+ }
+ }
+
+ // Track unmatched elements for set filters
+ if ( bySet ) {
+ // They will have gone through all possible matchers
+ if ( (elem = !matcher && elem) ) {
+ matchedCount--;
+ }
+
+ // Lengthen the array for every element, matched or not
+ if ( seed ) {
+ unmatched.push( elem );
+ }
+ }
+ }
+
+ // Apply set filters to unmatched elements
+ matchedCount += i;
+ if ( bySet && i !== matchedCount ) {
+ j = 0;
+ while ( (matcher = setMatchers[j++]) ) {
+ matcher( unmatched, setMatched, context, xml );
+ }
+
+ if ( seed ) {
+ // Reintegrate element matches to eliminate the need for sorting
+ if ( matchedCount > 0 ) {
+ while ( i-- ) {
+ if ( !(unmatched[i] || setMatched[i]) ) {
+ setMatched[i] = pop.call( results );
+ }
+ }
+ }
+
+ // Discard index placeholder values to get only actual matches
+ setMatched = condense( setMatched );
+ }
+
+ // Add matches to results
+ push.apply( results, setMatched );
+
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
+ if ( outermost && !seed && setMatched.length > 0 &&
+ ( matchedCount + setMatchers.length ) > 1 ) {
+
+ Sizzle.uniqueSort( results );
+ }
+ }
+
+ // Override manipulation of globals by nested matchers
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ outermostContext = contextBackup;
+ }
+
+ return unmatched;
+ };
+
+ return bySet ?
+ markFunction( superMatcher ) :
+ superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
+ var i,
+ setMatchers = [],
+ elementMatchers = [],
+ cached = compilerCache[ selector + " " ];
+
+ if ( !cached ) {
+ // Generate a function of recursive functions that can be used to check each element
+ if ( !group ) {
+ group = tokenize( selector );
+ }
+ i = group.length;
+ while ( i-- ) {
+ cached = matcherFromTokens( group[i] );
+ if ( cached[ expando ] ) {
+ setMatchers.push( cached );
+ } else {
+ elementMatchers.push( cached );
+ }
+ }
+
+ // Cache the compiled function
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+ }
+ return cached;
+};
+
+function multipleContexts( selector, contexts, results ) {
+ var i = 0,
+ len = contexts.length;
+ for ( ; i < len; i++ ) {
+ Sizzle( selector, contexts[i], results );
+ }
+ return results;
+}
+
+function select( selector, context, results, seed ) {
+ var i, tokens, token, type, find,
+ match = tokenize( selector );
+
+ if ( !seed ) {
+ // Try to minimize operations if there is only one group
+ if ( match.length === 1 ) {
+
+ // Take a shortcut and set the context if the root selector is an ID
+ tokens = match[0] = match[0].slice( 0 );
+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+ context.nodeType === 9 && !documentIsXML &&
+ Expr.relative[ tokens[1].type ] ) {
+
+ context = Expr.find["ID"]( token.matches[0].replace( runescape, funescape ), context )[0];
+ if ( !context ) {
+ return results;
+ }
+
+ selector = selector.slice( tokens.shift().value.length );
+ }
+
+ // Fetch a seed set for right-to-left matching
+ i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+ while ( i-- ) {
+ token = tokens[i];
+
+ // Abort if we hit a combinator
+ if ( Expr.relative[ (type = token.type) ] ) {
+ break;
+ }
+ if ( (find = Expr.find[ type ]) ) {
+ // Search, expanding context for leading sibling combinators
+ if ( (seed = find(
+ token.matches[0].replace( runescape, funescape ),
+ rsibling.test( tokens[0].type ) && context.parentNode || context
+ )) ) {
+
+ // If seed is empty or no tokens remain, we can return early
+ tokens.splice( i, 1 );
+ selector = seed.length && toSelector( tokens );
+ if ( !selector ) {
+ push.apply( results, slice.call( seed, 0 ) );
+ return results;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Compile and execute a filtering function
+ // Provide `match` to avoid retokenization if we modified the selector above
+ compile( selector, match )(
+ seed,
+ context,
+ documentIsXML,
+ results,
+ rsibling.test( selector )
+ );
+ return results;
+}
+
+// Deprecated
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Easy API for creating new setFilters
+function setFilters() {}
+Expr.filters = setFilters.prototype = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+// Initialize with the default document
+setDocument();
+
+// Override sizzle attribute retrieval
+Sizzle.attr = jQuery.attr;
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.pseudos;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+})( window );
+var runtil = /Until$/,
+ rparentsprev = /^(?:parents|prev(?:Until|All))/,
+ isSimple = /^.[^:#\[\.,]*$/,
+ rneedsContext = jQuery.expr.match.needsContext,
+ // methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+jQuery.fn.extend({
+ find: function( selector ) {
+ var i, ret, self,
+ len = this.length;
+
+ if ( typeof selector !== "string" ) {
+ self = this;
+ return this.pushStack( jQuery( selector ).filter(function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ }) );
+ }
+
+ ret = [];
+ for ( i = 0; i < len; i++ ) {
+ jQuery.find( selector, this[ i ], ret );
+ }
+
+ // Needed because $( selector, context ) becomes $( context ).find( selector )
+ ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+ ret.selector = ( this.selector ? this.selector + " " : "" ) + selector;
+ return ret;
+ },
+
+ has: function( target ) {
+ var i,
+ targets = jQuery( target, this ),
+ len = targets.length;
+
+ return this.filter(function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
+
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector, false) );
+ },
+
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector, true) );
+ },
+
+ is: function( selector ) {
+ return !!selector && (
+ typeof selector === "string" ?
+ // If this is a positional/relative selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ rneedsContext.test( selector ) ?
+ jQuery( selector, this.context ).index( this[0] ) >= 0 :
+ jQuery.filter( selector, this ).length > 0 :
+ this.filter( selector ).length > 0 );
+ },
+
+ closest: function( selectors, context ) {
+ var cur,
+ i = 0,
+ l = this.length,
+ ret = [],
+ pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+ jQuery( selectors, context || this.context ) :
+ 0;
+
+ for ( ; i < l; i++ ) {
+ cur = this[i];
+
+ while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {
+ if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+ ret.push( cur );
+ break;
+ }
+ cur = cur.parentNode;
+ }
+ }
+
+ return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
+ }
+
+ // index in selector
+ if ( typeof elem === "string" ) {
+ return jQuery.inArray( this[0], jQuery( elem ) );
+ }
+
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[0] : elem, this );
+ },
+
+ add: function( selector, context ) {
+ var set = typeof selector === "string" ?
+ jQuery( selector, context ) :
+ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
+ all = jQuery.merge( this.get(), set );
+
+ return this.pushStack( jQuery.unique(all) );
+ },
+
+ addBack: function( selector ) {
+ return this.add( selector == null ?
+ this.prevObject : this.prevObject.filter(selector)
+ );
+ }
+});
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+function sibling( cur, dir ) {
+ do {
+ cur = cur[ dir ];
+ } while ( cur && cur.nodeType !== 1 );
+
+ return cur;
+}
+
+jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return sibling( elem, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return sibling( elem, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return jQuery.nodeName( elem, "iframe" ) ?
+ elem.contentDocument || elem.contentWindow.document :
+ jQuery.merge( [], elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var ret = jQuery.map( this, fn, until );
+
+ if ( !runtil.test( name ) ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ ret = jQuery.filter( selector, ret );
+ }
+
+ ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
+
+ if ( this.length > 1 && rparentsprev.test( name ) ) {
+ ret = ret.reverse();
+ }
+
+ return this.pushStack( ret );
+ };
+});
+
+jQuery.extend({
+ filter: function( expr, elems, not ) {
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return elems.length === 1 ?
+ jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+ jQuery.find.matches(expr, elems);
+ },
+
+ dir: function( elem, dir, until ) {
+ var matched = [],
+ cur = elem[ dir ];
+
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+ if ( cur.nodeType === 1 ) {
+ matched.push( cur );
+ }
+ cur = cur[dir];
+ }
+ return matched;
+ },
+
+ sibling: function( n, elem ) {
+ var r = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ r.push( n );
+ }
+ }
+
+ return r;
+ }
+});
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, keep ) {
+
+ // Can't pass null or undefined to indexOf in Firefox 4
+ // Set to 0 to skip string check
+ qualifier = qualifier || 0;
+
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ var retVal = !!qualifier.call( elem, i, elem );
+ return retVal === keep;
+ });
+
+ } else if ( qualifier.nodeType ) {
+ return jQuery.grep(elements, function( elem ) {
+ return ( elem === qualifier ) === keep;
+ });
+
+ } else if ( typeof qualifier === "string" ) {
+ var filtered = jQuery.grep(elements, function( elem ) {
+ return elem.nodeType === 1;
+ });
+
+ if ( isSimple.test( qualifier ) ) {
+ return jQuery.filter(qualifier, filtered, !keep);
+ } else {
+ qualifier = jQuery.filter( qualifier, filtered );
+ }
+ }
+
+ return jQuery.grep(elements, function( elem ) {
+ return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
+ });
+}
+function createSafeFragment( document ) {
+ var list = nodeNames.split( "|" ),
+ safeFrag = document.createDocumentFragment();
+
+ if ( safeFrag.createElement ) {
+ while ( list.length ) {
+ safeFrag.createElement(
+ list.pop()
+ );
+ }
+ }
+ return safeFrag;
+}
+
+var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
+ "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+ rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
+ rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
+ rleadingWhitespace = /^\s+/,
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
+ rtagName = /<([\w:]+)/,
+ rtbody = /\s*$/g,
+
+ // We have to close these tags to support XHTML (#13200)
+ wrapMap = {
+ option: [ 1, "", " " ],
+ legend: [ 1, "", " " ],
+ area: [ 1, "", " " ],
+ param: [ 1, "", " " ],
+ thead: [ 1, "" ],
+ tr: [ 2, "" ],
+ col: [ 2, "" ],
+ td: [ 3, "" ],
+
+ // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
+ // unless wrapped in a div with non-breaking characters in front of it.
+ _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X", "
" ]
+ },
+ safeFragment = createSafeFragment( document ),
+ fragmentDiv = safeFragment.appendChild( document.createElement("div") );
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+jQuery.fn.extend({
+ text: function( value ) {
+ return jQuery.access( this, function( value ) {
+ return value === undefined ?
+ jQuery.text( this ) :
+ this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
+ }, null, value, arguments.length );
+ },
+
+ wrapAll: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapAll( html.call(this, i) );
+ });
+ }
+
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+ if ( this[0].parentNode ) {
+ wrap.insertBefore( this[0] );
+ }
+
+ wrap.map(function() {
+ var elem = this;
+
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+ elem = elem.firstChild;
+ }
+
+ return elem;
+ }).append( this );
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapInner( html.call(this, i) );
+ });
+ }
+
+ return this.each(function() {
+ var self = jQuery( this ),
+ contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ });
+ },
+
+ wrap: function( html ) {
+ var isFunction = jQuery.isFunction( html );
+
+ return this.each(function(i) {
+ jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+ });
+ },
+
+ unwrap: function() {
+ return this.parent().each(function() {
+ if ( !jQuery.nodeName( this, "body" ) ) {
+ jQuery( this ).replaceWith( this.childNodes );
+ }
+ }).end();
+ },
+
+ append: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ this.appendChild( elem );
+ }
+ });
+ },
+
+ prepend: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ this.insertBefore( elem, this.firstChild );
+ }
+ });
+ },
+
+ before: function() {
+ return this.domManip( arguments, false, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this );
+ }
+ });
+ },
+
+ after: function() {
+ return this.domManip( arguments, false, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ }
+ });
+ },
+
+ // keepData is for internal use only--do not document
+ remove: function( selector, keepData ) {
+ var elem,
+ i = 0;
+
+ for ( ; (elem = this[i]) != null; i++ ) {
+ if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) {
+ if ( !keepData && elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem ) );
+ }
+
+ if ( elem.parentNode ) {
+ if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
+ setGlobalEval( getAll( elem, "script" ) );
+ }
+ elem.parentNode.removeChild( elem );
+ }
+ }
+ }
+
+ return this;
+ },
+
+ empty: function() {
+ var elem,
+ i = 0;
+
+ for ( ; (elem = this[i]) != null; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem, false ) );
+ }
+
+ // Remove any remaining nodes
+ while ( elem.firstChild ) {
+ elem.removeChild( elem.firstChild );
+ }
+
+ // If this is a select, ensure that it displays empty (#12336)
+ // Support: IE<9
+ if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
+ elem.options.length = 0;
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( dataAndEvents, deepDataAndEvents ) {
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+ return this.map( function () {
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+ });
+ },
+
+ html: function( value ) {
+ return jQuery.access( this, function( value ) {
+ var elem = this[0] || {},
+ i = 0,
+ l = this.length;
+
+ if ( value === undefined ) {
+ return elem.nodeType === 1 ?
+ elem.innerHTML.replace( rinlinejQuery, "" ) :
+ undefined;
+ }
+
+ // See if we can take a shortcut and just use innerHTML
+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+ ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) &&
+ ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
+ !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
+
+ value = value.replace( rxhtmlTag, "<$1>$2>" );
+
+ try {
+ for (; i < l; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ elem = this[i] || {};
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem, false ) );
+ elem.innerHTML = value;
+ }
+ }
+
+ elem = 0;
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch(e) {}
+ }
+
+ if ( elem ) {
+ this.empty().append( value );
+ }
+ }, null, value, arguments.length );
+ },
+
+ replaceWith: function( value ) {
+ var isFunc = jQuery.isFunction( value );
+
+ // Make sure that the elements are removed from the DOM before they are inserted
+ // this can help fix replacing a parent with child elements
+ if ( !isFunc && typeof value !== "string" ) {
+ value = jQuery( value ).not( this ).detach();
+ }
+
+ return this.domManip( [ value ], true, function( elem ) {
+ var next = this.nextSibling,
+ parent = this.parentNode;
+
+ if ( parent ) {
+ jQuery( this ).remove();
+ parent.insertBefore( elem, next );
+ }
+ });
+ },
+
+ detach: function( selector ) {
+ return this.remove( selector, true );
+ },
+
+ domManip: function( args, table, callback ) {
+
+ // Flatten any nested arrays
+ args = core_concat.apply( [], args );
+
+ var first, node, hasScripts,
+ scripts, doc, fragment,
+ i = 0,
+ l = this.length,
+ set = this,
+ iNoClone = l - 1,
+ value = args[0],
+ isFunction = jQuery.isFunction( value );
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {
+ return this.each(function( index ) {
+ var self = set.eq( index );
+ if ( isFunction ) {
+ args[0] = value.call( this, index, table ? self.html() : undefined );
+ }
+ self.domManip( args, table, callback );
+ });
+ }
+
+ if ( l ) {
+ fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
+ first = fragment.firstChild;
+
+ if ( fragment.childNodes.length === 1 ) {
+ fragment = first;
+ }
+
+ if ( first ) {
+ table = table && jQuery.nodeName( first, "tr" );
+ scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+ hasScripts = scripts.length;
+
+ // Use the original fragment for the last item instead of the first because it can end up
+ // being emptied incorrectly in certain situations (#8070).
+ for ( ; i < l; i++ ) {
+ node = fragment;
+
+ if ( i !== iNoClone ) {
+ node = jQuery.clone( node, true, true );
+
+ // Keep references to cloned scripts for later restoration
+ if ( hasScripts ) {
+ jQuery.merge( scripts, getAll( node, "script" ) );
+ }
+ }
+
+ callback.call(
+ table && jQuery.nodeName( this[i], "table" ) ?
+ findOrAppend( this[i], "tbody" ) :
+ this[i],
+ node,
+ i
+ );
+ }
+
+ if ( hasScripts ) {
+ doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+ // Reenable scripts
+ jQuery.map( scripts, restoreScript );
+
+ // Evaluate executable scripts on first document insertion
+ for ( i = 0; i < hasScripts; i++ ) {
+ node = scripts[ i ];
+ if ( rscriptType.test( node.type || "" ) &&
+ !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
+
+ if ( node.src ) {
+ // Hope ajax is available...
+ jQuery.ajax({
+ url: node.src,
+ type: "GET",
+ dataType: "script",
+ async: false,
+ global: false,
+ "throws": true
+ });
+ } else {
+ jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
+ }
+ }
+ }
+ }
+
+ // Fix #11809: Avoid leaking memory
+ fragment = first = null;
+ }
+ }
+
+ return this;
+ }
+});
+
+function findOrAppend( elem, tag ) {
+ return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );
+}
+
+// Replace/restore the type attribute of script elements for safe DOM manipulation
+function disableScript( elem ) {
+ var attr = elem.getAttributeNode("type");
+ elem.type = ( attr && attr.specified ) + "/" + elem.type;
+ return elem;
+}
+function restoreScript( elem ) {
+ var match = rscriptTypeMasked.exec( elem.type );
+ if ( match ) {
+ elem.type = match[1];
+ } else {
+ elem.removeAttribute("type");
+ }
+ return elem;
+}
+
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+ var elem,
+ i = 0;
+ for ( ; (elem = elems[i]) != null; i++ ) {
+ jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
+ }
+}
+
+function cloneCopyEvent( src, dest ) {
+
+ if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+ return;
+ }
+
+ var type, i, l,
+ oldData = jQuery._data( src ),
+ curData = jQuery._data( dest, oldData ),
+ events = oldData.events;
+
+ if ( events ) {
+ delete curData.handle;
+ curData.events = {};
+
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type, events[ type ][ i ] );
+ }
+ }
+ }
+
+ // make the cloned public data object a copy from the original
+ if ( curData.data ) {
+ curData.data = jQuery.extend( {}, curData.data );
+ }
+}
+
+function fixCloneNodeIssues( src, dest ) {
+ var nodeName, e, data;
+
+ // We do not need to do anything for non-Elements
+ if ( dest.nodeType !== 1 ) {
+ return;
+ }
+
+ nodeName = dest.nodeName.toLowerCase();
+
+ // IE6-8 copies events bound via attachEvent when using cloneNode.
+ if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) {
+ data = jQuery._data( dest );
+
+ for ( e in data.events ) {
+ jQuery.removeEvent( dest, e, data.handle );
+ }
+
+ // Event data gets referenced instead of copied if the expando gets copied too
+ dest.removeAttribute( jQuery.expando );
+ }
+
+ // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
+ if ( nodeName === "script" && dest.text !== src.text ) {
+ disableScript( dest ).text = src.text;
+ restoreScript( dest );
+
+ // IE6-10 improperly clones children of object elements using classid.
+ // IE10 throws NoModificationAllowedError if parent is null, #12132.
+ } else if ( nodeName === "object" ) {
+ if ( dest.parentNode ) {
+ dest.outerHTML = src.outerHTML;
+ }
+
+ // This path appears unavoidable for IE9. When cloning an object
+ // element in IE9, the outerHTML strategy above is not sufficient.
+ // If the src has innerHTML and the destination does not,
+ // copy the src.innerHTML into the dest.innerHTML. #10324
+ if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
+ dest.innerHTML = src.innerHTML;
+ }
+
+ } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) {
+ // IE6-8 fails to persist the checked state of a cloned checkbox
+ // or radio button. Worse, IE6-7 fail to give the cloned element
+ // a checked appearance if the defaultChecked value isn't also set
+
+ dest.defaultChecked = dest.checked = src.checked;
+
+ // IE6-7 get confused and end up setting the value of a cloned
+ // checkbox/radio button to an empty string instead of "on"
+ if ( dest.value !== src.value ) {
+ dest.value = src.value;
+ }
+
+ // IE6-8 fails to return the selected option to the default selected
+ // state when cloning options
+ } else if ( nodeName === "option" ) {
+ dest.defaultSelected = dest.selected = src.defaultSelected;
+
+ // IE6-8 fails to set the defaultValue to the correct value when
+ // cloning other types of input fields
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
+ }
+}
+
+jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var elems,
+ i = 0,
+ ret = [],
+ insert = jQuery( selector ),
+ last = insert.length - 1;
+
+ for ( ; i <= last; i++ ) {
+ elems = i === last ? this : this.clone(true);
+ jQuery( insert[i] )[ original ]( elems );
+
+ // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
+ core_push.apply( ret, elems.get() );
+ }
+
+ return this.pushStack( ret );
+ };
+});
+
+function getAll( context, tag ) {
+ var elems, elem,
+ i = 0,
+ found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) :
+ typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) :
+ undefined;
+
+ if ( !found ) {
+ for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
+ if ( !tag || jQuery.nodeName( elem, tag ) ) {
+ found.push( elem );
+ } else {
+ jQuery.merge( found, getAll( elem, tag ) );
+ }
+ }
+ }
+
+ return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+ jQuery.merge( [ context ], found ) :
+ found;
+}
+
+// Used in buildFragment, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+ if ( manipulation_rcheckableType.test( elem.type ) ) {
+ elem.defaultChecked = elem.checked;
+ }
+}
+
+jQuery.extend({
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var destElements, node, clone, i, srcElements,
+ inPage = jQuery.contains( elem.ownerDocument, elem );
+
+ if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
+ clone = elem.cloneNode( true );
+
+ // IE<=8 does not properly clone detached, unknown element nodes
+ } else {
+ fragmentDiv.innerHTML = elem.outerHTML;
+ fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
+ }
+
+ if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
+ (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+
+ // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
+ destElements = getAll( clone );
+ srcElements = getAll( elem );
+
+ // Fix all IE cloning issues
+ for ( i = 0; (node = srcElements[i]) != null; ++i ) {
+ // Ensure that the destination node is not null; Fixes #9587
+ if ( destElements[i] ) {
+ fixCloneNodeIssues( node, destElements[i] );
+ }
+ }
+ }
+
+ // Copy the events from the original to the clone
+ if ( dataAndEvents ) {
+ if ( deepDataAndEvents ) {
+ srcElements = srcElements || getAll( elem );
+ destElements = destElements || getAll( clone );
+
+ for ( i = 0; (node = srcElements[i]) != null; i++ ) {
+ cloneCopyEvent( node, destElements[i] );
+ }
+ } else {
+ cloneCopyEvent( elem, clone );
+ }
+ }
+
+ // Preserve script evaluation history
+ destElements = getAll( clone, "script" );
+ if ( destElements.length > 0 ) {
+ setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+ }
+
+ destElements = srcElements = node = null;
+
+ // Return the cloned set
+ return clone;
+ },
+
+ buildFragment: function( elems, context, scripts, selection ) {
+ var j, elem, contains,
+ tmp, tag, tbody, wrap,
+ l = elems.length,
+
+ // Ensure a safe fragment
+ safe = createSafeFragment( context ),
+
+ nodes = [],
+ i = 0;
+
+ for ( ; i < l; i++ ) {
+ elem = elems[ i ];
+
+ if ( elem || elem === 0 ) {
+
+ // Add nodes directly
+ if ( jQuery.type( elem ) === "object" ) {
+ jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+ // Convert non-html into a text node
+ } else if ( !rhtml.test( elem ) ) {
+ nodes.push( context.createTextNode( elem ) );
+
+ // Convert html into DOM nodes
+ } else {
+ tmp = tmp || safe.appendChild( context.createElement("div") );
+
+ // Deserialize a standard representation
+ tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
+ wrap = wrapMap[ tag ] || wrapMap._default;
+
+ tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>$2>" ) + wrap[2];
+
+ // Descend through wrappers to the right content
+ j = wrap[0];
+ while ( j-- ) {
+ tmp = tmp.lastChild;
+ }
+
+ // Manually add leading whitespace removed by IE
+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+ nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
+ }
+
+ // Remove IE's autoinserted from table fragments
+ if ( !jQuery.support.tbody ) {
+
+ // String was a , *may* have spurious
+ elem = tag === "table" && !rtbody.test( elem ) ?
+ tmp.firstChild :
+
+ // String was a bare or
+ wrap[1] === "" && !rtbody.test( elem ) ?
+ tmp :
+ 0;
+
+ j = elem && elem.childNodes.length;
+ while ( j-- ) {
+ if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
+ elem.removeChild( tbody );
+ }
+ }
+ }
+
+ jQuery.merge( nodes, tmp.childNodes );
+
+ // Fix #12392 for WebKit and IE > 9
+ tmp.textContent = "";
+
+ // Fix #12392 for oldIE
+ while ( tmp.firstChild ) {
+ tmp.removeChild( tmp.firstChild );
+ }
+
+ // Remember the top-level container for proper cleanup
+ tmp = safe.lastChild;
+ }
+ }
+ }
+
+ // Fix #11356: Clear elements from fragment
+ if ( tmp ) {
+ safe.removeChild( tmp );
+ }
+
+ // Reset defaultChecked for any radios and checkboxes
+ // about to be appended to the DOM in IE 6/7 (#8060)
+ if ( !jQuery.support.appendChecked ) {
+ jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
+ }
+
+ i = 0;
+ while ( (elem = nodes[ i++ ]) ) {
+
+ // #4087 - If origin and destination elements are the same, and this is
+ // that element, do not do anything
+ if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
+ continue;
+ }
+
+ contains = jQuery.contains( elem.ownerDocument, elem );
+
+ // Append to fragment
+ tmp = getAll( safe.appendChild( elem ), "script" );
+
+ // Preserve script evaluation history
+ if ( contains ) {
+ setGlobalEval( tmp );
+ }
+
+ // Capture executables
+ if ( scripts ) {
+ j = 0;
+ while ( (elem = tmp[ j++ ]) ) {
+ if ( rscriptType.test( elem.type || "" ) ) {
+ scripts.push( elem );
+ }
+ }
+ }
+ }
+
+ tmp = null;
+
+ return safe;
+ },
+
+ cleanData: function( elems, /* internal */ acceptData ) {
+ var elem, type, id, data,
+ i = 0,
+ internalKey = jQuery.expando,
+ cache = jQuery.cache,
+ deleteExpando = jQuery.support.deleteExpando,
+ special = jQuery.event.special;
+
+ for ( ; (elem = elems[i]) != null; i++ ) {
+
+ if ( acceptData || jQuery.acceptData( elem ) ) {
+
+ id = elem[ internalKey ];
+ data = id && cache[ id ];
+
+ if ( data ) {
+ if ( data.events ) {
+ for ( type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ // This is a shortcut to avoid jQuery.event.remove's overhead
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
+ }
+
+ // Remove cache only if it was not already removed by jQuery.event.remove
+ if ( cache[ id ] ) {
+
+ delete cache[ id ];
+
+ // IE does not allow us to delete expando properties from nodes,
+ // nor does it have a removeAttribute function on Document nodes;
+ // we must handle all of these cases
+ if ( deleteExpando ) {
+ delete elem[ internalKey ];
+
+ } else if ( typeof elem.removeAttribute !== core_strundefined ) {
+ elem.removeAttribute( internalKey );
+
+ } else {
+ elem[ internalKey ] = null;
+ }
+
+ core_deletedIds.push( id );
+ }
+ }
+ }
+ }
+ }
+});
+var iframe, getStyles, curCSS,
+ ralpha = /alpha\([^)]*\)/i,
+ ropacity = /opacity\s*=\s*([^)]*)/,
+ rposition = /^(top|right|bottom|left)$/,
+ // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+ // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+ rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+ rmargin = /^margin/,
+ rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
+ rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
+ rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ),
+ elemdisplay = { BODY: "block" },
+
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+ cssNormalTransform = {
+ letterSpacing: 0,
+ fontWeight: 400
+ },
+
+ cssExpand = [ "Top", "Right", "Bottom", "Left" ],
+ cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
+
+// return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( style, name ) {
+
+ // shortcut for names that are not vendor prefixed
+ if ( name in style ) {
+ return name;
+ }
+
+ // check for vendor prefixed names
+ var capName = name.charAt(0).toUpperCase() + name.slice(1),
+ origName = name,
+ i = cssPrefixes.length;
+
+ while ( i-- ) {
+ name = cssPrefixes[ i ] + capName;
+ if ( name in style ) {
+ return name;
+ }
+ }
+
+ return origName;
+}
+
+function isHidden( elem, el ) {
+ // isHidden might be called from jQuery#filter function;
+ // in that case, element will be second argument
+ elem = el || elem;
+ return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+}
+
+function showHide( elements, show ) {
+ var display, elem, hidden,
+ values = [],
+ index = 0,
+ length = elements.length;
+
+ for ( ; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+
+ values[ index ] = jQuery._data( elem, "olddisplay" );
+ display = elem.style.display;
+ if ( show ) {
+ // Reset the inline display of this element to learn if it is
+ // being hidden by cascaded rules or not
+ if ( !values[ index ] && display === "none" ) {
+ elem.style.display = "";
+ }
+
+ // Set elements which have been overridden with display: none
+ // in a stylesheet to whatever the default browser style is
+ // for such an element
+ if ( elem.style.display === "" && isHidden( elem ) ) {
+ values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
+ }
+ } else {
+
+ if ( !values[ index ] ) {
+ hidden = isHidden( elem );
+
+ if ( display && display !== "none" || !hidden ) {
+ jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
+ }
+ }
+ }
+ }
+
+ // Set the display of most of the elements in a second loop
+ // to avoid the constant reflow
+ for ( index = 0; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+ if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+ elem.style.display = show ? values[ index ] || "" : "none";
+ }
+ }
+
+ return elements;
+}
+
+jQuery.fn.extend({
+ css: function( name, value ) {
+ return jQuery.access( this, function( elem, name, value ) {
+ var len, styles,
+ map = {},
+ i = 0;
+
+ if ( jQuery.isArray( name ) ) {
+ styles = getStyles( elem );
+ len = name.length;
+
+ for ( ; i < len; i++ ) {
+ map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+ }
+
+ return map;
+ }
+
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ }, name, value, arguments.length > 1 );
+ },
+ show: function() {
+ return showHide( this, true );
+ },
+ hide: function() {
+ return showHide( this );
+ },
+ toggle: function( state ) {
+ var bool = typeof state === "boolean";
+
+ return this.each(function() {
+ if ( bool ? state : isHidden( this ) ) {
+ jQuery( this ).show();
+ } else {
+ jQuery( this ).hide();
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity" );
+ return ret === "" ? "1" : ret;
+ }
+ }
+ }
+ },
+
+ // Exclude the following css properties to add px
+ cssNumber: {
+ "columnCount": true,
+ "fillOpacity": true,
+ "fontWeight": true,
+ "lineHeight": true,
+ "opacity": true,
+ "orphans": true,
+ "widows": true,
+ "zIndex": true,
+ "zoom": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ // normalize float css property
+ "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+ },
+
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
+ }
+
+ // Make sure that we're working with the right name
+ var ret, type, hooks,
+ origName = jQuery.camelCase( name ),
+ style = elem.style;
+
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+
+ // gets hook for the prefixed version
+ // followed by the unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // convert relative number strings (+= or -=) to relative numbers. #7345
+ if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+ value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
+ // Fixes bug #9237
+ type = "number";
+ }
+
+ // Make sure that NaN and null values aren't set. See: #7116
+ if ( value == null || type === "number" && isNaN( value ) ) {
+ return;
+ }
+
+ // If a number was passed in, add 'px' to the (except for certain CSS properties)
+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+ value += "px";
+ }
+
+ // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
+ // but it would mean to define eight (for every problematic property) identical functions
+ if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
+ style[ name ] = "inherit";
+ }
+
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
+
+ // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
+ // Fixes bug #5509
+ try {
+ style[ name ] = value;
+ } catch(e) {}
+ }
+
+ } else {
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+ return ret;
+ }
+
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
+
+ css: function( elem, name, extra, styles ) {
+ var num, val, hooks,
+ origName = jQuery.camelCase( name );
+
+ // Make sure that we're working with the right name
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+
+ // gets hook for the prefixed version
+ // followed by the unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks ) {
+ val = hooks.get( elem, true, extra );
+ }
+
+ // Otherwise, if a way to get the computed value exists, use that
+ if ( val === undefined ) {
+ val = curCSS( elem, name, styles );
+ }
+
+ //convert "normal" to computed value
+ if ( val === "normal" && name in cssNormalTransform ) {
+ val = cssNormalTransform[ name ];
+ }
+
+ // Return, converting to number if forced or a qualifier was provided and val looks numeric
+ if ( extra === "" || extra ) {
+ num = parseFloat( val );
+ return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
+ }
+ return val;
+ },
+
+ // A method for quickly swapping in/out CSS properties to get correct calculations
+ swap: function( elem, options, callback, args ) {
+ var ret, name,
+ old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ ret = callback.apply( elem, args || [] );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+
+ return ret;
+ }
+});
+
+// NOTE: we've included the "window" in window.getComputedStyle
+// because jsdom on node.js will break without it.
+if ( window.getComputedStyle ) {
+ getStyles = function( elem ) {
+ return window.getComputedStyle( elem, null );
+ };
+
+ curCSS = function( elem, name, _computed ) {
+ var width, minWidth, maxWidth,
+ computed = _computed || getStyles( elem ),
+
+ // getPropertyValue is only needed for .css('filter') in IE9, see #12537
+ ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,
+ style = elem.style;
+
+ if ( computed ) {
+
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+
+ // A tribute to the "awesome hack by Dean Edwards"
+ // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
+ // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
+ // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+ if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+ // Remember the original values
+ width = style.width;
+ minWidth = style.minWidth;
+ maxWidth = style.maxWidth;
+
+ // Put in the new values to get a computed value out
+ style.minWidth = style.maxWidth = style.width = ret;
+ ret = computed.width;
+
+ // Revert the changed values
+ style.width = width;
+ style.minWidth = minWidth;
+ style.maxWidth = maxWidth;
+ }
+ }
+
+ return ret;
+ };
+} else if ( document.documentElement.currentStyle ) {
+ getStyles = function( elem ) {
+ return elem.currentStyle;
+ };
+
+ curCSS = function( elem, name, _computed ) {
+ var left, rs, rsLeft,
+ computed = _computed || getStyles( elem ),
+ ret = computed ? computed[ name ] : undefined,
+ style = elem.style;
+
+ // Avoid setting ret to empty string here
+ // so we don't default to auto
+ if ( ret == null && style && style[ name ] ) {
+ ret = style[ name ];
+ }
+
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ // but not position css attributes, as those are proportional to the parent element instead
+ // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
+ if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
+
+ // Remember the original values
+ left = style.left;
+ rs = elem.runtimeStyle;
+ rsLeft = rs && rs.left;
+
+ // Put in the new values to get a computed value out
+ if ( rsLeft ) {
+ rs.left = elem.currentStyle.left;
+ }
+ style.left = name === "fontSize" ? "1em" : ret;
+ ret = style.pixelLeft + "px";
+
+ // Revert the changed values
+ style.left = left;
+ if ( rsLeft ) {
+ rs.left = rsLeft;
+ }
+ }
+
+ return ret === "" ? "auto" : ret;
+ };
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+ var matches = rnumsplit.exec( value );
+ return matches ?
+ // Guard against undefined "subtract", e.g., when used as in cssHooks
+ Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
+ value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+ var i = extra === ( isBorderBox ? "border" : "content" ) ?
+ // If we already have the right measurement, avoid augmentation
+ 4 :
+ // Otherwise initialize for horizontal or vertical properties
+ name === "width" ? 1 : 0,
+
+ val = 0;
+
+ for ( ; i < 4; i += 2 ) {
+ // both box models exclude margin, so add it if we want it
+ if ( extra === "margin" ) {
+ val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+ }
+
+ if ( isBorderBox ) {
+ // border-box includes padding, so remove it if we want content
+ if ( extra === "content" ) {
+ val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+ }
+
+ // at this point, extra isn't border nor margin, so remove border
+ if ( extra !== "margin" ) {
+ val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ } else {
+ // at this point, extra isn't content, so add padding
+ val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+
+ // at this point, extra isn't content nor padding, so add border
+ if ( extra !== "padding" ) {
+ val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ }
+ }
+
+ return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+ // Start with offset property, which is equivalent to the border-box value
+ var valueIsBorderBox = true,
+ val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+ styles = getStyles( elem ),
+ isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+ // some non-html elements return undefined for offsetWidth, so check for null/undefined
+ // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+ // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+ if ( val <= 0 || val == null ) {
+ // Fall back to computed then uncomputed css if necessary
+ val = curCSS( elem, name, styles );
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ];
+ }
+
+ // Computed unit is not pixels. Stop here and return.
+ if ( rnumnonpx.test(val) ) {
+ return val;
+ }
+
+ // we need the check for style in case a browser which returns unreliable values
+ // for getComputedStyle silently falls back to the reliable elem.style
+ valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
+
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+ }
+
+ // use the active box-sizing model to add/subtract irrelevant styles
+ return ( val +
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra || ( isBorderBox ? "border" : "content" ),
+ valueIsBorderBox,
+ styles
+ )
+ ) + "px";
+}
+
+// Try to determine the default display value of an element
+function css_defaultDisplay( nodeName ) {
+ var doc = document,
+ display = elemdisplay[ nodeName ];
+
+ if ( !display ) {
+ display = actualDisplay( nodeName, doc );
+
+ // If the simple way fails, read from inside an iframe
+ if ( display === "none" || !display ) {
+ // Use the already-created iframe if possible
+ iframe = ( iframe ||
+ jQuery("")
+ .css( "cssText", "display:block !important" )
+ ).appendTo( doc.documentElement );
+
+ // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
+ doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;
+ doc.write("");
+ doc.close();
+
+ display = actualDisplay( nodeName, doc );
+ iframe.detach();
+ }
+
+ // Store the correct default display
+ elemdisplay[ nodeName ] = display;
+ }
+
+ return display;
+}
+
+// Called ONLY from within css_defaultDisplay
+function actualDisplay( name, doc ) {
+ var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
+ display = jQuery.css( elem[0], "display" );
+ elem.remove();
+ return display;
+}
+
+jQuery.each([ "height", "width" ], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ if ( computed ) {
+ // certain elements can have dimension info if we invisibly show them
+ // however, it must have a current display style that would benefit from this
+ return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?
+ jQuery.swap( elem, cssShow, function() {
+ return getWidthOrHeight( elem, name, extra );
+ }) :
+ getWidthOrHeight( elem, name, extra );
+ }
+ },
+
+ set: function( elem, value, extra ) {
+ var styles = extra && getStyles( elem );
+ return setPositiveNumber( elem, value, extra ?
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra,
+ jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+ styles
+ ) : 0
+ );
+ }
+ };
+});
+
+if ( !jQuery.support.opacity ) {
+ jQuery.cssHooks.opacity = {
+ get: function( elem, computed ) {
+ // IE uses filters for opacity
+ return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+ ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
+ computed ? "1" : "";
+ },
+
+ set: function( elem, value ) {
+ var style = elem.style,
+ currentStyle = elem.currentStyle,
+ opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+ filter = currentStyle && currentStyle.filter || style.filter || "";
+
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ style.zoom = 1;
+
+ // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+ // if value === "", then remove inline opacity #12685
+ if ( ( value >= 1 || value === "" ) &&
+ jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
+ style.removeAttribute ) {
+
+ // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+ // if "filter:" is present at all, clearType is disabled, we want to avoid this
+ // style.removeAttribute is IE Only, but so apparently is this code path...
+ style.removeAttribute( "filter" );
+
+ // if there is no filter style applied in a css rule or unset inline opacity, we are done
+ if ( value === "" || currentStyle && !currentStyle.filter ) {
+ return;
+ }
+ }
+
+ // otherwise, set new filter values
+ style.filter = ralpha.test( filter ) ?
+ filter.replace( ralpha, opacity ) :
+ filter + " " + opacity;
+ }
+ };
+}
+
+// These hooks cannot be added until DOM ready because the support test
+// for it is not run until after DOM ready
+jQuery(function() {
+ if ( !jQuery.support.reliableMarginRight ) {
+ jQuery.cssHooks.marginRight = {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ // Work around by temporarily setting element display to inline-block
+ return jQuery.swap( elem, { "display": "inline-block" },
+ curCSS, [ elem, "marginRight" ] );
+ }
+ }
+ };
+ }
+
+ // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+ // getComputedStyle returns percent when specified for top/left/bottom/right
+ // rather than make the css module depend on the offset module, we just check for it here
+ if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
+ jQuery.each( [ "top", "left" ], function( i, prop ) {
+ jQuery.cssHooks[ prop ] = {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ computed = curCSS( elem, prop );
+ // if curCSS returns percentage, fallback to offset
+ return rnumnonpx.test( computed ) ?
+ jQuery( elem ).position()[ prop ] + "px" :
+ computed;
+ }
+ }
+ };
+ });
+ }
+
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.hidden = function( elem ) {
+ // Support: Opera <= 12.12
+ // Opera reports offsetWidths and offsetHeights less than zero on some elements
+ return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
+ (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
+ };
+
+ jQuery.expr.filters.visible = function( elem ) {
+ return !jQuery.expr.filters.hidden( elem );
+ };
+}
+
+// These hooks are used by animate to expand properties
+jQuery.each({
+ margin: "",
+ padding: "",
+ border: "Width"
+}, function( prefix, suffix ) {
+ jQuery.cssHooks[ prefix + suffix ] = {
+ expand: function( value ) {
+ var i = 0,
+ expanded = {},
+
+ // assumes a single number if not a string
+ parts = typeof value === "string" ? value.split(" ") : [ value ];
+
+ for ( ; i < 4; i++ ) {
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+ }
+
+ return expanded;
+ }
+ };
+
+ if ( !rmargin.test( prefix ) ) {
+ jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+ }
+});
+var r20 = /%20/g,
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+ rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+jQuery.fn.extend({
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
+ serializeArray: function() {
+ return this.map(function(){
+ // Can add propHook for "elements" to filter or add form elements
+ var elements = jQuery.prop( this, "elements" );
+ return elements ? jQuery.makeArray( elements ) : this;
+ })
+ .filter(function(){
+ var type = this.type;
+ // Use .is(":disabled") so that fieldset[disabled] works
+ return this.name && !jQuery( this ).is( ":disabled" ) &&
+ rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+ ( this.checked || !manipulation_rcheckableType.test( type ) );
+ })
+ .map(function( i, elem ){
+ var val = jQuery( this ).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray( val ) ?
+ jQuery.map( val, function( val ){
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }) :
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }).get();
+ }
+});
+
+//Serialize an array of form elements or a set of
+//key/values into a query string
+jQuery.param = function( a, traditional ) {
+ var prefix,
+ s = [],
+ add = function( key, value ) {
+ // If value is a function, invoke it and return its value
+ value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+ };
+
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
+ if ( traditional === undefined ) {
+ traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+ }
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ });
+
+ } else {
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join( "&" ).replace( r20, "+" );
+};
+
+function buildParams( prefix, obj, traditional, add ) {
+ var name;
+
+ if ( jQuery.isArray( obj ) ) {
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+ // Item is non-scalar (array or object), encode its numeric index.
+ buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+ }
+ });
+
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
+ // Serialize object item.
+ for ( name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ }
+
+ } else {
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+}
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ return arguments.length > 0 ?
+ this.on( name, null, data, fn ) :
+ this.trigger( name );
+ };
+});
+
+jQuery.fn.hover = function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+};
+var
+ // Document location
+ ajaxLocParts,
+ ajaxLocation,
+ ajax_nonce = jQuery.now(),
+
+ ajax_rquery = /\?/,
+ rhash = /#.*$/,
+ rts = /([?&])_=[^&]*/,
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+ // #7653, #8125, #8152: local protocol detection
+ rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rprotocol = /^\/\//,
+ rurl = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
+
+ // Keep a copy of the old load method
+ _load = jQuery.fn.load,
+
+ /* Prefilters
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+ * 2) These are called:
+ * - BEFORE asking for a transport
+ * - AFTER param serialization (s.data is a string if s.processData is true)
+ * 3) key is the dataType
+ * 4) the catchall symbol "*" can be used
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+ */
+ prefilters = {},
+
+ /* Transports bindings
+ * 1) key is the dataType
+ * 2) the catchall symbol "*" can be used
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
+ */
+ transports = {},
+
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+ allTypes = "*/".concat("*");
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+ ajaxLocation = location.href;
+} catch( e ) {
+ // Use the href attribute of an A element
+ // since IE will modify it given document.location
+ ajaxLocation = document.createElement( "a" );
+ ajaxLocation.href = "";
+ ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+ // dataTypeExpression is optional and defaults to "*"
+ return function( dataTypeExpression, func ) {
+
+ if ( typeof dataTypeExpression !== "string" ) {
+ func = dataTypeExpression;
+ dataTypeExpression = "*";
+ }
+
+ var dataType,
+ i = 0,
+ dataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];
+
+ if ( jQuery.isFunction( func ) ) {
+ // For each dataType in the dataTypeExpression
+ while ( (dataType = dataTypes[i++]) ) {
+ // Prepend if requested
+ if ( dataType[0] === "+" ) {
+ dataType = dataType.slice( 1 ) || "*";
+ (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
+
+ // Otherwise append
+ } else {
+ (structure[ dataType ] = structure[ dataType ] || []).push( func );
+ }
+ }
+ }
+ };
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+ var inspected = {},
+ seekingTransport = ( structure === transports );
+
+ function inspect( dataType ) {
+ var selected;
+ inspected[ dataType ] = true;
+ jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+ var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+ if( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+ options.dataTypes.unshift( dataTypeOrTransport );
+ inspect( dataTypeOrTransport );
+ return false;
+ } else if ( seekingTransport ) {
+ return !( selected = dataTypeOrTransport );
+ }
+ });
+ return selected;
+ }
+
+ return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+ var deep, key,
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
+
+ for ( key in src ) {
+ if ( src[ key ] !== undefined ) {
+ ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
+ }
+ }
+ if ( deep ) {
+ jQuery.extend( true, target, deep );
+ }
+
+ return target;
+}
+
+jQuery.fn.load = function( url, params, callback ) {
+ if ( typeof url !== "string" && _load ) {
+ return _load.apply( this, arguments );
+ }
+
+ var selector, response, type,
+ self = this,
+ off = url.indexOf(" ");
+
+ if ( off >= 0 ) {
+ selector = url.slice( off, url.length );
+ url = url.slice( 0, off );
+ }
+
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+
+ // We assume that it's the callback
+ callback = params;
+ params = undefined;
+
+ // Otherwise, build a param string
+ } else if ( params && typeof params === "object" ) {
+ type = "POST";
+ }
+
+ // If we have elements to modify, make the request
+ if ( self.length > 0 ) {
+ jQuery.ajax({
+ url: url,
+
+ // if "type" variable is undefined, then "GET" method will be used
+ type: type,
+ dataType: "html",
+ data: params
+ }).done(function( responseText ) {
+
+ // Save response for use in complete callback
+ response = arguments;
+
+ self.html( selector ?
+
+ // If a selector was specified, locate the right elements in a dummy div
+ // Exclude scripts to avoid IE 'Permission Denied' errors
+ jQuery("").append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+ // Otherwise use the full result
+ responseText );
+
+ }).complete( callback && function( jqXHR, status ) {
+ self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+ });
+ }
+
+ return this;
+};
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
+ jQuery.fn[ type ] = function( fn ){
+ return this.on( type, fn );
+ };
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
+ // shift arguments if data argument was omitted
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = undefined;
+ }
+
+ return jQuery.ajax({
+ url: url,
+ type: method,
+ dataType: type,
+ data: data,
+ success: callback
+ });
+ };
+});
+
+jQuery.extend({
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {},
+
+ ajaxSettings: {
+ url: ajaxLocation,
+ type: "GET",
+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+ global: true,
+ processData: true,
+ async: true,
+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+ /*
+ timeout: 0,
+ data: null,
+ dataType: null,
+ username: null,
+ password: null,
+ cache: null,
+ throws: false,
+ traditional: false,
+ headers: {},
+ */
+
+ accepts: {
+ "*": allTypes,
+ text: "text/plain",
+ html: "text/html",
+ xml: "application/xml, text/xml",
+ json: "application/json, text/javascript"
+ },
+
+ contents: {
+ xml: /xml/,
+ html: /html/,
+ json: /json/
+ },
+
+ responseFields: {
+ xml: "responseXML",
+ text: "responseText"
+ },
+
+ // Data converters
+ // Keys separate source (or catchall "*") and destination types with a single space
+ converters: {
+
+ // Convert anything to text
+ "* text": window.String,
+
+ // Text to html (true = no transformation)
+ "text html": true,
+
+ // Evaluate text as a json expression
+ "text json": jQuery.parseJSON,
+
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ },
+
+ // For options that shouldn't be deep extended:
+ // you can add your own custom options here if
+ // and when you create one that shouldn't be
+ // deep extended (see ajaxExtend)
+ flatOptions: {
+ url: true,
+ context: true
+ }
+ },
+
+ // Creates a full fledged settings object into target
+ // with both ajaxSettings and settings fields.
+ // If target is omitted, writes into ajaxSettings.
+ ajaxSetup: function( target, settings ) {
+ return settings ?
+
+ // Building a settings object
+ ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+ // Extending ajaxSettings
+ ajaxExtend( jQuery.ajaxSettings, target );
+ },
+
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+ // Main method
+ ajax: function( url, options ) {
+
+ // If url is an object, simulate pre-1.5 signature
+ if ( typeof url === "object" ) {
+ options = url;
+ url = undefined;
+ }
+
+ // Force options to be an object
+ options = options || {};
+
+ var // Cross-domain detection vars
+ parts,
+ // Loop variable
+ i,
+ // URL without anti-cache param
+ cacheURL,
+ // Response headers as string
+ responseHeadersString,
+ // timeout handle
+ timeoutTimer,
+
+ // To know if global events are to be dispatched
+ fireGlobals,
+
+ transport,
+ // Response headers
+ responseHeaders,
+ // Create the final options object
+ s = jQuery.ajaxSetup( {}, options ),
+ // Callbacks context
+ callbackContext = s.context || s,
+ // Context for global events is callbackContext if it is a DOM node or jQuery collection
+ globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
+ jQuery( callbackContext ) :
+ jQuery.event,
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery.Callbacks("once memory"),
+ // Status-dependent callbacks
+ statusCode = s.statusCode || {},
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ requestHeadersNames = {},
+ // The jqXHR state
+ state = 0,
+ // Default abort message
+ strAbort = "canceled",
+ // Fake xhr
+ jqXHR = {
+ readyState: 0,
+
+ // Builds headers hashtable if needed
+ getResponseHeader: function( key ) {
+ var match;
+ if ( state === 2 ) {
+ if ( !responseHeaders ) {
+ responseHeaders = {};
+ while ( (match = rheaders.exec( responseHeadersString )) ) {
+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ match = responseHeaders[ key.toLowerCase() ];
+ }
+ return match == null ? null : match;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return state === 2 ? responseHeadersString : null;
+ },
+
+ // Caches the header
+ setRequestHeader: function( name, value ) {
+ var lname = name.toLowerCase();
+ if ( !state ) {
+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+ requestHeaders[ name ] = value;
+ }
+ return this;
+ },
+
+ // Overrides response content-type header
+ overrideMimeType: function( type ) {
+ if ( !state ) {
+ s.mimeType = type;
+ }
+ return this;
+ },
+
+ // Status-dependent callbacks
+ statusCode: function( map ) {
+ var code;
+ if ( map ) {
+ if ( state < 2 ) {
+ for ( code in map ) {
+ // Lazy-add the new callback in a way that preserves old ones
+ statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+ }
+ } else {
+ // Execute the appropriate callbacks
+ jqXHR.always( map[ jqXHR.status ] );
+ }
+ }
+ return this;
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ var finalText = statusText || strAbort;
+ if ( transport ) {
+ transport.abort( finalText );
+ }
+ done( 0, finalText );
+ return this;
+ }
+ };
+
+ // Attach deferreds
+ deferred.promise( jqXHR ).complete = completeDeferred.add;
+ jqXHR.success = jqXHR.done;
+ jqXHR.error = jqXHR.fail;
+
+ // Remove hash character (#7531: and string promotion)
+ // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+ // Handle falsy url in the settings object (#10093: consistency with old signature)
+ // We also use the url parameter if available
+ s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+ // Alias method option to type as per ticket #12004
+ s.type = options.method || options.type || s.method || s.type;
+
+ // Extract dataTypes list
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""];
+
+ // A cross-domain request is in order when we have a protocol:host:port mismatch
+ if ( s.crossDomain == null ) {
+ parts = rurl.exec( s.url.toLowerCase() );
+ s.crossDomain = !!( parts &&
+ ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
+ );
+ }
+
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+ // If request was aborted inside a prefilter, stop there
+ if ( state === 2 ) {
+ return jqXHR;
+ }
+
+ // We can fire global events as of now if asked to
+ fireGlobals = s.global;
+
+ // Watch for a new set of requests
+ if ( fireGlobals && jQuery.active++ === 0 ) {
+ jQuery.event.trigger("ajaxStart");
+ }
+
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
+
+ // Determine if request has content
+ s.hasContent = !rnoContent.test( s.type );
+
+ // Save the URL in case we're toying with the If-Modified-Since
+ // and/or If-None-Match header later on
+ cacheURL = s.url;
+
+ // More options handling for requests with no content
+ if ( !s.hasContent ) {
+
+ // If data is available, append data to url
+ if ( s.data ) {
+ cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
+ // #9682: remove data so that it's not used in an eventual retry
+ delete s.data;
+ }
+
+ // Add anti-cache in url if needed
+ if ( s.cache === false ) {
+ s.url = rts.test( cacheURL ) ?
+
+ // If there is already a '_' parameter, set its value
+ cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) :
+
+ // Otherwise add one to the end
+ cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++;
+ }
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ if ( jQuery.lastModified[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+ }
+ if ( jQuery.etag[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+ }
+ }
+
+ // Set the correct header, if data is being sent
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ jqXHR.setRequestHeader(
+ "Accept",
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.accepts[ "*" ]
+ );
+
+ // Check for headers option
+ for ( i in s.headers ) {
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
+ }
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+ // Abort if not done already and return
+ return jqXHR.abort();
+ }
+
+ // aborting is no longer a cancellation
+ strAbort = "abort";
+
+ // Install callbacks on deferreds
+ for ( i in { success: 1, error: 1, complete: 1 } ) {
+ jqXHR[ i ]( s[ i ] );
+ }
+
+ // Get transport
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+ // If no transport, we auto-abort
+ if ( !transport ) {
+ done( -1, "No Transport" );
+ } else {
+ jqXHR.readyState = 1;
+
+ // Send global event
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+ }
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = setTimeout(function() {
+ jqXHR.abort("timeout");
+ }, s.timeout );
+ }
+
+ try {
+ state = 1;
+ transport.send( requestHeaders, done );
+ } catch ( e ) {
+ // Propagate exception as error if not done
+ if ( state < 2 ) {
+ done( -1, e );
+ // Simply rethrow otherwise
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ // Callback for when everything is done
+ function done( status, nativeStatusText, responses, headers ) {
+ var isSuccess, success, error, response, modified,
+ statusText = nativeStatusText;
+
+ // Called once
+ if ( state === 2 ) {
+ return;
+ }
+
+ // State is "done" now
+ state = 2;
+
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ clearTimeout( timeoutTimer );
+ }
+
+ // Dereference transport for early garbage collection
+ // (no matter how long the jqXHR object will be used)
+ transport = undefined;
+
+ // Cache response headers
+ responseHeadersString = headers || "";
+
+ // Set readyState
+ jqXHR.readyState = status > 0 ? 4 : 0;
+
+ // Get response data
+ if ( responses ) {
+ response = ajaxHandleResponses( s, jqXHR, responses );
+ }
+
+ // If successful, handle type chaining
+ if ( status >= 200 && status < 300 || status === 304 ) {
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ modified = jqXHR.getResponseHeader("Last-Modified");
+ if ( modified ) {
+ jQuery.lastModified[ cacheURL ] = modified;
+ }
+ modified = jqXHR.getResponseHeader("etag");
+ if ( modified ) {
+ jQuery.etag[ cacheURL ] = modified;
+ }
+ }
+
+ // if no content
+ if ( status === 204 ) {
+ isSuccess = true;
+ statusText = "nocontent";
+
+ // if not modified
+ } else if ( status === 304 ) {
+ isSuccess = true;
+ statusText = "notmodified";
+
+ // If we have data, let's convert it
+ } else {
+ isSuccess = ajaxConvert( s, response );
+ statusText = isSuccess.state;
+ success = isSuccess.data;
+ error = isSuccess.error;
+ isSuccess = !error;
+ }
+ } else {
+ // We extract error from statusText
+ // then normalize statusText and status for non-aborts
+ error = statusText;
+ if ( status || !statusText ) {
+ statusText = "error";
+ if ( status < 0 ) {
+ status = 0;
+ }
+ }
+ }
+
+ // Set data for the fake xhr object
+ jqXHR.status = status;
+ jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+ } else {
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+ }
+
+ // Status-dependent callbacks
+ jqXHR.statusCode( statusCode );
+ statusCode = undefined;
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+ [ jqXHR, s, isSuccess ? success : error ] );
+ }
+
+ // Complete
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+ // Handle the global AJAX counter
+ if ( !( --jQuery.active ) ) {
+ jQuery.event.trigger("ajaxStop");
+ }
+ }
+ }
+
+ return jqXHR;
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get( url, undefined, callback, "script" );
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get( url, data, callback, "json" );
+ }
+});
+
+/* Handles responses to an ajax request:
+ * - sets all responseXXX fields accordingly
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+ var firstDataType, ct, finalDataType, type,
+ contents = s.contents,
+ dataTypes = s.dataTypes,
+ responseFields = s.responseFields;
+
+ // Fill responseXXX fields
+ for ( type in responseFields ) {
+ if ( type in responses ) {
+ jqXHR[ responseFields[type] ] = responses[ type ];
+ }
+ }
+
+ // Remove auto dataType and get content-type in the process
+ while( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
+ }
+ }
+
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
+ }
+ }
+ }
+
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
+ }
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
+ }
+
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
+ }
+}
+
+// Chain conversions given the request and the original response
+function ajaxConvert( s, response ) {
+ var conv2, current, conv, tmp,
+ converters = {},
+ i = 0,
+ // Work with a copy of dataTypes in case we need to modify it for conversion
+ dataTypes = s.dataTypes.slice(),
+ prev = dataTypes[ 0 ];
+
+ // Apply the dataFilter if provided
+ if ( s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
+
+ // Create converters map with lowercased keys
+ if ( dataTypes[ 1 ] ) {
+ for ( conv in s.converters ) {
+ converters[ conv.toLowerCase() ] = s.converters[ conv ];
+ }
+ }
+
+ // Convert to each sequential dataType, tolerating list modification
+ for ( ; (current = dataTypes[++i]); ) {
+
+ // There's only work to do if current dataType is non-auto
+ if ( current !== "*" ) {
+
+ // Convert response if prev dataType is non-auto and differs from current
+ if ( prev !== "*" && prev !== current ) {
+
+ // Seek a direct converter
+ conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+ // If none found, seek a pair
+ if ( !conv ) {
+ for ( conv2 in converters ) {
+
+ // If conv2 outputs current
+ tmp = conv2.split(" ");
+ if ( tmp[ 1 ] === current ) {
+
+ // If prev can be converted to accepted input
+ conv = converters[ prev + " " + tmp[ 0 ] ] ||
+ converters[ "* " + tmp[ 0 ] ];
+ if ( conv ) {
+ // Condense equivalence converters
+ if ( conv === true ) {
+ conv = converters[ conv2 ];
+
+ // Otherwise, insert the intermediate dataType
+ } else if ( converters[ conv2 ] !== true ) {
+ current = tmp[ 0 ];
+ dataTypes.splice( i--, 0, current );
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ // Apply converter (if not an equivalence)
+ if ( conv !== true ) {
+
+ // Unless errors are allowed to bubble, catch and return them
+ if ( conv && s["throws"] ) {
+ response = conv( response );
+ } else {
+ try {
+ response = conv( response );
+ } catch ( e ) {
+ return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
+ }
+ }
+ }
+ }
+
+ // Update prev for next iteration
+ prev = current;
+ }
+ }
+
+ return { state: "success", data: response };
+}
+// Install script dataType
+jQuery.ajaxSetup({
+ accepts: {
+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+ },
+ contents: {
+ script: /(?:java|ecma)script/
+ },
+ converters: {
+ "text script": function( text ) {
+ jQuery.globalEval( text );
+ return text;
+ }
+ }
+});
+
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+ if ( s.cache === undefined ) {
+ s.cache = false;
+ }
+ if ( s.crossDomain ) {
+ s.type = "GET";
+ s.global = false;
+ }
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
+
+ // This transport only deals with cross domain requests
+ if ( s.crossDomain ) {
+
+ var script,
+ head = document.head || jQuery("head")[0] || document.documentElement;
+
+ return {
+
+ send: function( _, callback ) {
+
+ script = document.createElement("script");
+
+ script.async = true;
+
+ if ( s.scriptCharset ) {
+ script.charset = s.scriptCharset;
+ }
+
+ script.src = s.url;
+
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+ if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+ // Handle memory leak in IE
+ script.onload = script.onreadystatechange = null;
+
+ // Remove the script
+ if ( script.parentNode ) {
+ script.parentNode.removeChild( script );
+ }
+
+ // Dereference the script
+ script = null;
+
+ // Callback if not abort
+ if ( !isAbort ) {
+ callback( 200, "success" );
+ }
+ }
+ };
+
+ // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
+ // Use native DOM manipulation to avoid our domManip AJAX trickery
+ head.insertBefore( script, head.firstChild );
+ },
+
+ abort: function() {
+ if ( script ) {
+ script.onload( undefined, true );
+ }
+ }
+ };
+ }
+});
+var oldCallbacks = [],
+ rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+ jsonp: "callback",
+ jsonpCallback: function() {
+ var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
+ this[ callback ] = true;
+ return callback;
+ }
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+ var callbackName, overwritten, responseContainer,
+ jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+ "url" :
+ typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
+ );
+
+ // Handle iff the expected data type is "jsonp" or we have a parameter to set
+ if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+ // Get callback name, remembering preexisting value associated with it
+ callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+ s.jsonpCallback() :
+ s.jsonpCallback;
+
+ // Insert callback into url or form data
+ if ( jsonProp ) {
+ s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+ } else if ( s.jsonp !== false ) {
+ s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+ }
+
+ // Use data converter to retrieve json after script execution
+ s.converters["script json"] = function() {
+ if ( !responseContainer ) {
+ jQuery.error( callbackName + " was not called" );
+ }
+ return responseContainer[ 0 ];
+ };
+
+ // force json dataType
+ s.dataTypes[ 0 ] = "json";
+
+ // Install callback
+ overwritten = window[ callbackName ];
+ window[ callbackName ] = function() {
+ responseContainer = arguments;
+ };
+
+ // Clean-up function (fires after converters)
+ jqXHR.always(function() {
+ // Restore preexisting value
+ window[ callbackName ] = overwritten;
+
+ // Save back as free
+ if ( s[ callbackName ] ) {
+ // make sure that re-using the options doesn't screw things around
+ s.jsonpCallback = originalSettings.jsonpCallback;
+
+ // save the callback name for future use
+ oldCallbacks.push( callbackName );
+ }
+
+ // Call if it was a function and we have a response
+ if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+ overwritten( responseContainer[ 0 ] );
+ }
+
+ responseContainer = overwritten = undefined;
+ });
+
+ // Delegate to script
+ return "script";
+ }
+});
+var xhrCallbacks, xhrSupported,
+ xhrId = 0,
+ // #5280: Internet Explorer will keep connections alive if we don't abort on unload
+ xhrOnUnloadAbort = window.ActiveXObject && function() {
+ // Abort all pending requests
+ var key;
+ for ( key in xhrCallbacks ) {
+ xhrCallbacks[ key ]( undefined, true );
+ }
+ };
+
+// Functions to create xhrs
+function createStandardXHR() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch( e ) {}
+}
+
+function createActiveXHR() {
+ try {
+ return new window.ActiveXObject("Microsoft.XMLHTTP");
+ } catch( e ) {}
+}
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+jQuery.ajaxSettings.xhr = window.ActiveXObject ?
+ /* Microsoft failed to properly
+ * implement the XMLHttpRequest in IE7 (can't request local files),
+ * so we use the ActiveXObject when it is available
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+ * we need a fallback.
+ */
+ function() {
+ return !this.isLocal && createStandardXHR() || createActiveXHR();
+ } :
+ // For all other browsers, use the standard XMLHttpRequest object
+ createStandardXHR;
+
+// Determine support properties
+xhrSupported = jQuery.ajaxSettings.xhr();
+jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+xhrSupported = jQuery.support.ajax = !!xhrSupported;
+
+// Create transport if the browser can provide an xhr
+if ( xhrSupported ) {
+
+ jQuery.ajaxTransport(function( s ) {
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( !s.crossDomain || jQuery.support.cors ) {
+
+ var callback;
+
+ return {
+ send: function( headers, complete ) {
+
+ // Get a new xhr
+ var handle, i,
+ xhr = s.xhr();
+
+ // Open the socket
+ // Passing null username, generates a login popup on Opera (#2865)
+ if ( s.username ) {
+ xhr.open( s.type, s.url, s.async, s.username, s.password );
+ } else {
+ xhr.open( s.type, s.url, s.async );
+ }
+
+ // Apply custom fields if provided
+ if ( s.xhrFields ) {
+ for ( i in s.xhrFields ) {
+ xhr[ i ] = s.xhrFields[ i ];
+ }
+ }
+
+ // Override mime type if needed
+ if ( s.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( s.mimeType );
+ }
+
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !s.crossDomain && !headers["X-Requested-With"] ) {
+ headers["X-Requested-With"] = "XMLHttpRequest";
+ }
+
+ // Need an extra try/catch for cross domain requests in Firefox 3
+ try {
+ for ( i in headers ) {
+ xhr.setRequestHeader( i, headers[ i ] );
+ }
+ } catch( err ) {}
+
+ // Do send the request
+ // This may raise an exception which is actually
+ // handled in jQuery.ajax (so no try/catch here)
+ xhr.send( ( s.hasContent && s.data ) || null );
+
+ // Listener
+ callback = function( _, isAbort ) {
+ var status, responseHeaders, statusText, responses;
+
+ // Firefox throws exceptions when accessing properties
+ // of an xhr when a network error occurred
+ // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
+ try {
+
+ // Was never called and is aborted or complete
+ if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+
+ // Only called once
+ callback = undefined;
+
+ // Do not keep as active anymore
+ if ( handle ) {
+ xhr.onreadystatechange = jQuery.noop;
+ if ( xhrOnUnloadAbort ) {
+ delete xhrCallbacks[ handle ];
+ }
+ }
+
+ // If it's an abort
+ if ( isAbort ) {
+ // Abort it manually if needed
+ if ( xhr.readyState !== 4 ) {
+ xhr.abort();
+ }
+ } else {
+ responses = {};
+ status = xhr.status;
+ responseHeaders = xhr.getAllResponseHeaders();
+
+ // When requesting binary data, IE6-9 will throw an exception
+ // on any attempt to access responseText (#11426)
+ if ( typeof xhr.responseText === "string" ) {
+ responses.text = xhr.responseText;
+ }
+
+ // Firefox throws an exception when accessing
+ // statusText for faulty cross-domain requests
+ try {
+ statusText = xhr.statusText;
+ } catch( e ) {
+ // We normalize with Webkit giving an empty statusText
+ statusText = "";
+ }
+
+ // Filter status for non standard behaviors
+
+ // If the request is local and we have data: assume a success
+ // (success with no data won't get notified, that's the best we
+ // can do given current implementations)
+ if ( !status && s.isLocal && !s.crossDomain ) {
+ status = responses.text ? 200 : 404;
+ // IE - #1450: sometimes returns 1223 when it should be 204
+ } else if ( status === 1223 ) {
+ status = 204;
+ }
+ }
+ }
+ } catch( firefoxAccessException ) {
+ if ( !isAbort ) {
+ complete( -1, firefoxAccessException );
+ }
+ }
+
+ // Call complete if needed
+ if ( responses ) {
+ complete( status, statusText, responses, responseHeaders );
+ }
+ };
+
+ if ( !s.async ) {
+ // if we're in sync mode we fire the callback
+ callback();
+ } else if ( xhr.readyState === 4 ) {
+ // (IE6 & IE7) if it's in cache and has been
+ // retrieved directly we need to fire the callback
+ setTimeout( callback );
+ } else {
+ handle = ++xhrId;
+ if ( xhrOnUnloadAbort ) {
+ // Create the active xhrs callbacks list if needed
+ // and attach the unload handler
+ if ( !xhrCallbacks ) {
+ xhrCallbacks = {};
+ jQuery( window ).unload( xhrOnUnloadAbort );
+ }
+ // Add to list of active xhrs callbacks
+ xhrCallbacks[ handle ] = callback;
+ }
+ xhr.onreadystatechange = callback;
+ }
+ },
+
+ abort: function() {
+ if ( callback ) {
+ callback( undefined, true );
+ }
+ }
+ };
+ }
+ });
+}
+var fxNow, timerId,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
+ rrun = /queueHooks$/,
+ animationPrefilters = [ defaultPrefilter ],
+ tweeners = {
+ "*": [function( prop, value ) {
+ var end, unit,
+ tween = this.createTween( prop, value ),
+ parts = rfxnum.exec( value ),
+ target = tween.cur(),
+ start = +target || 0,
+ scale = 1,
+ maxIterations = 20;
+
+ if ( parts ) {
+ end = +parts[2];
+ unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+
+ // We need to compute starting value
+ if ( unit !== "px" && start ) {
+ // Iteratively approximate from a nonzero starting point
+ // Prefer the current property, because this process will be trivial if it uses the same units
+ // Fallback to end or a simple constant
+ start = jQuery.css( tween.elem, prop, true ) || end || 1;
+
+ do {
+ // If previous iteration zeroed out, double until we get *something*
+ // Use a string for doubling factor so we don't accidentally see scale as unchanged below
+ scale = scale || ".5";
+
+ // Adjust and apply
+ start = start / scale;
+ jQuery.style( tween.elem, prop, start + unit );
+
+ // Update scale, tolerating zero or NaN from tween.cur()
+ // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
+ } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
+ }
+
+ tween.unit = unit;
+ tween.start = start;
+ // If a +=/-= token was provided, we're doing a relative animation
+ tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
+ }
+ return tween;
+ }]
+ };
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+ setTimeout(function() {
+ fxNow = undefined;
+ });
+ return ( fxNow = jQuery.now() );
+}
+
+function createTweens( animation, props ) {
+ jQuery.each( props, function( prop, value ) {
+ var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
+ index = 0,
+ length = collection.length;
+ for ( ; index < length; index++ ) {
+ if ( collection[ index ].call( animation, prop, value ) ) {
+
+ // we're done with this property
+ return;
+ }
+ }
+ });
+}
+
+function Animation( elem, properties, options ) {
+ var result,
+ stopped,
+ index = 0,
+ length = animationPrefilters.length,
+ deferred = jQuery.Deferred().always( function() {
+ // don't match elem in the :animated selector
+ delete tick.elem;
+ }),
+ tick = function() {
+ if ( stopped ) {
+ return false;
+ }
+ var currentTime = fxNow || createFxNow(),
+ remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+ // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
+ temp = remaining / animation.duration || 0,
+ percent = 1 - temp,
+ index = 0,
+ length = animation.tweens.length;
+
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( percent );
+ }
+
+ deferred.notifyWith( elem, [ animation, percent, remaining ]);
+
+ if ( percent < 1 && length ) {
+ return remaining;
+ } else {
+ deferred.resolveWith( elem, [ animation ] );
+ return false;
+ }
+ },
+ animation = deferred.promise({
+ elem: elem,
+ props: jQuery.extend( {}, properties ),
+ opts: jQuery.extend( true, { specialEasing: {} }, options ),
+ originalProperties: properties,
+ originalOptions: options,
+ startTime: fxNow || createFxNow(),
+ duration: options.duration,
+ tweens: [],
+ createTween: function( prop, end ) {
+ var tween = jQuery.Tween( elem, animation.opts, prop, end,
+ animation.opts.specialEasing[ prop ] || animation.opts.easing );
+ animation.tweens.push( tween );
+ return tween;
+ },
+ stop: function( gotoEnd ) {
+ var index = 0,
+ // if we are going to the end, we want to run all the tweens
+ // otherwise we skip this part
+ length = gotoEnd ? animation.tweens.length : 0;
+ if ( stopped ) {
+ return this;
+ }
+ stopped = true;
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( 1 );
+ }
+
+ // resolve when we played the last frame
+ // otherwise, reject
+ if ( gotoEnd ) {
+ deferred.resolveWith( elem, [ animation, gotoEnd ] );
+ } else {
+ deferred.rejectWith( elem, [ animation, gotoEnd ] );
+ }
+ return this;
+ }
+ }),
+ props = animation.props;
+
+ propFilter( props, animation.opts.specialEasing );
+
+ for ( ; index < length ; index++ ) {
+ result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
+ if ( result ) {
+ return result;
+ }
+ }
+
+ createTweens( animation, props );
+
+ if ( jQuery.isFunction( animation.opts.start ) ) {
+ animation.opts.start.call( elem, animation );
+ }
+
+ jQuery.fx.timer(
+ jQuery.extend( tick, {
+ elem: elem,
+ anim: animation,
+ queue: animation.opts.queue
+ })
+ );
+
+ // attach callbacks from options
+ return animation.progress( animation.opts.progress )
+ .done( animation.opts.done, animation.opts.complete )
+ .fail( animation.opts.fail )
+ .always( animation.opts.always );
+}
+
+function propFilter( props, specialEasing ) {
+ var value, name, index, easing, hooks;
+
+ // camelCase, specialEasing and expand cssHook pass
+ for ( index in props ) {
+ name = jQuery.camelCase( index );
+ easing = specialEasing[ name ];
+ value = props[ index ];
+ if ( jQuery.isArray( value ) ) {
+ easing = value[ 1 ];
+ value = props[ index ] = value[ 0 ];
+ }
+
+ if ( index !== name ) {
+ props[ name ] = value;
+ delete props[ index ];
+ }
+
+ hooks = jQuery.cssHooks[ name ];
+ if ( hooks && "expand" in hooks ) {
+ value = hooks.expand( value );
+ delete props[ name ];
+
+ // not quite $.extend, this wont overwrite keys already present.
+ // also - reusing 'index' from above because we have the correct "name"
+ for ( index in value ) {
+ if ( !( index in props ) ) {
+ props[ index ] = value[ index ];
+ specialEasing[ index ] = easing;
+ }
+ }
+ } else {
+ specialEasing[ name ] = easing;
+ }
+ }
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+
+ tweener: function( props, callback ) {
+ if ( jQuery.isFunction( props ) ) {
+ callback = props;
+ props = [ "*" ];
+ } else {
+ props = props.split(" ");
+ }
+
+ var prop,
+ index = 0,
+ length = props.length;
+
+ for ( ; index < length ; index++ ) {
+ prop = props[ index ];
+ tweeners[ prop ] = tweeners[ prop ] || [];
+ tweeners[ prop ].unshift( callback );
+ }
+ },
+
+ prefilter: function( callback, prepend ) {
+ if ( prepend ) {
+ animationPrefilters.unshift( callback );
+ } else {
+ animationPrefilters.push( callback );
+ }
+ }
+});
+
+function defaultPrefilter( elem, props, opts ) {
+ /*jshint validthis:true */
+ var prop, index, length,
+ value, dataShow, toggle,
+ tween, hooks, oldfire,
+ anim = this,
+ style = elem.style,
+ orig = {},
+ handled = [],
+ hidden = elem.nodeType && isHidden( elem );
+
+ // handle queue: false promises
+ if ( !opts.queue ) {
+ hooks = jQuery._queueHooks( elem, "fx" );
+ if ( hooks.unqueued == null ) {
+ hooks.unqueued = 0;
+ oldfire = hooks.empty.fire;
+ hooks.empty.fire = function() {
+ if ( !hooks.unqueued ) {
+ oldfire();
+ }
+ };
+ }
+ hooks.unqueued++;
+
+ anim.always(function() {
+ // doing this makes sure that the complete handler will be called
+ // before this completes
+ anim.always(function() {
+ hooks.unqueued--;
+ if ( !jQuery.queue( elem, "fx" ).length ) {
+ hooks.empty.fire();
+ }
+ });
+ });
+ }
+
+ // height/width overflow pass
+ if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+ // Make sure that nothing sneaks out
+ // Record all 3 overflow attributes because IE does not
+ // change the overflow attribute when overflowX and
+ // overflowY are set to the same value
+ opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+ // Set display property to inline-block for height/width
+ // animations on inline elements that are having width/height animated
+ if ( jQuery.css( elem, "display" ) === "inline" &&
+ jQuery.css( elem, "float" ) === "none" ) {
+
+ // inline-level elements accept inline-block;
+ // block-level elements need to be inline with layout
+ if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
+ style.display = "inline-block";
+
+ } else {
+ style.zoom = 1;
+ }
+ }
+ }
+
+ if ( opts.overflow ) {
+ style.overflow = "hidden";
+ if ( !jQuery.support.shrinkWrapBlocks ) {
+ anim.always(function() {
+ style.overflow = opts.overflow[ 0 ];
+ style.overflowX = opts.overflow[ 1 ];
+ style.overflowY = opts.overflow[ 2 ];
+ });
+ }
+ }
+
+
+ // show/hide pass
+ for ( index in props ) {
+ value = props[ index ];
+ if ( rfxtypes.exec( value ) ) {
+ delete props[ index ];
+ toggle = toggle || value === "toggle";
+ if ( value === ( hidden ? "hide" : "show" ) ) {
+ continue;
+ }
+ handled.push( index );
+ }
+ }
+
+ length = handled.length;
+ if ( length ) {
+ dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
+ if ( "hidden" in dataShow ) {
+ hidden = dataShow.hidden;
+ }
+
+ // store state if its toggle - enables .stop().toggle() to "reverse"
+ if ( toggle ) {
+ dataShow.hidden = !hidden;
+ }
+ if ( hidden ) {
+ jQuery( elem ).show();
+ } else {
+ anim.done(function() {
+ jQuery( elem ).hide();
+ });
+ }
+ anim.done(function() {
+ var prop;
+ jQuery._removeData( elem, "fxshow" );
+ for ( prop in orig ) {
+ jQuery.style( elem, prop, orig[ prop ] );
+ }
+ });
+ for ( index = 0 ; index < length ; index++ ) {
+ prop = handled[ index ];
+ tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
+ orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
+
+ if ( !( prop in dataShow ) ) {
+ dataShow[ prop ] = tween.start;
+ if ( hidden ) {
+ tween.end = tween.start;
+ tween.start = prop === "width" || prop === "height" ? 1 : 0;
+ }
+ }
+ }
+ }
+}
+
+function Tween( elem, options, prop, end, easing ) {
+ return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+ constructor: Tween,
+ init: function( elem, options, prop, end, easing, unit ) {
+ this.elem = elem;
+ this.prop = prop;
+ this.easing = easing || "swing";
+ this.options = options;
+ this.start = this.now = this.cur();
+ this.end = end;
+ this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+ },
+ cur: function() {
+ var hooks = Tween.propHooks[ this.prop ];
+
+ return hooks && hooks.get ?
+ hooks.get( this ) :
+ Tween.propHooks._default.get( this );
+ },
+ run: function( percent ) {
+ var eased,
+ hooks = Tween.propHooks[ this.prop ];
+
+ if ( this.options.duration ) {
+ this.pos = eased = jQuery.easing[ this.easing ](
+ percent, this.options.duration * percent, 0, 1, this.options.duration
+ );
+ } else {
+ this.pos = eased = percent;
+ }
+ this.now = ( this.end - this.start ) * eased + this.start;
+
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ if ( hooks && hooks.set ) {
+ hooks.set( this );
+ } else {
+ Tween.propHooks._default.set( this );
+ }
+ return this;
+ }
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+ _default: {
+ get: function( tween ) {
+ var result;
+
+ if ( tween.elem[ tween.prop ] != null &&
+ (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
+ return tween.elem[ tween.prop ];
+ }
+
+ // passing an empty string as a 3rd parameter to .css will automatically
+ // attempt a parseFloat and fallback to a string if the parse fails
+ // so, simple values such as "10px" are parsed to Float.
+ // complex values such as "rotate(1rad)" are returned as is.
+ result = jQuery.css( tween.elem, tween.prop, "" );
+ // Empty strings, null, undefined and "auto" are converted to 0.
+ return !result || result === "auto" ? 0 : result;
+ },
+ set: function( tween ) {
+ // use step hook for back compat - use cssHook if its there - use .style if its
+ // available and use plain properties where available
+ if ( jQuery.fx.step[ tween.prop ] ) {
+ jQuery.fx.step[ tween.prop ]( tween );
+ } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
+ jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+ } else {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+ }
+};
+
+// Remove in 2.0 - this supports IE8's panic based approach
+// to setting things on disconnected nodes
+
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+ set: function( tween ) {
+ if ( tween.elem.nodeType && tween.elem.parentNode ) {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+};
+
+jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
+ var cssFn = jQuery.fn[ name ];
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return speed == null || typeof speed === "boolean" ?
+ cssFn.apply( this, arguments ) :
+ this.animate( genFx( name, true ), speed, easing, callback );
+ };
+});
+
+jQuery.fn.extend({
+ fadeTo: function( speed, to, easing, callback ) {
+
+ // show any hidden elements after setting opacity to 0
+ return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+ // animate to the value specified
+ .end().animate({ opacity: to }, speed, easing, callback );
+ },
+ animate: function( prop, speed, easing, callback ) {
+ var empty = jQuery.isEmptyObject( prop ),
+ optall = jQuery.speed( speed, easing, callback ),
+ doAnimation = function() {
+ // Operate on a copy of prop so per-property easing won't be lost
+ var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+ doAnimation.finish = function() {
+ anim.stop( true );
+ };
+ // Empty animations, or finishing resolves immediately
+ if ( empty || jQuery._data( this, "finish" ) ) {
+ anim.stop( true );
+ }
+ };
+ doAnimation.finish = doAnimation;
+
+ return empty || optall.queue === false ?
+ this.each( doAnimation ) :
+ this.queue( optall.queue, doAnimation );
+ },
+ stop: function( type, clearQueue, gotoEnd ) {
+ var stopQueue = function( hooks ) {
+ var stop = hooks.stop;
+ delete hooks.stop;
+ stop( gotoEnd );
+ };
+
+ if ( typeof type !== "string" ) {
+ gotoEnd = clearQueue;
+ clearQueue = type;
+ type = undefined;
+ }
+ if ( clearQueue && type !== false ) {
+ this.queue( type || "fx", [] );
+ }
+
+ return this.each(function() {
+ var dequeue = true,
+ index = type != null && type + "queueHooks",
+ timers = jQuery.timers,
+ data = jQuery._data( this );
+
+ if ( index ) {
+ if ( data[ index ] && data[ index ].stop ) {
+ stopQueue( data[ index ] );
+ }
+ } else {
+ for ( index in data ) {
+ if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+ stopQueue( data[ index ] );
+ }
+ }
+ }
+
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+ timers[ index ].anim.stop( gotoEnd );
+ dequeue = false;
+ timers.splice( index, 1 );
+ }
+ }
+
+ // start the next in the queue if the last step wasn't forced
+ // timers currently will call their complete callbacks, which will dequeue
+ // but only if they were gotoEnd
+ if ( dequeue || !gotoEnd ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ finish: function( type ) {
+ if ( type !== false ) {
+ type = type || "fx";
+ }
+ return this.each(function() {
+ var index,
+ data = jQuery._data( this ),
+ queue = data[ type + "queue" ],
+ hooks = data[ type + "queueHooks" ],
+ timers = jQuery.timers,
+ length = queue ? queue.length : 0;
+
+ // enable finishing flag on private data
+ data.finish = true;
+
+ // empty the queue first
+ jQuery.queue( this, type, [] );
+
+ if ( hooks && hooks.cur && hooks.cur.finish ) {
+ hooks.cur.finish.call( this );
+ }
+
+ // look for any active animations, and finish them
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+ timers[ index ].anim.stop( true );
+ timers.splice( index, 1 );
+ }
+ }
+
+ // look for any animations in the old queue and finish them
+ for ( index = 0; index < length; index++ ) {
+ if ( queue[ index ] && queue[ index ].finish ) {
+ queue[ index ].finish.call( this );
+ }
+ }
+
+ // turn off finishing flag
+ delete data.finish;
+ });
+ }
+});
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+ var which,
+ attrs = { height: type },
+ i = 0;
+
+ // if we include width, step value is 1 to do all cssExpand values,
+ // if we don't include width, step value is 2 to skip over Left and Right
+ includeWidth = includeWidth? 1 : 0;
+ for( ; i < 4 ; i += 2 - includeWidth ) {
+ which = cssExpand[ i ];
+ attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+ }
+
+ if ( includeWidth ) {
+ attrs.opacity = attrs.width = type;
+ }
+
+ return attrs;
+}
+
+// Generate shortcuts for custom animations
+jQuery.each({
+ slideDown: genFx("show"),
+ slideUp: genFx("hide"),
+ slideToggle: genFx("toggle"),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+});
+
+jQuery.speed = function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+ // normalize opt.queue - true/undefined/null -> "fx"
+ if ( opt.queue == null || opt.queue === true ) {
+ opt.queue = "fx";
+ }
+
+ // Queueing
+ opt.old = opt.complete;
+
+ opt.complete = function() {
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+
+ if ( opt.queue ) {
+ jQuery.dequeue( this, opt.queue );
+ }
+ };
+
+ return opt;
+};
+
+jQuery.easing = {
+ linear: function( p ) {
+ return p;
+ },
+ swing: function( p ) {
+ return 0.5 - Math.cos( p*Math.PI ) / 2;
+ }
+};
+
+jQuery.timers = [];
+jQuery.fx = Tween.prototype.init;
+jQuery.fx.tick = function() {
+ var timer,
+ timers = jQuery.timers,
+ i = 0;
+
+ fxNow = jQuery.now();
+
+ for ( ; i < timers.length; i++ ) {
+ timer = timers[ i ];
+ // Checks the timer has not already been removed
+ if ( !timer() && timers[ i ] === timer ) {
+ timers.splice( i--, 1 );
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+ if ( timer() && jQuery.timers.push( timer ) ) {
+ jQuery.fx.start();
+ }
+};
+
+jQuery.fx.interval = 13;
+
+jQuery.fx.start = function() {
+ if ( !timerId ) {
+ timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
+ }
+};
+
+jQuery.fx.stop = function() {
+ clearInterval( timerId );
+ timerId = null;
+};
+
+jQuery.fx.speeds = {
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+};
+
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+ };
+}
+jQuery.fn.offset = function( options ) {
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ var docElem, win,
+ box = { top: 0, left: 0 },
+ elem = this[ 0 ],
+ doc = elem && elem.ownerDocument;
+
+ if ( !doc ) {
+ return;
+ }
+
+ docElem = doc.documentElement;
+
+ // Make sure it's not a disconnected DOM node
+ if ( !jQuery.contains( docElem, elem ) ) {
+ return box;
+ }
+
+ // If we don't have gBCR, just use 0,0 rather than error
+ // BlackBerry 5, iOS 3 (original iPhone)
+ if ( typeof elem.getBoundingClientRect !== core_strundefined ) {
+ box = elem.getBoundingClientRect();
+ }
+ win = getWindow( doc );
+ return {
+ top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
+ left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
+ };
+};
+
+jQuery.offset = {
+
+ setOffset: function( elem, options, i ) {
+ var position = jQuery.css( elem, "position" );
+
+ // set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ var curElem = jQuery( elem ),
+ curOffset = curElem.offset(),
+ curCSSTop = jQuery.css( elem, "top" ),
+ curCSSLeft = jQuery.css( elem, "left" ),
+ calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
+ props = {}, curPosition = {}, curTop, curLeft;
+
+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+
+jQuery.fn.extend({
+
+ position: function() {
+ if ( !this[ 0 ] ) {
+ return;
+ }
+
+ var offsetParent, offset,
+ parentOffset = { top: 0, left: 0 },
+ elem = this[ 0 ];
+
+ // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
+ // we assume that getBoundingClientRect is available when computed position is fixed
+ offset = elem.getBoundingClientRect();
+ } else {
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent();
+
+ // Get correct offsets
+ offset = this.offset();
+ if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+ parentOffset = offsetParent.offset();
+ }
+
+ // Add offsetParent borders
+ parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+ parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+ }
+
+ // Subtract parent offsets and element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ return {
+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
+ };
+ },
+
+ offsetParent: function() {
+ return this.map(function() {
+ var offsetParent = this.offsetParent || document.documentElement;
+ while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent || document.documentElement;
+ });
+ }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
+ var top = /Y/.test( prop );
+
+ jQuery.fn[ method ] = function( val ) {
+ return jQuery.access( this, function( elem, method, val ) {
+ var win = getWindow( elem );
+
+ if ( val === undefined ) {
+ return win ? (prop in win) ? win[ prop ] :
+ win.document.documentElement[ method ] :
+ elem[ method ];
+ }
+
+ if ( win ) {
+ win.scrollTo(
+ !top ? val : jQuery( win ).scrollLeft(),
+ top ? val : jQuery( win ).scrollTop()
+ );
+
+ } else {
+ elem[ method ] = val;
+ }
+ }, method, val, arguments.length, null );
+ };
+});
+
+function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+}
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+ // margin is only for outerHeight, outerWidth
+ jQuery.fn[ funcName ] = function( margin, value ) {
+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+ return jQuery.access( this, function( elem, type, value ) {
+ var doc;
+
+ if ( jQuery.isWindow( elem ) ) {
+ // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+ // isn't a whole lot we can do. See pull request at this URL for discussion:
+ // https://github.com/jquery/jquery/pull/764
+ return elem.document.documentElement[ "client" + name ];
+ }
+
+ // Get document width or height
+ if ( elem.nodeType === 9 ) {
+ doc = elem.documentElement;
+
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
+ // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
+ return Math.max(
+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+ elem.body[ "offset" + name ], doc[ "offset" + name ],
+ doc[ "client" + name ]
+ );
+ }
+
+ return value === undefined ?
+ // Get width or height on the element, requesting but not forcing parseFloat
+ jQuery.css( elem, type, extra ) :
+
+ // Set width or height on the element
+ jQuery.style( elem, type, value, extra );
+ }, type, chainable ? margin : undefined, chainable, null );
+ };
+ });
+});
+// Limit scope pollution from any deprecated API
+// (function() {
+
+// })();
+// Expose jQuery to the global object
+window.jQuery = window.$ = jQuery;
+
+// Expose jQuery as an AMD module, but only for AMD loaders that
+// understand the issues with loading multiple versions of jQuery
+// in a page that all might call define(). The loader will indicate
+// they have special allowances for multiple jQuery versions by
+// specifying define.amd.jQuery = true. Register as a named module,
+// since jQuery can be concatenated with other files that may use define,
+// but not use a proper concatenation script that understands anonymous
+// AMD modules. A named AMD is safest and most robust way to register.
+// Lowercase jquery is used because AMD module names are derived from
+// file names, and jQuery is normally delivered in a lowercase file name.
+// Do this after creating the global so that if an AMD module wants to call
+// noConflict to hide this version of jQuery, it will work.
+if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
+ define( "jquery", [], function () { return jQuery; } );
+}
+
+})( window );// Underscore.js 1.8.2
+// http://underscorejs.org
+// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+// Underscore may be freely distributed under the MIT license.
+
+(function() {
+
+ // Baseline setup
+ // --------------
+
+ // Establish the root object, `window` in the browser, or `exports` on the server.
+ var root = this;
+
+ // Save the previous value of the `_` variable.
+ var previousUnderscore = root._;
+
+ // Save bytes in the minified (but not gzipped) version:
+ var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
+
+ // Create quick reference variables for speed access to core prototypes.
+ var
+ push = ArrayProto.push,
+ slice = ArrayProto.slice,
+ toString = ObjProto.toString,
+ hasOwnProperty = ObjProto.hasOwnProperty;
+
+ // All **ECMAScript 5** native function implementations that we hope to use
+ // are declared here.
+ var
+ nativeIsArray = Array.isArray,
+ nativeKeys = Object.keys,
+ nativeBind = FuncProto.bind,
+ nativeCreate = Object.create;
+
+ // Naked function reference for surrogate-prototype-swapping.
+ var Ctor = function(){};
+
+ // Create a safe reference to the Underscore object for use below.
+ var _ = function(obj) {
+ if (obj instanceof _) return obj;
+ if (!(this instanceof _)) return new _(obj);
+ this._wrapped = obj;
+ };
+
+ // Export the Underscore object for **Node.js**, with
+ // backwards-compatibility for the old `require()` API. If we're in
+ // the browser, add `_` as a global object.
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = _;
+ }
+ exports._ = _;
+ } else {
+ root._ = _;
+ }
+
+ // Current version.
+ _.VERSION = '1.8.2';
+
+ // Internal function that returns an efficient (for current engines) version
+ // of the passed-in callback, to be repeatedly applied in other Underscore
+ // functions.
+ var optimizeCb = function(func, context, argCount) {
+ if (context === void 0) return func;
+ switch (argCount == null ? 3 : argCount) {
+ case 1: return function(value) {
+ return func.call(context, value);
+ };
+ case 2: return function(value, other) {
+ return func.call(context, value, other);
+ };
+ case 3: return function(value, index, collection) {
+ return func.call(context, value, index, collection);
+ };
+ case 4: return function(accumulator, value, index, collection) {
+ return func.call(context, accumulator, value, index, collection);
+ };
+ }
+ return function() {
+ return func.apply(context, arguments);
+ };
+ };
+
+ // A mostly-internal function to generate callbacks that can be applied
+ // to each element in a collection, returning the desired result 鈥? either
+ // identity, an arbitrary callback, a property matcher, or a property accessor.
+ var cb = function(value, context, argCount) {
+ if (value == null) return _.identity;
+ if (_.isFunction(value)) return optimizeCb(value, context, argCount);
+ if (_.isObject(value)) return _.matcher(value);
+ return _.property(value);
+ };
+ _.iteratee = function(value, context) {
+ return cb(value, context, Infinity);
+ };
+
+ // An internal function for creating assigner functions.
+ var createAssigner = function(keysFunc, undefinedOnly) {
+ return function(obj) {
+ var length = arguments.length;
+ if (length < 2 || obj == null) return obj;
+ for (var index = 1; index < length; index++) {
+ var source = arguments[index],
+ keys = keysFunc(source),
+ l = keys.length;
+ for (var i = 0; i < l; i++) {
+ var key = keys[i];
+ if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
+ }
+ }
+ return obj;
+ };
+ };
+
+ // An internal function for creating a new object that inherits from another.
+ var baseCreate = function(prototype) {
+ if (!_.isObject(prototype)) return {};
+ if (nativeCreate) return nativeCreate(prototype);
+ Ctor.prototype = prototype;
+ var result = new Ctor;
+ Ctor.prototype = null;
+ return result;
+ };
+
+ // Helper for collection methods to determine whether a collection
+ // should be iterated as an array or as an object
+ // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
+ var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
+ var isArrayLike = function(collection) {
+ var length = collection != null && collection.length;
+ return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
+ };
+
+ // Collection Functions
+ // --------------------
+
+ // The cornerstone, an `each` implementation, aka `forEach`.
+ // Handles raw objects in addition to array-likes. Treats all
+ // sparse array-likes as if they were dense.
+ _.each = _.forEach = function(obj, iteratee, context) {
+ iteratee = optimizeCb(iteratee, context);
+ var i, length;
+ if (isArrayLike(obj)) {
+ for (i = 0, length = obj.length; i < length; i++) {
+ iteratee(obj[i], i, obj);
+ }
+ } else {
+ var keys = _.keys(obj);
+ for (i = 0, length = keys.length; i < length; i++) {
+ iteratee(obj[keys[i]], keys[i], obj);
+ }
+ }
+ return obj;
+ };
+
+ // Return the results of applying the iteratee to each element.
+ _.map = _.collect = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length,
+ results = Array(length);
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ results[index] = iteratee(obj[currentKey], currentKey, obj);
+ }
+ return results;
+ };
+
+ // Create a reducing function iterating left or right.
+ function createReduce(dir) {
+ // Optimized iterator function as using arguments.length
+ // in the main function will deoptimize the, see #1991.
+ function iterator(obj, iteratee, memo, keys, index, length) {
+ for (; index >= 0 && index < length; index += dir) {
+ var currentKey = keys ? keys[index] : index;
+ memo = iteratee(memo, obj[currentKey], currentKey, obj);
+ }
+ return memo;
+ }
+
+ return function(obj, iteratee, memo, context) {
+ iteratee = optimizeCb(iteratee, context, 4);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length,
+ index = dir > 0 ? 0 : length - 1;
+ // Determine the initial value if none is provided.
+ if (arguments.length < 3) {
+ memo = obj[keys ? keys[index] : index];
+ index += dir;
+ }
+ return iterator(obj, iteratee, memo, keys, index, length);
+ };
+ }
+
+ // **Reduce** builds up a single result from a list of values, aka `inject`,
+ // or `foldl`.
+ _.reduce = _.foldl = _.inject = createReduce(1);
+
+ // The right-associative version of reduce, also known as `foldr`.
+ _.reduceRight = _.foldr = createReduce(-1);
+
+ // Return the first value which passes a truth test. Aliased as `detect`.
+ _.find = _.detect = function(obj, predicate, context) {
+ var key;
+ if (isArrayLike(obj)) {
+ key = _.findIndex(obj, predicate, context);
+ } else {
+ key = _.findKey(obj, predicate, context);
+ }
+ if (key !== void 0 && key !== -1) return obj[key];
+ };
+
+ // Return all the elements that pass a truth test.
+ // Aliased as `select`.
+ _.filter = _.select = function(obj, predicate, context) {
+ var results = [];
+ predicate = cb(predicate, context);
+ _.each(obj, function(value, index, list) {
+ if (predicate(value, index, list)) results.push(value);
+ });
+ return results;
+ };
+
+ // Return all the elements for which a truth test fails.
+ _.reject = function(obj, predicate, context) {
+ return _.filter(obj, _.negate(cb(predicate)), context);
+ };
+
+ // Determine whether all of the elements match a truth test.
+ // Aliased as `all`.
+ _.every = _.all = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length;
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ if (!predicate(obj[currentKey], currentKey, obj)) return false;
+ }
+ return true;
+ };
+
+ // Determine if at least one element in the object matches a truth test.
+ // Aliased as `any`.
+ _.some = _.any = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length;
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ if (predicate(obj[currentKey], currentKey, obj)) return true;
+ }
+ return false;
+ };
+
+ // Determine if the array or object contains a given value (using `===`).
+ // Aliased as `includes` and `include`.
+ _.contains = _.includes = _.include = function(obj, target, fromIndex) {
+ if (!isArrayLike(obj)) obj = _.values(obj);
+ return _.indexOf(obj, target, typeof fromIndex == 'number' && fromIndex) >= 0;
+ };
+
+ // Invoke a method (with arguments) on every item in a collection.
+ _.invoke = function(obj, method) {
+ var args = slice.call(arguments, 2);
+ var isFunc = _.isFunction(method);
+ return _.map(obj, function(value) {
+ var func = isFunc ? method : value[method];
+ return func == null ? func : func.apply(value, args);
+ });
+ };
+
+ // Convenience version of a common use case of `map`: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, _.property(key));
+ };
+
+ // Convenience version of a common use case of `filter`: selecting only objects
+ // containing specific `key:value` pairs.
+ _.where = function(obj, attrs) {
+ return _.filter(obj, _.matcher(attrs));
+ };
+
+ // Convenience version of a common use case of `find`: getting the first object
+ // containing specific `key:value` pairs.
+ _.findWhere = function(obj, attrs) {
+ return _.find(obj, _.matcher(attrs));
+ };
+
+ // Return the maximum element (or element-based computation).
+ _.max = function(obj, iteratee, context) {
+ var result = -Infinity, lastComputed = -Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = isArrayLike(obj) ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value > result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Return the minimum element (or element-based computation).
+ _.min = function(obj, iteratee, context) {
+ var result = Infinity, lastComputed = Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = isArrayLike(obj) ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value < result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed < lastComputed || computed === Infinity && result === Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Shuffle a collection, using the modern version of the
+ // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher鈥揧ates_shuffle).
+ _.shuffle = function(obj) {
+ var set = isArrayLike(obj) ? obj : _.values(obj);
+ var length = set.length;
+ var shuffled = Array(length);
+ for (var index = 0, rand; index < length; index++) {
+ rand = _.random(0, index);
+ if (rand !== index) shuffled[index] = shuffled[rand];
+ shuffled[rand] = set[index];
+ }
+ return shuffled;
+ };
+
+ // Sample **n** random values from a collection.
+ // If **n** is not specified, returns a single random element.
+ // The internal `guard` argument allows it to work with `map`.
+ _.sample = function(obj, n, guard) {
+ if (n == null || guard) {
+ if (!isArrayLike(obj)) obj = _.values(obj);
+ return obj[_.random(obj.length - 1)];
+ }
+ return _.shuffle(obj).slice(0, Math.max(0, n));
+ };
+
+ // Sort the object's values by a criterion produced by an iteratee.
+ _.sortBy = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value: value,
+ index: index,
+ criteria: iteratee(value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria;
+ var b = right.criteria;
+ if (a !== b) {
+ if (a > b || a === void 0) return 1;
+ if (a < b || b === void 0) return -1;
+ }
+ return left.index - right.index;
+ }), 'value');
+ };
+
+ // An internal function used for aggregate "group by" operations.
+ var group = function(behavior) {
+ return function(obj, iteratee, context) {
+ var result = {};
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index) {
+ var key = iteratee(value, index, obj);
+ behavior(result, value, key);
+ });
+ return result;
+ };
+ };
+
+ // Groups the object's values by a criterion. Pass either a string attribute
+ // to group by, or a function that returns the criterion.
+ _.groupBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key].push(value); else result[key] = [value];
+ });
+
+ // Indexes the object's values by a criterion, similar to `groupBy`, but for
+ // when you know that your index values will be unique.
+ _.indexBy = group(function(result, value, key) {
+ result[key] = value;
+ });
+
+ // Counts instances of an object that group by a certain criterion. Pass
+ // either a string attribute to count by, or a function that returns the
+ // criterion.
+ _.countBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key]++; else result[key] = 1;
+ });
+
+ // Safely create a real, live array from anything iterable.
+ _.toArray = function(obj) {
+ if (!obj) return [];
+ if (_.isArray(obj)) return slice.call(obj);
+ if (isArrayLike(obj)) return _.map(obj, _.identity);
+ return _.values(obj);
+ };
+
+ // Return the number of elements in an object.
+ _.size = function(obj) {
+ if (obj == null) return 0;
+ return isArrayLike(obj) ? obj.length : _.keys(obj).length;
+ };
+
+ // Split a collection into two arrays: one whose elements all satisfy the given
+ // predicate, and one whose elements all do not satisfy the predicate.
+ _.partition = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var pass = [], fail = [];
+ _.each(obj, function(value, key, obj) {
+ (predicate(value, key, obj) ? pass : fail).push(value);
+ });
+ return [pass, fail];
+ };
+
+ // Array Functions
+ // ---------------
+
+ // Get the first element of an array. Passing **n** will return the first N
+ // values in the array. Aliased as `head` and `take`. The **guard** check
+ // allows it to work with `_.map`.
+ _.first = _.head = _.take = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[0];
+ return _.initial(array, array.length - n);
+ };
+
+ // Returns everything but the last entry of the array. Especially useful on
+ // the arguments object. Passing **n** will return all the values in
+ // the array, excluding the last N.
+ _.initial = function(array, n, guard) {
+ return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
+ };
+
+ // Get the last element of an array. Passing **n** will return the last N
+ // values in the array.
+ _.last = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[array.length - 1];
+ return _.rest(array, Math.max(0, array.length - n));
+ };
+
+ // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
+ // Especially useful on the arguments object. Passing an **n** will return
+ // the rest N values in the array.
+ _.rest = _.tail = _.drop = function(array, n, guard) {
+ return slice.call(array, n == null || guard ? 1 : n);
+ };
+
+ // Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.filter(array, _.identity);
+ };
+
+ // Internal implementation of a recursive `flatten` function.
+ var flatten = function(input, shallow, strict, startIndex) {
+ var output = [], idx = 0;
+ for (var i = startIndex || 0, length = input && input.length; i < length; i++) {
+ var value = input[i];
+ if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
+ //flatten current level of array or arguments object
+ if (!shallow) value = flatten(value, shallow, strict);
+ var j = 0, len = value.length;
+ output.length += len;
+ while (j < len) {
+ output[idx++] = value[j++];
+ }
+ } else if (!strict) {
+ output[idx++] = value;
+ }
+ }
+ return output;
+ };
+
+ // Flatten out an array, either recursively (by default), or just one level.
+ _.flatten = function(array, shallow) {
+ return flatten(array, shallow, false);
+ };
+
+ // Return a version of the array that does not contain the specified value(s).
+ _.without = function(array) {
+ return _.difference(array, slice.call(arguments, 1));
+ };
+
+ // Produce a duplicate-free version of the array. If the array has already
+ // been sorted, you have the option of using a faster algorithm.
+ // Aliased as `unique`.
+ _.uniq = _.unique = function(array, isSorted, iteratee, context) {
+ if (array == null) return [];
+ if (!_.isBoolean(isSorted)) {
+ context = iteratee;
+ iteratee = isSorted;
+ isSorted = false;
+ }
+ if (iteratee != null) iteratee = cb(iteratee, context);
+ var result = [];
+ var seen = [];
+ for (var i = 0, length = array.length; i < length; i++) {
+ var value = array[i],
+ computed = iteratee ? iteratee(value, i, array) : value;
+ if (isSorted) {
+ if (!i || seen !== computed) result.push(value);
+ seen = computed;
+ } else if (iteratee) {
+ if (!_.contains(seen, computed)) {
+ seen.push(computed);
+ result.push(value);
+ }
+ } else if (!_.contains(result, value)) {
+ result.push(value);
+ }
+ }
+ return result;
+ };
+
+ // Produce an array that contains the union: each distinct element from all of
+ // the passed-in arrays.
+ _.union = function() {
+ return _.uniq(flatten(arguments, true, true));
+ };
+
+ // Produce an array that contains every item shared between all the
+ // passed-in arrays.
+ _.intersection = function(array) {
+ if (array == null) return [];
+ var result = [];
+ var argsLength = arguments.length;
+ for (var i = 0, length = array.length; i < length; i++) {
+ var item = array[i];
+ if (_.contains(result, item)) continue;
+ for (var j = 1; j < argsLength; j++) {
+ if (!_.contains(arguments[j], item)) break;
+ }
+ if (j === argsLength) result.push(item);
+ }
+ return result;
+ };
+
+ // Take the difference between one array and a number of other arrays.
+ // Only the elements present in just the first array will remain.
+ _.difference = function(array) {
+ var rest = flatten(arguments, true, true, 1);
+ return _.filter(array, function(value){
+ return !_.contains(rest, value);
+ });
+ };
+
+ // Zip together multiple lists into a single array -- elements that share
+ // an index go together.
+ _.zip = function() {
+ return _.unzip(arguments);
+ };
+
+ // Complement of _.zip. Unzip accepts an array of arrays and groups
+ // each array's elements on shared indices
+ _.unzip = function(array) {
+ var length = array && _.max(array, 'length').length || 0;
+ var result = Array(length);
+
+ for (var index = 0; index < length; index++) {
+ result[index] = _.pluck(array, index);
+ }
+ return result;
+ };
+
+ // Converts lists into objects. Pass either a single array of `[key, value]`
+ // pairs, or two parallel arrays of the same length -- one of keys, and one of
+ // the corresponding values.
+ _.object = function(list, values) {
+ var result = {};
+ for (var i = 0, length = list && list.length; i < length; i++) {
+ if (values) {
+ result[list[i]] = values[i];
+ } else {
+ result[list[i][0]] = list[i][1];
+ }
+ }
+ return result;
+ };
+
+ // Return the position of the first occurrence of an item in an array,
+ // or -1 if the item is not included in the array.
+ // If the array is large and already in sort order, pass `true`
+ // for **isSorted** to use binary search.
+ _.indexOf = function(array, item, isSorted) {
+ var i = 0, length = array && array.length;
+ if (typeof isSorted == 'number') {
+ i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted;
+ } else if (isSorted && length) {
+ i = _.sortedIndex(array, item);
+ return array[i] === item ? i : -1;
+ }
+ if (item !== item) {
+ return _.findIndex(slice.call(array, i), _.isNaN);
+ }
+ for (; i < length; i++) if (array[i] === item) return i;
+ return -1;
+ };
+
+ _.lastIndexOf = function(array, item, from) {
+ var idx = array ? array.length : 0;
+ if (typeof from == 'number') {
+ idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1);
+ }
+ if (item !== item) {
+ return _.findLastIndex(slice.call(array, 0, idx), _.isNaN);
+ }
+ while (--idx >= 0) if (array[idx] === item) return idx;
+ return -1;
+ };
+
+ // Generator function to create the findIndex and findLastIndex functions
+ function createIndexFinder(dir) {
+ return function(array, predicate, context) {
+ predicate = cb(predicate, context);
+ var length = array != null && array.length;
+ var index = dir > 0 ? 0 : length - 1;
+ for (; index >= 0 && index < length; index += dir) {
+ if (predicate(array[index], index, array)) return index;
+ }
+ return -1;
+ };
+ }
+
+ // Returns the first index on an array-like that passes a predicate test
+ _.findIndex = createIndexFinder(1);
+
+ _.findLastIndex = createIndexFinder(-1);
+
+ // Use a comparator function to figure out the smallest index at which
+ // an object should be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iteratee, context) {
+ iteratee = cb(iteratee, context, 1);
+ var value = iteratee(obj);
+ var low = 0, high = array.length;
+ while (low < high) {
+ var mid = Math.floor((low + high) / 2);
+ if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
+ }
+ return low;
+ };
+
+ // Generate an integer Array containing an arithmetic progression. A port of
+ // the native Python `range()` function. See
+ // [the Python documentation](http://docs.python.org/library/functions.html#range).
+ _.range = function(start, stop, step) {
+ if (arguments.length <= 1) {
+ stop = start || 0;
+ start = 0;
+ }
+ step = step || 1;
+
+ var length = Math.max(Math.ceil((stop - start) / step), 0);
+ var range = Array(length);
+
+ for (var idx = 0; idx < length; idx++, start += step) {
+ range[idx] = start;
+ }
+
+ return range;
+ };
+
+ // Function (ahem) Functions
+ // ------------------
+
+ // Determines whether to execute a function as a constructor
+ // or a normal function with the provided arguments
+ var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
+ if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
+ var self = baseCreate(sourceFunc.prototype);
+ var result = sourceFunc.apply(self, args);
+ if (_.isObject(result)) return result;
+ return self;
+ };
+
+ // Create a function bound to a given object (assigning `this`, and arguments,
+ // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
+ // available.
+ _.bind = function(func, context) {
+ if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+ if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
+ var args = slice.call(arguments, 2);
+ var bound = function() {
+ return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
+ };
+ return bound;
+ };
+
+ // Partially apply a function by creating a version that has had some of its
+ // arguments pre-filled, without changing its dynamic `this` context. _ acts
+ // as a placeholder, allowing any combination of arguments to be pre-filled.
+ _.partial = function(func) {
+ var boundArgs = slice.call(arguments, 1);
+ var bound = function() {
+ var position = 0, length = boundArgs.length;
+ var args = Array(length);
+ for (var i = 0; i < length; i++) {
+ args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
+ }
+ while (position < arguments.length) args.push(arguments[position++]);
+ return executeBound(func, bound, this, this, args);
+ };
+ return bound;
+ };
+
+ // Bind a number of an object's methods to that object. Remaining arguments
+ // are the method names to be bound. Useful for ensuring that all callbacks
+ // defined on an object belong to it.
+ _.bindAll = function(obj) {
+ var i, length = arguments.length, key;
+ if (length <= 1) throw new Error('bindAll must be passed function names');
+ for (i = 1; i < length; i++) {
+ key = arguments[i];
+ obj[key] = _.bind(obj[key], obj);
+ }
+ return obj;
+ };
+
+ // Memoize an expensive function by storing its results.
+ _.memoize = function(func, hasher) {
+ var memoize = function(key) {
+ var cache = memoize.cache;
+ var address = '' + (hasher ? hasher.apply(this, arguments) : key);
+ if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
+ return cache[address];
+ };
+ memoize.cache = {};
+ return memoize;
+ };
+
+ // Delays a function for the given number of milliseconds, and then calls
+ // it with the arguments supplied.
+ _.delay = function(func, wait) {
+ var args = slice.call(arguments, 2);
+ return setTimeout(function(){
+ return func.apply(null, args);
+ }, wait);
+ };
+
+ // Defers a function, scheduling it to run after the current call stack has
+ // cleared.
+ _.defer = _.partial(_.delay, _, 1);
+
+ // Returns a function, that, when invoked, will only be triggered at most once
+ // during a given window of time. Normally, the throttled function will run
+ // as much as it can, without ever going more than once per `wait` duration;
+ // but if you'd like to disable the execution on the leading edge, pass
+ // `{leading: false}`. To disable execution on the trailing edge, ditto.
+ _.throttle = function(func, wait, options) {
+ var context, args, result;
+ var timeout = null;
+ var previous = 0;
+ if (!options) options = {};
+ var later = function() {
+ previous = options.leading === false ? 0 : _.now();
+ timeout = null;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ };
+ return function() {
+ var now = _.now();
+ if (!previous && options.leading === false) previous = now;
+ var remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0 || remaining > wait) {
+ if (timeout) {
+ clearTimeout(timeout);
+ timeout = null;
+ }
+ previous = now;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ } else if (!timeout && options.trailing !== false) {
+ timeout = setTimeout(later, remaining);
+ }
+ return result;
+ };
+ };
+
+ // Returns a function, that, as long as it continues to be invoked, will not
+ // be triggered. The function will be called after it stops being called for
+ // N milliseconds. If `immediate` is passed, trigger the function on the
+ // leading edge, instead of the trailing.
+ _.debounce = function(func, wait, immediate) {
+ var timeout, args, context, timestamp, result;
+
+ var later = function() {
+ var last = _.now() - timestamp;
+
+ if (last < wait && last >= 0) {
+ timeout = setTimeout(later, wait - last);
+ } else {
+ timeout = null;
+ if (!immediate) {
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ }
+ }
+ };
+
+ return function() {
+ context = this;
+ args = arguments;
+ timestamp = _.now();
+ var callNow = immediate && !timeout;
+ if (!timeout) timeout = setTimeout(later, wait);
+ if (callNow) {
+ result = func.apply(context, args);
+ context = args = null;
+ }
+
+ return result;
+ };
+ };
+
+ // Returns the first function passed as an argument to the second,
+ // allowing you to adjust arguments, run code before and after, and
+ // conditionally execute the original function.
+ _.wrap = function(func, wrapper) {
+ return _.partial(wrapper, func);
+ };
+
+ // Returns a negated version of the passed-in predicate.
+ _.negate = function(predicate) {
+ return function() {
+ return !predicate.apply(this, arguments);
+ };
+ };
+
+ // Returns a function that is the composition of a list of functions, each
+ // consuming the return value of the function that follows.
+ _.compose = function() {
+ var args = arguments;
+ var start = args.length - 1;
+ return function() {
+ var i = start;
+ var result = args[start].apply(this, arguments);
+ while (i--) result = args[i].call(this, result);
+ return result;
+ };
+ };
+
+ // Returns a function that will only be executed on and after the Nth call.
+ _.after = function(times, func) {
+ return function() {
+ if (--times < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ };
+
+ // Returns a function that will only be executed up to (but not including) the Nth call.
+ _.before = function(times, func) {
+ var memo;
+ return function() {
+ if (--times > 0) {
+ memo = func.apply(this, arguments);
+ }
+ if (times <= 1) func = null;
+ return memo;
+ };
+ };
+
+ // Returns a function that will be executed at most one time, no matter how
+ // often you call it. Useful for lazy initialization.
+ _.once = _.partial(_.before, 2);
+
+ // Object Functions
+ // ----------------
+
+ // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
+ var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
+ var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
+ 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
+
+ function collectNonEnumProps(obj, keys) {
+ var nonEnumIdx = nonEnumerableProps.length;
+ var constructor = obj.constructor;
+ var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
+
+ // Constructor is a special case.
+ var prop = 'constructor';
+ if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
+
+ while (nonEnumIdx--) {
+ prop = nonEnumerableProps[nonEnumIdx];
+ if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
+ keys.push(prop);
+ }
+ }
+ }
+
+ // Retrieve the names of an object's own properties.
+ // Delegates to **ECMAScript 5**'s native `Object.keys`
+ _.keys = function(obj) {
+ if (!_.isObject(obj)) return [];
+ if (nativeKeys) return nativeKeys(obj);
+ var keys = [];
+ for (var key in obj) if (_.has(obj, key)) keys.push(key);
+ // Ahem, IE < 9.
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
+ return keys;
+ };
+
+ // Retrieve all the property names of an object.
+ _.allKeys = function(obj) {
+ if (!_.isObject(obj)) return [];
+ var keys = [];
+ for (var key in obj) keys.push(key);
+ // Ahem, IE < 9.
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
+ return keys;
+ };
+
+ // Retrieve the values of an object's properties.
+ _.values = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var values = Array(length);
+ for (var i = 0; i < length; i++) {
+ values[i] = obj[keys[i]];
+ }
+ return values;
+ };
+
+ // Returns the results of applying the iteratee to each element of the object
+ // In contrast to _.map it returns an object
+ _.mapObject = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ var keys = _.keys(obj),
+ length = keys.length,
+ results = {},
+ currentKey;
+ for (var index = 0; index < length; index++) {
+ currentKey = keys[index];
+ results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
+ }
+ return results;
+ };
+
+ // Convert an object into a list of `[key, value]` pairs.
+ _.pairs = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var pairs = Array(length);
+ for (var i = 0; i < length; i++) {
+ pairs[i] = [keys[i], obj[keys[i]]];
+ }
+ return pairs;
+ };
+
+ // Invert the keys and values of an object. The values must be serializable.
+ _.invert = function(obj) {
+ var result = {};
+ var keys = _.keys(obj);
+ for (var i = 0, length = keys.length; i < length; i++) {
+ result[obj[keys[i]]] = keys[i];
+ }
+ return result;
+ };
+
+ // Return a sorted list of the function names available on the object.
+ // Aliased as `methods`
+ _.functions = _.methods = function(obj) {
+ var names = [];
+ for (var key in obj) {
+ if (_.isFunction(obj[key])) names.push(key);
+ }
+ return names.sort();
+ };
+
+ // Extend a given object with all the properties in passed-in object(s).
+ _.extend = createAssigner(_.allKeys);
+
+ // Assigns a given object with all the own properties in the passed-in object(s)
+ // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
+ _.extendOwn = _.assign = createAssigner(_.keys);
+
+ // Returns the first key on an object that passes a predicate test
+ _.findKey = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = _.keys(obj), key;
+ for (var i = 0, length = keys.length; i < length; i++) {
+ key = keys[i];
+ if (predicate(obj[key], key, obj)) return key;
+ }
+ };
+
+ // Return a copy of the object only containing the whitelisted properties.
+ _.pick = function(object, oiteratee, context) {
+ var result = {}, obj = object, iteratee, keys;
+ if (obj == null) return result;
+ if (_.isFunction(oiteratee)) {
+ keys = _.allKeys(obj);
+ iteratee = optimizeCb(oiteratee, context);
+ } else {
+ keys = flatten(arguments, false, false, 1);
+ iteratee = function(value, key, obj) { return key in obj; };
+ obj = Object(obj);
+ }
+ for (var i = 0, length = keys.length; i < length; i++) {
+ var key = keys[i];
+ var value = obj[key];
+ if (iteratee(value, key, obj)) result[key] = value;
+ }
+ return result;
+ };
+
+ // Return a copy of the object without the blacklisted properties.
+ _.omit = function(obj, iteratee, context) {
+ if (_.isFunction(iteratee)) {
+ iteratee = _.negate(iteratee);
+ } else {
+ var keys = _.map(flatten(arguments, false, false, 1), String);
+ iteratee = function(value, key) {
+ return !_.contains(keys, key);
+ };
+ }
+ return _.pick(obj, iteratee, context);
+ };
+
+ // Fill in a given object with default properties.
+ _.defaults = createAssigner(_.allKeys, true);
+
+ // Creates an object that inherits from the given prototype object.
+ // If additional properties are provided then they will be added to the
+ // created object.
+ _.create = function(prototype, props) {
+ var result = baseCreate(prototype);
+ if (props) _.extendOwn(result, props);
+ return result;
+ };
+
+ // Create a (shallow-cloned) duplicate of an object.
+ _.clone = function(obj) {
+ if (!_.isObject(obj)) return obj;
+ return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+ };
+
+ // Invokes interceptor with the obj, and then returns obj.
+ // The primary purpose of this method is to "tap into" a method chain, in
+ // order to perform operations on intermediate results within the chain.
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ };
+
+ // Returns whether an object has a given set of `key:value` pairs.
+ _.isMatch = function(object, attrs) {
+ var keys = _.keys(attrs), length = keys.length;
+ if (object == null) return !length;
+ var obj = Object(object);
+ for (var i = 0; i < length; i++) {
+ var key = keys[i];
+ if (attrs[key] !== obj[key] || !(key in obj)) return false;
+ }
+ return true;
+ };
+
+
+ // Internal recursive comparison function for `isEqual`.
+ var eq = function(a, b, aStack, bStack) {
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
+ // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
+ if (a === b) return a !== 0 || 1 / a === 1 / b;
+ // A strict comparison is necessary because `null == undefined`.
+ if (a == null || b == null) return a === b;
+ // Unwrap any wrapped objects.
+ if (a instanceof _) a = a._wrapped;
+ if (b instanceof _) b = b._wrapped;
+ // Compare `[[Class]]` names.
+ var className = toString.call(a);
+ if (className !== toString.call(b)) return false;
+ switch (className) {
+ // Strings, numbers, regular expressions, dates, and booleans are compared by value.
+ case '[object RegExp]':
+ // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
+ case '[object String]':
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
+ // equivalent to `new String("5")`.
+ return '' + a === '' + b;
+ case '[object Number]':
+ // `NaN`s are equivalent, but non-reflexive.
+ // Object(NaN) is equivalent to NaN
+ if (+a !== +a) return +b !== +b;
+ // An `egal` comparison is performed for other numeric values.
+ return +a === 0 ? 1 / +a === 1 / b : +a === +b;
+ case '[object Date]':
+ case '[object Boolean]':
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
+ // millisecond representations. Note that invalid dates with millisecond representations
+ // of `NaN` are not equivalent.
+ return +a === +b;
+ }
+
+ var areArrays = className === '[object Array]';
+ if (!areArrays) {
+ if (typeof a != 'object' || typeof b != 'object') return false;
+
+ // Objects with different constructors are not equivalent, but `Object`s or `Array`s
+ // from different frames are.
+ var aCtor = a.constructor, bCtor = b.constructor;
+ if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
+ _.isFunction(bCtor) && bCtor instanceof bCtor)
+ && ('constructor' in a && 'constructor' in b)) {
+ return false;
+ }
+ }
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+
+ // Initializing stack of traversed objects.
+ // It's done here since we only need them for objects and arrays comparison.
+ aStack = aStack || [];
+ bStack = bStack || [];
+ var length = aStack.length;
+ while (length--) {
+ // Linear search. Performance is inversely proportional to the number of
+ // unique nested structures.
+ if (aStack[length] === a) return bStack[length] === b;
+ }
+
+ // Add the first object to the stack of traversed objects.
+ aStack.push(a);
+ bStack.push(b);
+
+ // Recursively compare objects and arrays.
+ if (areArrays) {
+ // Compare array lengths to determine if a deep comparison is necessary.
+ length = a.length;
+ if (length !== b.length) return false;
+ // Deep compare the contents, ignoring non-numeric properties.
+ while (length--) {
+ if (!eq(a[length], b[length], aStack, bStack)) return false;
+ }
+ } else {
+ // Deep compare objects.
+ var keys = _.keys(a), key;
+ length = keys.length;
+ // Ensure that both objects contain the same number of properties before comparing deep equality.
+ if (_.keys(b).length !== length) return false;
+ while (length--) {
+ // Deep compare each member
+ key = keys[length];
+ if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
+ }
+ }
+ // Remove the first object from the stack of traversed objects.
+ aStack.pop();
+ bStack.pop();
+ return true;
+ };
+
+ // Perform a deep comparison to check if two objects are equal.
+ _.isEqual = function(a, b) {
+ return eq(a, b);
+ };
+
+ // Is a given array, string, or object empty?
+ // An "empty" object has no enumerable own-properties.
+ _.isEmpty = function(obj) {
+ if (obj == null) return true;
+ if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
+ return _.keys(obj).length === 0;
+ };
+
+ // Is a given value a DOM element?
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType === 1);
+ };
+
+ // Is a given value an array?
+ // Delegates to ECMA5's native Array.isArray
+ _.isArray = nativeIsArray || function(obj) {
+ return toString.call(obj) === '[object Array]';
+ };
+
+ // Is a given variable an object?
+ _.isObject = function(obj) {
+ var type = typeof obj;
+ return type === 'function' || type === 'object' && !!obj;
+ };
+
+ // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
+ _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
+ _['is' + name] = function(obj) {
+ return toString.call(obj) === '[object ' + name + ']';
+ };
+ });
+
+ // Define a fallback version of the method in browsers (ahem, IE < 9), where
+ // there isn't any inspectable "Arguments" type.
+ if (!_.isArguments(arguments)) {
+ _.isArguments = function(obj) {
+ return _.has(obj, 'callee');
+ };
+ }
+
+ // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
+ // IE 11 (#1621), and in Safari 8 (#1929).
+ if (typeof /./ != 'function' && typeof Int8Array != 'object') {
+ _.isFunction = function(obj) {
+ return typeof obj == 'function' || false;
+ };
+ }
+
+ // Is a given object a finite number?
+ _.isFinite = function(obj) {
+ return isFinite(obj) && !isNaN(parseFloat(obj));
+ };
+
+ // Is the given value `NaN`? (NaN is the only number which does not equal itself).
+ _.isNaN = function(obj) {
+ return _.isNumber(obj) && obj !== +obj;
+ };
+
+ // Is a given value a boolean?
+ _.isBoolean = function(obj) {
+ return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
+ };
+
+ // Is a given value equal to null?
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+
+ // Is a given variable undefined?
+ _.isUndefined = function(obj) {
+ return obj === void 0;
+ };
+
+ // Shortcut function for checking if an object has a given property directly
+ // on itself (in other words, not on a prototype).
+ _.has = function(obj, key) {
+ return obj != null && hasOwnProperty.call(obj, key);
+ };
+
+ // Utility Functions
+ // -----------------
+
+ // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
+ // previous owner. Returns a reference to the Underscore object.
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+
+ // Keep the identity function around for default iteratees.
+ _.identity = function(value) {
+ return value;
+ };
+
+ // Predicate-generating functions. Often useful outside of Underscore.
+ _.constant = function(value) {
+ return function() {
+ return value;
+ };
+ };
+
+ _.noop = function(){};
+
+ _.property = function(key) {
+ return function(obj) {
+ return obj == null ? void 0 : obj[key];
+ };
+ };
+
+ // Generates a function for a given object that returns a given property.
+ _.propertyOf = function(obj) {
+ return obj == null ? function(){} : function(key) {
+ return obj[key];
+ };
+ };
+
+ // Returns a predicate for checking whether an object has a given set of
+ // `key:value` pairs.
+ _.matcher = _.matches = function(attrs) {
+ attrs = _.extendOwn({}, attrs);
+ return function(obj) {
+ return _.isMatch(obj, attrs);
+ };
+ };
+
+ // Run a function **n** times.
+ _.times = function(n, iteratee, context) {
+ var accum = Array(Math.max(0, n));
+ iteratee = optimizeCb(iteratee, context, 1);
+ for (var i = 0; i < n; i++) accum[i] = iteratee(i);
+ return accum;
+ };
+
+ // Return a random integer between min and max (inclusive).
+ _.random = function(min, max) {
+ if (max == null) {
+ max = min;
+ min = 0;
+ }
+ return min + Math.floor(Math.random() * (max - min + 1));
+ };
+
+ // A (possibly faster) way to get the current timestamp as an integer.
+ _.now = Date.now || function() {
+ return new Date().getTime();
+ };
+
+ // List of HTML entities for escaping.
+ var escapeMap = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '`': '`'
+ };
+ var unescapeMap = _.invert(escapeMap);
+
+ // Functions for escaping and unescaping strings to/from HTML interpolation.
+ var createEscaper = function(map) {
+ var escaper = function(match) {
+ return map[match];
+ };
+ // Regexes for identifying a key that needs to be escaped
+ var source = '(?:' + _.keys(map).join('|') + ')';
+ var testRegexp = RegExp(source);
+ var replaceRegexp = RegExp(source, 'g');
+ return function(string) {
+ string = string == null ? '' : '' + string;
+ return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
+ };
+ };
+ _.escape = createEscaper(escapeMap);
+ _.unescape = createEscaper(unescapeMap);
+
+ // If the value of the named `property` is a function then invoke it with the
+ // `object` as context; otherwise, return it.
+ _.result = function(object, property, fallback) {
+ var value = object == null ? void 0 : object[property];
+ if (value === void 0) {
+ value = fallback;
+ }
+ return _.isFunction(value) ? value.call(object) : value;
+ };
+
+ // Generate a unique integer id (unique within the entire client session).
+ // Useful for temporary DOM ids.
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = ++idCounter + '';
+ return prefix ? prefix + id : id;
+ };
+
+ // By default, Underscore uses ERB-style template delimiters, change the
+ // following template settings to use alternative delimiters.
+ _.templateSettings = {
+ evaluate : /<%([\s\S]+?)%>/g,
+ interpolate : /<%=([\s\S]+?)%>/g,
+ escape : /<%-([\s\S]+?)%>/g
+ };
+
+ // When customizing `templateSettings`, if you don't want to define an
+ // interpolation, evaluation or escaping regex, we need one that is
+ // guaranteed not to match.
+ var noMatch = /(.)^/;
+
+ // Certain characters need to be escaped so that they can be put into a
+ // string literal.
+ var escapes = {
+ "'": "'",
+ '\\': '\\',
+ '\r': 'r',
+ '\n': 'n',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
+
+ var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
+
+ var escapeChar = function(match) {
+ return '\\' + escapes[match];
+ };
+
+ // JavaScript micro-templating, similar to John Resig's implementation.
+ // Underscore templating handles arbitrary delimiters, preserves whitespace,
+ // and correctly escapes quotes within interpolated code.
+ // NB: `oldSettings` only exists for backwards compatibility.
+ _.template = function(text, settings, oldSettings) {
+ if (!settings && oldSettings) settings = oldSettings;
+ settings = _.defaults({}, settings, _.templateSettings);
+
+ // Combine delimiters into one regular expression via alternation.
+ var matcher = RegExp([
+ (settings.escape || noMatch).source,
+ (settings.interpolate || noMatch).source,
+ (settings.evaluate || noMatch).source
+ ].join('|') + '|$', 'g');
+
+ // Compile the template source, escaping string literals appropriately.
+ var index = 0;
+ var source = "__p+='";
+ text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
+ source += text.slice(index, offset).replace(escaper, escapeChar);
+ index = offset + match.length;
+
+ if (escape) {
+ source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
+ } else if (interpolate) {
+ source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
+ } else if (evaluate) {
+ source += "';\n" + evaluate + "\n__p+='";
+ }
+
+ // Adobe VMs need the match returned to produce the correct offest.
+ return match;
+ });
+ source += "';\n";
+
+ // If a variable is not specified, place data values in local scope.
+ if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
+
+ source = "var __t,__p='',__j=Array.prototype.join," +
+ "print=function(){__p+=__j.call(arguments,'');};\n" +
+ source + 'return __p;\n';
+
+ try {
+ var render = new Function(settings.variable || 'obj', '_', source);
+ } catch (e) {
+ e.source = source;
+ throw e;
+ }
+
+ var template = function(data) {
+ return render.call(this, data, _);
+ };
+
+ // Provide the compiled source as a convenience for precompilation.
+ var argument = settings.variable || 'obj';
+ template.source = 'function(' + argument + '){\n' + source + '}';
+
+ return template;
+ };
+
+ // Add a "chain" function. Start chaining a wrapped Underscore object.
+ _.chain = function(obj) {
+ var instance = _(obj);
+ instance._chain = true;
+ return instance;
+ };
+
+ // OOP
+ // ---------------
+ // If Underscore is called as a function, it returns a wrapped object that
+ // can be used OO-style. This wrapper holds altered versions of all the
+ // underscore functions. Wrapped objects may be chained.
+
+ // Helper function to continue chaining intermediate results.
+ var result = function(instance, obj) {
+ return instance._chain ? _(obj).chain() : obj;
+ };
+
+ // Add your own custom functions to the Underscore object.
+ _.mixin = function(obj) {
+ _.each(_.functions(obj), function(name) {
+ var func = _[name] = obj[name];
+ _.prototype[name] = function() {
+ var args = [this._wrapped];
+ push.apply(args, arguments);
+ return result(this, func.apply(_, args));
+ };
+ });
+ };
+
+ // Add all of the Underscore functions to the wrapper object.
+ _.mixin(_);
+
+ // Add all mutator Array functions to the wrapper.
+ _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ var obj = this._wrapped;
+ method.apply(obj, arguments);
+ if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
+ return result(this, obj);
+ };
+ });
+
+ // Add all accessor Array functions to the wrapper.
+ _.each(['concat', 'join', 'slice'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ return result(this, method.apply(this._wrapped, arguments));
+ };
+ });
+
+ // Extracts the result from a wrapped and chained object.
+ _.prototype.value = function() {
+ return this._wrapped;
+ };
+
+ // Provide unwrapping proxy for some methods used in engine operations
+ // such as arithmetic and JSON stringification.
+ _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
+
+ _.prototype.toString = function() {
+ return '' + this._wrapped;
+ };
+
+ // AMD registration happens at the end for compatibility with AMD loaders
+ // that may not enforce next-turn semantics on modules. Even though general
+ // practice for AMD registration is to be anonymous, underscore registers
+ // as a named module because, like jQuery, it is a base library that is
+ // popular enough to be bundled in a third party lib, but not be part of
+ // an AMD load request. Those cases could generate an error when an
+ // anonymous define() is called outside of a loader request.
+ if (typeof define === 'function' && define.amd) {
+ define('underscore', [], function() {
+ return _;
+ });
+ }
+}.call(this));/**
+ * Created by richie on 15/7/8.
+ */
+/**
+ * 初始化BI对象
+ */
+if (window.BI == null) {
+ window.BI = {};
+}/**
+ * MVC工厂
+ * guy
+ * @class BI.Factory
+ */
+BI.Factory = {
+ parsePath: function parsePath (path) {
+ var segments = path.split('.');
+ return function (obj) {
+ for (var i = 0; i < segments.length; i++) {
+ if (!obj) {
+ return;
+ }
+ obj = obj[segments[i]];
+ }
+ return obj;
+ }
+ },
+ createView : function(url, viewFunc, mData, vData, context){
+ var modelFunc = viewFunc.replace(/View/, "Model");
+ modelFunc = this.parsePath(modelFunc)(window);
+ if(!_.isFunction(modelFunc)){
+ modelFunc = BI.Model;
+ }
+// try {
+ var model = new (modelFunc)(_.extend({}, mData, {
+ parent: context && context.model,
+ rootURL: url
+ }), {silent: true});
+// } catch (e) {
+//
+// }
+// try {
+ var view = new (eval(viewFunc))(_.extend({}, vData, {
+ model: model,
+ parent: context,
+ rootURL: url
+ }));
+// } catch (e) {
+//
+// }
+ return view;
+ }
+};(function (root, factory) {
+ root.BI = factory(root, root.BI || {}, root._, (root.jQuery || root.$));
+}(this, function (root, BI, _, $) {
+
+ var previousBI = root.BI;
+
+ // Create local references to array methods we'll want to use later.
+ var array = [];
+ var slice = array.slice;
+
+ // Current version of the library. Keep in sync with `package.json`.
+ BI.VERSION = '1.0.0';
+
+ // For BI's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
+ // the `$` variable.
+ BI.$ = $;
+
+ // Runs BI.js in *noConflict* mode, returning the `BI` variable
+ // to its previous owner. Returns a reference to this BI object.
+ BI.noConflict = function () {
+ root.BI = previousBI;
+ return this;
+ };
+
+ // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option
+ // will fake `"PATCH"`, `"PUT"` and `"DELETE"` requests via the `_method` parameter and
+ // set a `X-Http-Method-Override` header.
+ BI.emulateHTTP = true;
+
+ // Turn on `emulateJSON` to support legacy servers that can't deal with direct
+ // `application/json` requests ... this will encode the body as
+ // `application/x-www-form-urlencoded` instead and will send the model in a
+ // form param named `model`.
+ BI.emulateJSON = true;
+
+ // BI.Events
+ // ---------------
+
+ // A module that can be mixed in to *any object* in order to provide it with
+ // custom events. You may bind with `on` or remove with `off` callback
+ // functions to an event; `trigger`-ing an event fires all callbacks in
+ // succession.
+ //
+ // var object = {};
+ // _.extend(object, BI.Events);
+ // object.on('expand', function(){ alert('expanded'); });
+ // object.trigger('expand');
+ //
+ var Events = BI.Events = {
+
+ // Bind an event to a `callback` function. Passing `"all"` will bind
+ // the callback to all events fired.
+ on: function (name, callback, context) {
+ if (!eventsApi(this, 'on', name, [callback, context]) || !callback) return this;
+ this._events || (this._events = {});
+ var events = this._events[name] || (this._events[name] = []);
+ events.push({callback: callback, context: context, ctx: context || this});
+ return this;
+ },
+
+ // Bind an event to only be triggered a single time. After the first time
+ // the callback is invoked, it will be removed.
+ once: function (name, callback, context) {
+ if (!eventsApi(this, 'once', name, [callback, context]) || !callback) return this;
+ var self = this;
+ var once = _.once(function () {
+ self.off(name, once);
+ callback.apply(this, arguments);
+ });
+ once._callback = callback;
+ return this.on(name, once, context);
+ },
+
+ // Remove one or many callbacks. If `context` is null, removes all
+ // callbacks with that function. If `callback` is null, removes all
+ // callbacks for the event. If `name` is null, removes all bound
+ // callbacks for all events.
+ off: function (name, callback, context) {
+ if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this;
+
+ // Remove all callbacks for all events.
+ if (!name && !callback && !context) {
+ this._events = void 0;
+ return this;
+ }
+
+ var names = name ? [name] : _.keys(this._events);
+ for (var i = 0, length = names.length; i < length; i++) {
+ name = names[i];
+
+ // Bail out if there are no events stored.
+ var events = this._events[name];
+ if (!events) continue;
+
+ // Remove all callbacks for this event.
+ if (!callback && !context) {
+ delete this._events[name];
+ continue;
+ }
+
+ // Find any remaining events.
+ var remaining = [];
+ for (var j = 0, k = events.length; j < k; j++) {
+ var event = events[j];
+ if (
+ callback && callback !== event.callback &&
+ callback !== event.callback._callback ||
+ context && context !== event.context
+ ) {
+ remaining.push(event);
+ }
+ }
+
+ // Replace events if there are any remaining. Otherwise, clean up.
+ if (remaining.length) {
+ this._events[name] = remaining;
+ } else {
+ delete this._events[name];
+ }
+ }
+
+ return this;
+ },
+
+ un: function () {
+ this.off.apply(this, arguments);
+ },
+
+ // Trigger one or many events, firing all bound callbacks. Callbacks are
+ // passed the same arguments as `trigger` is, apart from the event name
+ // (unless you're listening on `"all"`, which will cause your callback to
+ // receive the true name of the event as the first argument).
+ trigger: function (name) {
+ if (!this._events) return this;
+ var args = slice.call(arguments, 1);
+ if (!eventsApi(this, 'trigger', name, args)) return this;
+ var events = this._events[name];
+ var allEvents = this._events.all;
+ if (events) triggerEvents(events, args);
+ if (allEvents) triggerEvents(allEvents, arguments);
+ return this;
+ },
+
+ fireEvent: function () {
+ this.trigger.apply(this, arguments);
+ },
+
+ // Inversion-of-control versions of `on` and `once`. Tell *this* object to
+ // listen to an event in another object ... keeping track of what it's
+ // listening to.
+ listenTo: function (obj, name, callback) {
+ var listeningTo = this._listeningTo || (this._listeningTo = {});
+ var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
+ listeningTo[id] = obj;
+ if (!callback && typeof name === 'object') callback = this;
+ obj.on(name, callback, this);
+ return this;
+ },
+
+ listenToOnce: function (obj, name, callback) {
+ if (typeof name === 'object') {
+ for (var event in name) this.listenToOnce(obj, event, name[event]);
+ return this;
+ }
+ if (eventSplitter.test(name)) {
+ var names = name.split(eventSplitter);
+ for (var i = 0, length = names.length; i < length; i++) {
+ this.listenToOnce(obj, names[i], callback);
+ }
+ return this;
+ }
+ if (!callback) return this;
+ var once = _.once(function () {
+ this.stopListening(obj, name, once);
+ callback.apply(this, arguments);
+ });
+ once._callback = callback;
+ return this.listenTo(obj, name, once);
+ },
+
+ // Tell this object to stop listening to either specific events ... or
+ // to every object it's currently listening to.
+ stopListening: function (obj, name, callback) {
+ var listeningTo = this._listeningTo;
+ if (!listeningTo) return this;
+ var remove = !name && !callback;
+ if (!callback && typeof name === 'object') callback = this;
+ if (obj) (listeningTo = {})[obj._listenId] = obj;
+ for (var id in listeningTo) {
+ obj = listeningTo[id];
+ obj.off(name, callback, this);
+ if (remove || _.isEmpty(obj._events)) delete this._listeningTo[id];
+ }
+ return this;
+ }
+
+ };
+
+ // Regular expression used to split event strings.
+ var eventSplitter = /\s+/;
+
+ // Implement fancy features of the Events API such as multiple event
+ // names `"change blur"` and jQuery-style event maps `{change: action}`
+ // in terms of the existing API.
+ var eventsApi = function (obj, action, name, rest) {
+ if (!name) return true;
+
+ // Handle event maps.
+ if (typeof name === 'object') {
+ for (var key in name) {
+ obj[action].apply(obj, [key, name[key]].concat(rest));
+ }
+ return false;
+ }
+
+ // Handle space separated event names.
+ if (eventSplitter.test(name)) {
+ var names = name.split(eventSplitter);
+ for (var i = 0, length = names.length; i < length; i++) {
+ obj[action].apply(obj, [names[i]].concat(rest));
+ }
+ return false;
+ }
+
+ return true;
+ };
+
+ // A difficult-to-believe, but optimized internal dispatch function for
+ // triggering events. Tries to keep the usual cases speedy (most internal
+ // BI events have 3 arguments).
+ var triggerEvents = function (events, args) {
+ var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2];
+ switch (args.length) {
+ case 0:
+ while (++i < l) (ev = events[i]).callback.call(ev.ctx);
+ return;
+ case 1:
+ while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1);
+ return;
+ case 2:
+ while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2);
+ return;
+ case 3:
+ while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3);
+ return;
+ default:
+ while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args);
+ return;
+ }
+ };
+
+ // Aliases for backwards compatibility.
+ Events.bind = Events.on;
+ Events.unbind = Events.off;
+
+ // Allow the `BI` object to serve as a global event bus, for folks who
+ // want global "pubsub" in a convenient place.
+ _.extend(BI, Events);
+
+ // BI.M
+ // --------------
+
+ // BI **Models** are the basic data object in the framework --
+ // frequently representing a row in a table in a database on your server.
+ // A discrete chunk of data and a bunch of useful, related methods for
+ // performing computations and transformations on that data.
+
+ // Create a new model with the specified attributes. A client id (`cid`)
+ // is automatically generated and assigned for you.
+ var M = BI.M = function (attributes, options) {
+ var attrs = attributes || {};
+ options = options || {};
+ this.cid = _.uniqueId('c');
+ this.attributes = {};
+ if (options.collection) this.collection = options.collection;
+ if (options.parse) attrs = this.parse(attrs, options) || {};
+ this.options = attrs = _.defaults({}, attrs, _.result(this, '_defaultConfig'));
+ _.extend(this, _.pick(this.options, modelOptions));
+ this.set(attrs, options);
+ this.changed = {};
+ this._init.apply(this, arguments);
+ };
+
+ var modelOptions = ['rootURL', 'parent', 'data', 'id'];
+
+ // Attach all inheritable methods to the M prototype.
+ _.extend(M.prototype, Events, {
+
+ // A hash of attributes whose current and previous value differ.
+ changed: null,
+
+ // The value returned during the last failed validation.
+ validationError: null,
+
+ // The default name for the JSON `id` attribute is `"id"`. MongoDB and
+ // CouchDB users may want to set this to `"_id"`.
+ idAttribute: 'ID',
+
+ _defaultConfig: function () {
+ return {}
+ },
+
+ // _init is an empty function by default. Override it with your own
+ // initialization logic.
+ _init: function () {
+ },
+
+ // Return a copy of the model's `attributes` object.
+ toJSON: function (options) {
+ return _.clone(this.attributes);
+ },
+
+ // Proxy `BI.sync` by default -- but override this if you need
+ // custom syncing semantics for *this* particular model.
+ sync: function () {
+ return BI.sync.apply(this, arguments);
+ },
+
+ // Get the value of an attribute.
+ get: function (attr) {
+ return this.attributes[attr];
+ },
+
+ // Get the HTML-escaped value of an attribute.
+ escape: function (attr) {
+ return _.escape(this.get(attr));
+ },
+
+ // Returns `true` if the attribute contains a value that is not null
+ // or undefined.
+ has: function (attr) {
+ return _.has(this.attributes, attr);
+ },
+
+ // Special-cased proxy to underscore's `_.matches` method.
+ matches: function (attrs) {
+ var keys = _.keys(attrs), length = keys.length;
+ var obj = Object(this.attributes);
+ for (var i = 0; i < length; i++) {
+ var key = keys[i];
+ if (!_.isEqual(attrs[key], obj[key]) || !(key in obj)) return false;
+ }
+ return true;
+ },
+
+ // Set a hash of model attributes on the object, firing `"change"`. This is
+ // the core primitive operation of a model, updating the data and notifying
+ // anyone who needs to know about the change in state. The heart of the beast.
+ set: function (key, val, options) {
+ var attr, attrs, unset, changes, silent, changing, changed, prev, current;
+ if (key == null) return this;
+
+ // Handle both `"key", value` and `{key: value}` -style arguments.
+ if (typeof key === 'object') {
+ attrs = key;
+ options = val;
+ } else {
+ (attrs = {})[key] = val;
+ }
+
+ options || (options = {});
+
+ // Run validation.
+ if (!this._validate(attrs, options)) return false;
+
+ // Extract attributes and options.
+ unset = options.unset;
+ silent = options.silent;
+ changes = [];
+ changing = this._changing;
+ this._changing = true;
+
+ if (!changing) {
+ this._previousAttributes = _.clone(this.attributes);
+ this.changed = {};
+ }
+ current = this.attributes, prev = this._previousAttributes;
+
+ // Check for changes of `id`.
+ if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];
+
+ // For each `set` attribute, update or delete the current value.
+ for (attr in attrs) {
+ val = attrs[attr];
+ if (!_.isEqual(current[attr], val)) changes.push(attr);
+ if (!_.isEqual(prev[attr], val)) {
+ this.changed[attr] = val;
+ } else {
+ delete this.changed[attr];
+ }
+ unset ? delete current[attr] : current[attr] = val;
+ }
+
+ // Trigger all relevant attribute changes.
+ if (!silent) {
+ if (changes.length) this._pending = options;
+ for (var i = 0, length = changes.length; i < length; i++) {
+ this.trigger('change:' + changes[i], this, current[changes[i]], options);
+ }
+ }
+
+ // You might be wondering why there's a `while` loop here. Changes can
+ // be recursively nested within `"change"` events.
+ if (changing) return this;
+ changed = BI.clone(this.changed);
+ if (!silent) {
+ while (this._pending) {
+ options = this._pending;
+ this._pending = false;
+ this.trigger('change', changed, prev, this, options);
+ }
+ }
+ this._pending = false;
+ this._changing = false;
+ if (!silent && changes.length) this.trigger("changed", changed, prev, this, options);
+ return this;
+ },
+
+ // Remove an attribute from the model, firing `"change"`. `unset` is a noop
+ // if the attribute doesn't exist.
+ unset: function (attr, options) {
+ return this.set(attr, void 0, _.extend({}, options, {unset: true}));
+ },
+
+ // Clear all attributes on the model, firing `"change"`.
+ clear: function (options) {
+ var attrs = {};
+ for (var key in this.attributes) attrs[key] = void 0;
+ return this.set(attrs, _.extend({}, options, {unset: true}));
+ },
+
+ // Determine if the model has changed since the last `"change"` event.
+ // If you specify an attribute name, determine if that attribute has changed.
+ hasChanged: function (attr) {
+ if (attr == null) return !_.isEmpty(this.changed);
+ return _.has(this.changed, attr);
+ },
+
+ // Return an object containing all the attributes that have changed, or
+ // false if there are no changed attributes. Useful for determining what
+ // parts of a view need to be updated and/or what attributes need to be
+ // persisted to the server. Unset attributes will be set to undefined.
+ // You can also pass an attributes object to diff against the model,
+ // determining if there *would be* a change.
+ changedAttributes: function (diff) {
+ if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
+ var val, changed = false;
+ var old = this._changing ? this._previousAttributes : this.attributes;
+ for (var attr in diff) {
+ if (_.isEqual(old[attr], (val = diff[attr]))) continue;
+ (changed || (changed = {}))[attr] = val;
+ }
+ return changed;
+ },
+
+ // Get the previous value of an attribute, recorded at the time the last
+ // `"change"` event was fired.
+ previous: function (attr) {
+ if (attr == null || !this._previousAttributes) return null;
+ return this._previousAttributes[attr];
+ },
+
+ // Get all of the attributes of the model at the time of the previous
+ // `"change"` event.
+ previousAttributes: function () {
+ return _.clone(this._previousAttributes);
+ },
+
+ // Fetch the model from the server. If the server's representation of the
+ // model differs from its current attributes, they will be overridden,
+ // triggering a `"change"` event.
+ fetch: function (options) {
+ options = options ? _.clone(options) : {};
+ if (options.parse === void 0) options.parse = true;
+ var model = this;
+ var success = options.success;
+ options.success = function (resp) {
+ if (!options.noset) {
+ if (!model.set(model.parse(resp, options), options)) return false;
+ }
+ if (success) success(resp, model, options);
+ model.trigger('sync', resp, model, options).trigger('read', resp, model, options);
+ };
+ wrapError(this, options);
+ return this.sync('read', this, options);
+ },
+
+ // Set a hash of model attributes, and sync the model to the server.
+ // If the server returns an attributes hash that differs, the model's
+ // state will be `set` again.
+ save: function (key, val, options) {
+ var attrs, method, xhr, attributes = this.attributes;
+
+ // Handle both `"key", value` and `{key: value}` -style arguments.
+ if (key == null || typeof key === 'object') {
+ attrs = key;
+ options = val;
+ } else {
+ (attrs = {})[key] = val;
+ }
+
+ options = _.extend({validate: true}, options);
+
+ // If we're not waiting and attributes exist, save acts as
+ // `set(attr).save(null, opts)` with validation. Otherwise, check if
+ // the model will be valid when the attributes, if any, are set.
+ if (attrs && !options.wait) {
+ if (!this.set(attrs, options)) return false;
+ } else {
+ if (!this._validate(attrs, options)) return false;
+ }
+
+ // Set temporary attributes if `{wait: true}`.
+ if (attrs && options.wait) {
+ this.attributes = _.extend({}, attributes, attrs);
+ }
+
+ // After a successful server-side save, the client is (optionally)
+ // updated with the server-side state.
+ if (options.parse === void 0) options.parse = true;
+ var model = this;
+ var success = options.success;
+ options.success = function (resp) {
+ // Ensure attributes are restored during synchronous saves.
+ model.attributes = attributes;
+ var serverAttrs = model.parse(resp, options);
+ if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs);
+ if (_.isObject(serverAttrs) && !options.noset && !model.set(serverAttrs, options)) {
+ return false;
+ }
+ if (success) success(resp, model, options);
+ model.trigger('sync', resp, model, options)
+ .trigger((options.patch ? 'patch' : 'update'), resp, model, options);
+ };
+ wrapError(this, options);
+
+ method = /**this.isNew() ? 'create' :**/ (options.patch ? 'patch' : 'update');
+ if (method === 'patch' && !options.attrs) options.attrs = attrs;
+ xhr = this.sync(method, this, options);
+
+ // Restore attributes.
+ if (attrs && options.wait) this.attributes = attributes;
+
+ return xhr;
+ },
+
+ // Destroy this model on the server if it was already persisted.
+ // Optimistically removes the model from its collection, if it has one.
+ // If `wait: true` is passed, waits for the server to respond before removal.
+ destroy: function (options) {
+ options = options ? _.clone(options) : {};
+ var model = this;
+ var success = options.success;
+
+ var destroy = function () {
+ model.stopListening();
+ model.trigger('destroy', model.collection, model, options);
+ };
+
+ options.success = function (resp) {
+ if (options.wait || model.isNew()) destroy();
+ if (success) success(resp, model, options);
+ if (!model.isNew()) model.trigger('sync', resp, model, options).trigger('delete', resp, model, options);
+ };
+
+ if (this.isNew()) {
+ options.success();
+ return false;
+ }
+ wrapError(this, options);
+
+ var xhr = this.sync('delete', this, options);
+ if (!options.wait) destroy();
+ return xhr;
+ },
+
+ // Default URL for the model's representation on the server -- if you're
+ // using BI's restful methods, override this to change the endpoint
+ // that will be called.
+ url: function () {
+ var base =
+ _.result(this.collection, 'url');
+ if (this.isNew()) return base;
+ return base.replace(/([^\/])$/, '$1/') + encodeURIComponent(this.id);
+ },
+
+ // **parse** converts a response into the hash of attributes to be `set` on
+ // the model. The default implementation is just to pass the response along.
+ parse: function (resp, options) {
+ return resp;
+ },
+
+ // Create a new model with identical attributes to this one.
+ clone: function () {
+ return new this.constructor(this.attributes);
+ },
+
+ // A model is new if it has never been saved to the server, and lacks an id.
+ isNew: function () {
+ return !this.has(this.idAttribute);
+ },
+
+ // Check if the model is currently in a valid state.
+ isValid: function (options) {
+ return this._validate({}, _.extend(options || {}, {validate: true}));
+ },
+
+ // Run validation against the next complete set of model attributes,
+ // returning `true` if all is well. Otherwise, fire an `"invalid"` event.
+ _validate: function (attrs, options) {
+ if (!options.validate || !this.validate) return true;
+ attrs = _.extend({}, this.attributes, attrs);
+ var error = this.validationError = this.validate(attrs, options) || null;
+ if (!error) return true;
+ this.trigger('invalid', error, this, _.extend(options, {validationError: error}));
+ return false;
+ }
+
+ });
+
+ // Underscore methods that we want to implement on the M.
+ var modelMethods = ['keys', 'values', 'pairs', 'invert', 'pick', 'omit', 'chain', 'isEmpty'];
+
+ // Mix in each Underscore method as a proxy to `M#attributes`.
+ _.each(modelMethods, function (method) {
+ if (!_[method]) return;
+ M.prototype[method] = function () {
+ var args = slice.call(arguments);
+ args.unshift(this.attributes);
+ return _[method].apply(_, args);
+ };
+ });
+
+ // BI.Collection
+ // -------------------
+
+ // If models tend to represent a single row of data, a BI Collection is
+ // more analogous to a table full of data ... or a small slice or page of that
+ // table, or a collection of rows that belong together for a particular reason
+ // -- all of the messages in this particular folder, all of the documents
+ // belonging to this particular author, and so on. Collections maintain
+ // indexes of their models, both in order, and for lookup by `id`.
+
+ // Create a new **Collection**, perhaps to contain a specific type of `model`.
+ // If a `comparator` is specified, the Collection will maintain
+ // its models in sort order, as they're added and removed.
+ var Collection = BI.Collection = function (models, options) {
+ this.options = options = options || {};
+ if (options.model) this.model = options.model;
+ if (options.comparator !== void 0) this.comparator = options.comparator;
+ this._reset();
+ this._init.apply(this, arguments);
+ if (models) this.reset(models, _.extend({silent: true}, options));
+ };
+
+ // Default options for `Collection#set`.
+ var setOptions = {add: true, remove: true, merge: true};
+ var addOptions = {add: true, remove: false};
+
+ // Define the Collection's inheritable methods.
+ _.extend(Collection.prototype, Events, {
+
+ // The default model for a collection is just a **BI.M**.
+ // This should be overridden in most cases.
+ model: M,
+
+ // _init is an empty function by default. Override it with your own
+ // initialization logic.
+ _init: function () {
+ },
+
+ // The JSON representation of a Collection is an array of the
+ // models' attributes.
+ toJSON: function (options) {
+ return this.map(function (model) {
+ return model.toJSON(options);
+ });
+ },
+
+ // Proxy `BI.sync` by default.
+ sync: function () {
+ return BI.sync.apply(this, arguments);
+ },
+
+ // Add a model, or list of models to the set.
+ add: function (models, options) {
+ return this.set(models, _.extend({merge: false}, options, addOptions));
+ },
+
+ // Remove a model, or a list of models from the set.
+ remove: function (models, options) {
+ var singular = !_.isArray(models);
+ models = singular ? [models] : _.clone(models);
+ options || (options = {});
+ for (var i = 0, length = models.length; i < length; i++) {
+ var model = models[i] = this.get(models[i]);
+ if (!model) continue;
+ var id = this.modelId(model.attributes);
+ if (id != null) delete this._byId[id];
+ delete this._byId[model.cid];
+ var index = this.indexOf(model);
+ this.models.splice(index, 1);
+ this.length--;
+ if (!options.silent) {
+ options.index = index;
+ model.trigger('remove', model, this, options);
+ }
+ this._removeReference(model, options);
+ }
+ return singular ? models[0] : models;
+ },
+
+ // Update a collection by `set`-ing a new list of models, adding new ones,
+ // removing models that are no longer present, and merging models that
+ // already exist in the collection, as necessary. Similar to **M#set**,
+ // the core operation for updating the data contained by the collection.
+ set: function (models, options) {
+ options = _.defaults({}, options, setOptions);
+ if (options.parse) models = this.parse(models, options);
+ var singular = !_.isArray(models);
+ models = singular ? (models ? [models] : []) : models.slice();
+ var id, model, attrs, existing, sort;
+ var at = options.at;
+ if (at != null) at = +at;
+ if (at < 0) at += this.length + 1;
+ var sortable = this.comparator && (at == null) && options.sort !== false;
+ var sortAttr = _.isString(this.comparator) ? this.comparator : null;
+ var toAdd = [], toRemove = [], modelMap = {};
+ var add = options.add, merge = options.merge, remove = options.remove;
+ var order = !sortable && add && remove ? [] : false;
+ var orderChanged = false;
+
+ // Turn bare objects into model references, and prevent invalid models
+ // from being added.
+ for (var i = 0, length = models.length; i < length; i++) {
+ attrs = models[i];
+
+ // If a duplicate is found, prevent it from being added and
+ // optionally merge it into the existing model.
+ if (existing = this.get(attrs)) {
+ if (remove) modelMap[existing.cid] = true;
+ if (merge && attrs !== existing) {
+ attrs = this._isModel(attrs) ? attrs.attributes : attrs;
+ if (options.parse) attrs = existing.parse(attrs, options);
+ existing.set(attrs, options);
+ if (sortable && !sort && existing.hasChanged(sortAttr)) sort = true;
+ }
+ models[i] = existing;
+
+ // If this is a new, valid model, push it to the `toAdd` list.
+ } else if (add) {
+ model = models[i] = this._prepareModel(attrs, options);
+ if (!model) continue;
+ toAdd.push(model);
+ this._addReference(model, options);
+ }
+
+ // Do not add multiple models with the same `id`.
+ model = existing || model;
+ if (!model) continue;
+ id = this.modelId(model.attributes);
+ if (order && (model.isNew() || !modelMap[id])) {
+ order.push(model);
+
+ // Check to see if this is actually a new model at this index.
+ orderChanged = orderChanged || !this.models[i] || model.cid !== this.models[i].cid;
+ }
+
+ modelMap[id] = true;
+ }
+
+ // Remove nonexistent models if appropriate.
+ if (remove) {
+ for (var i = 0, length = this.length; i < length; i++) {
+ if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model);
+ }
+ if (toRemove.length) this.remove(toRemove, options);
+ }
+
+ // See if sorting is needed, update `length` and splice in new models.
+ if (toAdd.length || orderChanged) {
+ if (sortable) sort = true;
+ this.length += toAdd.length;
+ if (at != null) {
+ for (var i = 0, length = toAdd.length; i < length; i++) {
+ this.models.splice(at + i, 0, toAdd[i]);
+ }
+ } else {
+ if (order) this.models.length = 0;
+ var orderedModels = order || toAdd;
+ for (var i = 0, length = orderedModels.length; i < length; i++) {
+ this.models.push(orderedModels[i]);
+ }
+ }
+ }
+
+ // Silently sort the collection if appropriate.
+ if (sort) this.sort({silent: true});
+
+ // Unless silenced, it's time to fire all appropriate add/sort events.
+ if (!options.silent) {
+ var addOpts = at != null ? _.clone(options) : options;
+ for (var i = 0, length = toAdd.length; i < length; i++) {
+ if (at != null) addOpts.index = at + i;
+ (model = toAdd[i]).trigger('add', model, this, addOpts);
+ }
+ if (sort || orderChanged) this.trigger('sort', this, options);
+ }
+
+ // Return the added (or merged) model (or models).
+ return singular ? models[0] : models;
+ },
+
+ // When you have more items than you want to add or remove individually,
+ // you can reset the entire set with a new list of models, without firing
+ // any granular `add` or `remove` events. Fires `reset` when finished.
+ // Useful for bulk operations and optimizations.
+ reset: function (models, options) {
+ options = options ? _.clone(options) : {};
+ for (var i = 0, length = this.models.length; i < length; i++) {
+ this._removeReference(this.models[i], options);
+ }
+ options.previousModels = this.models;
+ this._reset();
+ models = this.add(models, _.extend({silent: true}, options));
+ if (!options.silent) this.trigger('reset', this, options);
+ return models;
+ },
+
+ // Add a model to the end of the collection.
+ push: function (model, options) {
+ return this.add(model, _.extend({at: this.length}, options));
+ },
+
+ // Remove a model from the end of the collection.
+ pop: function (options) {
+ var model = this.at(this.length - 1);
+ this.remove(model, options);
+ return model;
+ },
+
+ // Add a model to the beginning of the collection.
+ unshift: function (model, options) {
+ return this.add(model, _.extend({at: 0}, options));
+ },
+
+ // Remove a model from the beginning of the collection.
+ shift: function (options) {
+ var model = this.at(0);
+ this.remove(model, options);
+ return model;
+ },
+
+ // Slice out a sub-array of models from the collection.
+ slice: function () {
+ return slice.apply(this.models, arguments);
+ },
+
+ // Get a model from the set by id.
+ get: function (obj) {
+ if (obj == null) return void 0;
+ var id = this.modelId(this._isModel(obj) ? obj.attributes : obj);
+ return this._byId[obj] || this._byId[id] || this._byId[obj.cid];
+ },
+
+ // Get the model at the given index.
+ at: function (index) {
+ if (index < 0) index += this.length;
+ return this.models[index];
+ },
+
+ // Return models with matching attributes. Useful for simple cases of
+ // `filter`.
+ where: function (attrs, first) {
+ var matches = _.matches(attrs);
+ return this[first ? 'find' : 'filter'](function (model) {
+ return matches(model.attributes);
+ });
+ },
+
+ // Return the first model with matching attributes. Useful for simple cases
+ // of `find`.
+ findWhere: function (attrs) {
+ return this.where(attrs, true);
+ },
+
+ // Force the collection to re-sort itself. You don't need to call this under
+ // normal circumstances, as the set will maintain sort order as each item
+ // is added.
+ sort: function (options) {
+ if (!this.comparator) throw new Error('Cannot sort a set without a comparator');
+ options || (options = {});
+
+ // Run sort based on type of `comparator`.
+ if (_.isString(this.comparator) || this.comparator.length === 1) {
+ this.models = this.sortBy(this.comparator, this);
+ } else {
+ this.models.sort(_.bind(this.comparator, this));
+ }
+
+ if (!options.silent) this.trigger('sort', this, options);
+ return this;
+ },
+
+ // Pluck an attribute from each model in the collection.
+ pluck: function (attr) {
+ return _.invoke(this.models, 'get', attr);
+ },
+
+ // Fetch the default set of models for this collection, resetting the
+ // collection when they arrive. If `reset: true` is passed, the response
+ // data will be passed through the `reset` method instead of `set`.
+ fetch: function (options) {
+ options = options ? _.clone(options) : {};
+ if (options.parse === void 0) options.parse = true;
+ var success = options.success;
+ var collection = this;
+ options.success = function (resp) {
+ var method = options.reset ? 'reset' : 'set';
+ collection[method](resp, options);
+ if (success) success(collection, resp, options);
+ collection.trigger('sync', collection, resp, options);
+ };
+ wrapError(this, options);
+ return this.sync('read', this, options);
+ },
+
+ // Create a new instance of a model in this collection. Add the model to the
+ // collection immediately, unless `wait: true` is passed, in which case we
+ // wait for the server to agree.
+ create: function (model, options) {
+ options = options ? _.clone(options) : {};
+ if (!(model = this._prepareModel(model, options))) return false;
+ if (!options.wait) this.add(model, options);
+ var collection = this;
+ var success = options.success;
+ options.success = function (model, resp) {
+ if (options.wait) collection.add(model, options);
+ if (success) success(model, resp, options);
+ };
+ model.save(null, options);
+ return model;
+ },
+
+ // **parse** converts a response into a list of models to be added to the
+ // collection. The default implementation is just to pass it through.
+ parse: function (resp, options) {
+ return resp;
+ },
+
+ // Create a new collection with an identical list of models as this one.
+ clone: function () {
+ return new this.constructor(this.models, {
+ model: this.model,
+ comparator: this.comparator
+ });
+ },
+
+ // Define how to uniquely identify models in the collection.
+ modelId: function (attrs) {
+ return attrs[this.model.prototype.idAttribute || 'id'];
+ },
+
+ // Private method to reset all internal state. Called when the collection
+ // is first _initd or reset.
+ _reset: function () {
+ this.length = 0;
+ this.models = [];
+ this._byId = {};
+ },
+
+ // Prepare a hash of attributes (or other model) to be added to this
+ // collection.
+ _prepareModel: function (attrs, options) {
+ if (this._isModel(attrs)) {
+ if (!attrs.collection) attrs.collection = this;
+ return attrs;
+ }
+ options = options ? _.clone(options) : {};
+ options.collection = this;
+ var model = new this.model(attrs, options);
+ if (!model.validationError) return model;
+ this.trigger('invalid', this, model.validationError, options);
+ return false;
+ },
+
+ // Method for checking whether an object should be considered a model for
+ // the purposes of adding to the collection.
+ _isModel: function (model) {
+ return model instanceof M;
+ },
+
+ // Internal method to create a model's ties to a collection.
+ _addReference: function (model, options) {
+ this._byId[model.cid] = model;
+ var id = this.modelId(model.attributes);
+ if (id != null) this._byId[id] = model;
+ model.on('all', this._onModelEvent, this);
+ },
+
+ // Internal method to sever a model's ties to a collection.
+ _removeReference: function (model, options) {
+ if (this === model.collection) delete model.collection;
+ model.off('all', this._onModelEvent, this);
+ },
+
+ // Internal method called every time a model in the set fires an event.
+ // Sets need to update their indexes when models change ids. All other
+ // events simply proxy through. "add" and "remove" events that originate
+ // in other collections are ignored.
+ _onModelEvent: function (event, model, collection, options) {
+ if ((event === 'add' || event === 'remove') && collection !== this) return;
+ if (event === 'destroy') this.remove(model, options);
+ if (event === 'change') {
+ var prevId = this.modelId(model.previousAttributes());
+ var id = this.modelId(model.attributes);
+ if (prevId !== id) {
+ if (prevId != null) delete this._byId[prevId];
+ if (id != null) this._byId[id] = model;
+ }
+ }
+ this.trigger.apply(this, arguments);
+ }
+
+ });
+
+ // Underscore methods that we want to implement on the Collection.
+ // 90% of the core usefulness of BI Collections is actually implemented
+ // right here:
+ var methods = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl',
+ 'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select',
+ 'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke',
+ 'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest',
+ 'tail', 'drop', 'last', 'without', 'difference', 'indexOf', 'shuffle',
+ 'lastIndexOf', 'isEmpty', 'chain', 'sample', 'partition'];
+
+ // Mix in each Underscore method as a proxy to `Collection#models`.
+ _.each(methods, function (method) {
+ if (!_[method]) return;
+ Collection.prototype[method] = function () {
+ var args = slice.call(arguments);
+ args.unshift(this.models);
+ return _[method].apply(_, args);
+ };
+ });
+
+ // Underscore methods that take a property name as an argument.
+ var attributeMethods = ['groupBy', 'countBy', 'sortBy', 'indexBy'];
+
+ // Use attributes instead of properties.
+ _.each(attributeMethods, function (method) {
+ if (!_[method]) return;
+ Collection.prototype[method] = function (value, context) {
+ var iterator = _.isFunction(value) ? value : function (model) {
+ return model.get(value);
+ };
+ return _[method](this.models, iterator, context);
+ };
+ });
+
+ // BI.V
+ // -------------
+
+ // BI Views are almost more convention than they are actual code. A V
+ // is simply a JavaScript object that represents a logical chunk of UI in the
+ // DOM. This might be a single item, an entire list, a sidebar or panel, or
+ // even the surrounding frame which wraps your whole app. Defining a chunk of
+ // UI as a **V** allows you to define your DOM events declaratively, without
+ // having to worry about render order ... and makes it easy for the view to
+ // react to specific changes in the state of your models.
+
+ // Creating a BI.V creates its initial element outside of the DOM,
+ // if an existing element is not provided...
+ var V = BI.V = function (options) {
+ this.cid = _.uniqueId('view');
+ options = options || {};
+ this.options = _.defaults(options, _.result(this, '_defaultConfig'));
+ _.extend(this, _.pick(this.options, viewOptions));
+ this._ensureElement();
+ this._init.apply(this, arguments);
+ };
+
+ // Cached regex to split keys for `delegate`.
+ var delegateEventSplitter = /^(\S+)\s*(.*)$/;
+
+ // List of view options to be merged as properties.
+ var viewOptions = ['rootURL', 'model', 'parent', 'collection', 'element', 'id', 'attributes', 'baseCls', 'tagName', 'events'];
+
+ // Set up all inheritable **BI.V** properties and methods.
+ _.extend(V.prototype, Events, {
+
+ // The default `tagName` of a V's element is `"div"`.
+ tagName: 'div',
+
+ // jQuery delegate for element lookup, scoped to DOM elements within the
+ // current view. This should be preferred to global lookups where possible.
+ $: function (selector) {
+ return this.$el.find(selector);
+ },
+
+ _defaultConfig: function () {
+ return {}
+ },
+
+ // _init is an empty function by default. Override it with your own
+ // initialization logic.
+ _init: function () {
+ },
+
+ //容器,默认放在this.element上
+ _vessel: function () {
+ return this
+ },
+ // **render** is the core function that your view should override, in order
+ // to populate its element (`this.el`), with the appropriate HTML. The
+ // convention is for **render** to always return `this`.
+ render: function (vessel) {
+ return this;
+ },
+
+ // Remove this view by taking the element out of the DOM, and removing any
+ // applicable BI.Events listeners.
+ remove: function () {
+ this._removeElement();
+ this.stopListening();
+ return this;
+ },
+
+ // Remove this view's element from the document and all event listeners
+ // attached to it. Exposed for subclasses using an alternative DOM
+ // manipulation API.
+ _removeElement: function () {
+ this.$el.remove();
+ if ($.browser.msie === true) {
+ this.el.outerHTML = '';
+ }
+ },
+
+ // Change the view's element (`this.el` property) and re-delegate the
+ // view's events on the new element.
+ setElement: function (element) {
+ this.undelegateEvents();
+ this._setElement(element);
+ this.vessel = this._vessel();
+ this.render(this.vessel);
+ this.delegateEvents();
+ return this;
+ },
+
+ setVisible: function (visible) {
+ this.options.invisible = !visible;
+ if (visible) {
+ this.element.css("display", "");
+ } else {
+ this.element.css("display", "none");
+ }
+ },
+
+ isVisible: function () {
+ return !this.options.invisible;
+ },
+
+ visible: function () {
+ this.setVisible(true);
+ },
+
+ invisible: function () {
+ this.setVisible(false);
+ },
+
+ // Creates the `this.el` and `this.$el` references for this view using the
+ // given `el`. `el` can be a CSS selector or an HTML string, a jQuery
+ // context or an element. Subclasses can override this to utilize an
+ // alternative DOM manipulation API and are only required to set the
+ // `this.el` property.
+ _setElement: function (el) {
+ this.$el = el instanceof BI.$ ? el : BI.$(el);
+ this.element = this.$el;
+ this.el = this.$el[0];
+ },
+
+ // Set callbacks, where `this.events` is a hash of
+ //
+ // *{"event selector": "callback"}*
+ //
+ // {
+ // 'mousedown .title': 'edit',
+ // 'click .button': 'save',
+ // 'click .open': function(e) { ... }
+ // }
+ //
+ // pairs. Callbacks will be bound to the view, with `this` set properly.
+ // Uses event delegation for efficiency.
+ // Omitting the selector binds the event to `this.el`.
+ delegateEvents: function (events) {
+ if (!(events || (events = _.result(this, 'events')))) return this;
+ this.undelegateEvents();
+ for (var key in events) {
+ var method = events[key];
+ if (!_.isFunction(method)) method = this[events[key]];
+ if (!method) continue;
+ var match = key.match(delegateEventSplitter);
+ this.delegate(match[1], match[2], _.bind(method, this));
+ }
+ return this;
+ },
+
+ // Add a single event listener to the view's element (or a child element
+ // using `selector`). This only works for delegate-able events: not `focus`,
+ // `blur`, and not `change`, `submit`, and `reset` in Internet Explorer.
+ delegate: function (eventName, selector, listener) {
+ this.vessel.element.on(eventName + '.delegateEvents' + this.cid, selector, listener);
+ },
+
+ // Clears all callbacks previously bound to the view by `delegateEvents`.
+ // You usually don't need to use this, but may wish to if you have multiple
+ // BI views attached to the same DOM element.
+ undelegateEvents: function () {
+ if (this.vessel) this.vessel.element.off('.delegateEvents' + this.cid);
+ return this;
+ },
+
+ // A finer-grained `undelegateEvents` for removing a single delegated event.
+ // `selector` and `listener` are both optional.
+ undelegate: function (eventName, selector, listener) {
+ this.vessel.element.off(eventName + '.delegateEvents' + this.cid, selector, listener);
+ },
+
+ // Produces a DOM element to be assigned to your view. Exposed for
+ // subclasses using an alternative DOM manipulation API.
+ _createElement: function (tagName) {
+ return document.createElement(tagName);
+ },
+
+ // Ensure that the V has a DOM element to render into.
+ // If `this.el` is a string, pass it through `$()`, take the first
+ // matching element, and re-assign it to `el`. Otherwise, create
+ // an element from the `id`, `className` and `tagName` properties.
+ _ensureElement: function () {
+ var attrs = _.extend({}, _.result(this, 'attributes'));
+ if (this.baseCls) attrs['class'] = _.result(this, 'baseCls');
+ if (!this.element) {
+ this.setElement(this._createElement(_.result(this, 'tagName')));
+ } else {
+ this.setElement(_.result(this, 'element'));
+ }
+ this._setAttributes(attrs);
+ },
+
+ // Set attributes from a hash on this view's element. Exposed for
+ // subclasses using an alternative DOM manipulation API.
+ _setAttributes: function (attributes) {
+ this.$el.attr(attributes);
+ }
+
+ });
+
+ // BI.sync
+ // -------------
+
+ // Override this function to change the manner in which BI persists
+ // models to the server. You will be passed the type of request, and the
+ // model in question. By default, makes a RESTful Ajax request
+ // to the model's `url()`. Some possible customizations could be:
+ //
+ // * Use `setTimeout` to batch rapid-fire updates into a single request.
+ // * Send up the models as XML instead of JSON.
+ // * Persist models via WebSockets instead of Ajax.
+ //
+ // Turn on `BI.emulateHTTP` in order to send `PUT` and `DELETE` requests
+ // as `POST`, with a `_method` parameter containing the true HTTP method,
+ // as well as all requests with the body as `application/x-www-form-urlencoded`
+ // instead of `application/json` with the model in a param named `model`.
+ // Useful when interfacing with server-side languages like **PHP** that make
+ // it difficult to read the body of `PUT` requests.
+ BI.sync = function (method, model, options) {
+ var type = methodMap[method];
+
+ // Default options, unless specified.
+ _.defaults(options || (options = {}), {
+ emulateHTTP: BI.emulateHTTP,
+ emulateJSON: BI.emulateJSON
+ });
+
+ // Default JSON-request options.
+ var params = {type: type, dataType: 'json'};
+
+ // Ensure that we have a URL.
+ if (!options.url) {
+ params.url = _.result(model, method + "URL") || _.result(model, 'url');
+ if (!params.url) {
+ return;
+ }
+ }
+
+ // Ensure that we have the appropriate request data.
+ if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
+ params.contentType = 'application/json';
+ params.data = _.extend({id: model.id}, model.toJSON(options), options.attrs);
+ }
+
+ // For older servers, emulate JSON by encoding the request into an HTML-form.
+ if (options.emulateJSON) {
+ params.contentType = 'application/x-www-form-urlencoded';
+ params.data = options.data ? options.data : params.data;
+ }
+
+ // For older servers, emulate HTTP by mimicking the HTTP method with `_method`
+ // And an `X-HTTP-Method-Override` header.
+ if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) {
+ params.type = 'POST';
+ if (options.emulateJSON) params.data._method = type;
+ var beforeSend = options.beforeSend;
+ options.beforeSend = function (xhr) {
+ xhr.setRequestHeader('X-HTTP-Method-Override', type);
+ if (beforeSend) return beforeSend.apply(this, arguments);
+ };
+ }
+
+ // Don't process data on a non-GET request.
+ if (params.type !== 'GET' && !options.emulateJSON) {
+ params.processData = false;
+ }
+
+ // Pass along `textStatus` and `errorThrown` from jQuery.
+ var error = options.error;
+ options.error = function (xhr, textStatus, errorThrown) {
+ options.textStatus = textStatus;
+ options.errorThrown = errorThrown;
+ if (error) error.apply(this, arguments);
+ };
+
+ // Make the request, allowing the user to override any Ajax options.
+ var xhr = options.xhr = BI.ajax(_.extend(params, options));
+ model.trigger('request', xhr, model, options);
+ return xhr;
+ };
+
+ // Map from CRUD to HTTP for our default `BI.sync` implementation.
+ var methodMap = {
+ 'create': 'POST',
+ 'update': 'PUT',
+ 'patch': 'PATCH',
+ 'delete': 'DELETE',
+ 'read': 'GET'
+ };
+
+ // Set the default implementation of `BI.ajax` to proxy through to `$`.
+ // Override this if you'd like to use a different library.
+ BI.ajax = $.ajax;
+
+ // BI.Router
+ // ---------------
+
+ // Routers map faux-URLs to actions, and fire events when routes are
+ // matched. Creating a new one sets its `routes` hash, if not set statically.
+ var Router = BI.Router = function (options) {
+ options || (options = {});
+ if (options.routes) this.routes = options.routes;
+ this._bindRoutes();
+ this._init.apply(this, arguments);
+ };
+
+ // Cached regular expressions for matching named param parts and splatted
+ // parts of route strings.
+ var optionalParam = /\((.*?)\)/g;
+ var namedParam = /(\(\?)?:\w+/g;
+ var splatParam = /\*\w+/g;
+ var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g;
+
+ // Set up all inheritable **BI.Router** properties and methods.
+ _.extend(Router.prototype, Events, {
+
+ // _init is an empty function by default. Override it with your own
+ // initialization logic.
+ _init: function () {
+ },
+
+ // Manually bind a single named route to a callback. For example:
+ //
+ // this.route('search/:query/p:num', 'search', function(query, num) {
+ // ...
+ // });
+ //
+ route: function (route, name, callback) {
+ if (!_.isRegExp(route)) route = this._routeToRegExp(route);
+ if (_.isFunction(name)) {
+ callback = name;
+ name = '';
+ }
+ if (!callback) callback = this[name];
+ var router = this;
+ BI.history.route(route, function (fragment) {
+ var args = router._extractParameters(route, fragment);
+ if (router.execute(callback, args, name) !== false) {
+ router.trigger.apply(router, ['route:' + name].concat(args));
+ router.trigger('route', name, args);
+ BI.history.trigger('route', router, name, args);
+ }
+ });
+ return this;
+ },
+
+ // Execute a route handler with the provided parameters. This is an
+ // excellent place to do pre-route setup or post-route cleanup.
+ execute: function (callback, args, name) {
+ if (callback) callback.apply(this, args);
+ },
+
+ // Simple proxy to `BI.history` to save a fragment into the history.
+ navigate: function (fragment, options) {
+ BI.history.navigate(fragment, options);
+ return this;
+ },
+
+ // Bind all defined routes to `BI.history`. We have to reverse the
+ // order of the routes here to support behavior where the most general
+ // routes can be defined at the bottom of the route map.
+ _bindRoutes: function () {
+ if (!this.routes) return;
+ this.routes = _.result(this, 'routes');
+ var route, routes = _.keys(this.routes);
+ while ((route = routes.pop()) != null) {
+ this.route(route, this.routes[route]);
+ }
+ },
+
+ // Convert a route string into a regular expression, suitable for matching
+ // against the current location hash.
+ _routeToRegExp: function (route) {
+ route = route.replace(escapeRegExp, '\\$&')
+ .replace(optionalParam, '(?:$1)?')
+ .replace(namedParam, function (match, optional) {
+ return optional ? match : '([^/?]+)';
+ })
+ .replace(splatParam, '([^?]*?)');
+ return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$');
+ },
+
+ // Given a route, and a URL fragment that it matches, return the array of
+ // extracted decoded parameters. Empty or unmatched parameters will be
+ // treated as `null` to normalize cross-browser behavior.
+ _extractParameters: function (route, fragment) {
+ var params = route.exec(fragment).slice(1);
+ return _.map(params, function (param, i) {
+ // Don't decode the search params.
+ if (i === params.length - 1) return param || null;
+ return param ? decodeURIComponent(param) : null;
+ });
+ }
+
+ });
+
+ // BI.History
+ // ----------------
+
+ // Handles cross-browser history management, based on either
+ // [pushState](http://diveintohtml5.info/history.html) and real URLs, or
+ // [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange)
+ // and URL fragments. If the browser supports neither (old IE, natch),
+ // falls back to polling.
+ var History = BI.History = function () {
+ this.handlers = [];
+ _.bindAll(this, 'checkUrl');
+
+ // Ensure that `History` can be used outside of the browser.
+ if (typeof window !== 'undefined') {
+ this.location = window.location;
+ this.history = window.history;
+ }
+ };
+
+ // Cached regex for stripping a leading hash/slash and trailing space.
+ var routeStripper = /^[#\/]|\s+$/g;
+
+ // Cached regex for stripping leading and trailing slashes.
+ var rootStripper = /^\/+|\/+$/g;
+
+ // Cached regex for stripping urls of hash.
+ var pathStripper = /#.*$/;
+
+ // Has the history handling already been started?
+ History.started = false;
+
+ // Set up all inheritable **BI.History** properties and methods.
+ _.extend(History.prototype, Events, {
+
+ // The default interval to poll for hash changes, if necessary, is
+ // twenty times a second.
+ interval: 50,
+
+ // Are we at the app root?
+ atRoot: function () {
+ var path = this.location.pathname.replace(/[^\/]$/, '$&/');
+ return path === this.root && !this.getSearch();
+ },
+
+ // In IE6, the hash fragment and search params are incorrect if the
+ // fragment contains `?`.
+ getSearch: function () {
+ var match = this.location.href.replace(/#.*/, '').match(/\?.+/);
+ return match ? match[0] : '';
+ },
+
+ // Gets the true hash value. Cannot use location.hash directly due to bug
+ // in Firefox where location.hash will always be decoded.
+ getHash: function (window) {
+ var match = (window || this).location.href.match(/#(.*)$/);
+ return match ? match[1] : '';
+ },
+
+ // Get the pathname and search params, without the root.
+ getPath: function () {
+ var path = decodeURI(this.location.pathname + this.getSearch());
+ var root = this.root.slice(0, -1);
+ if (!path.indexOf(root)) path = path.slice(root.length);
+ return path.charAt(0) === '/' ? path.slice(1) : path;
+ },
+
+ // Get the cross-browser normalized URL fragment from the path or hash.
+ getFragment: function (fragment) {
+ if (fragment == null) {
+ if (this._hasPushState || !this._wantsHashChange) {
+ fragment = this.getPath();
+ } else {
+ fragment = this.getHash();
+ }
+ }
+ return fragment.replace(routeStripper, '');
+ },
+
+ // Start the hash change handling, returning `true` if the current URL matches
+ // an existing route, and `false` otherwise.
+ start: function (options) {
+ if (History.started) throw new Error('BI.history has already been started');
+ History.started = true;
+
+ // Figure out the initial configuration. Do we need an iframe?
+ // Is pushState desired ... is it available?
+ this.options = _.extend({root: '/'}, this.options, options);
+ this.root = this.options.root;
+ this._wantsHashChange = this.options.hashChange !== false;
+ this._hasHashChange = 'onhashchange' in window;
+ this._wantsPushState = !!this.options.pushState;
+ this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState);
+ this.fragment = this.getFragment();
+
+ // Normalize root to always include a leading and trailing slash.
+ this.root = ('/' + this.root + '/').replace(rootStripper, '/');
+
+ // Transition from hashChange to pushState or vice versa if both are
+ // requested.
+ if (this._wantsHashChange && this._wantsPushState) {
+
+ // If we've started off with a route from a `pushState`-enabled
+ // browser, but we're currently in a browser that doesn't support it...
+ if (!this._hasPushState && !this.atRoot()) {
+ var root = this.root.slice(0, -1) || '/';
+ this.location.replace(root + '#' + this.getPath());
+ // Return immediately as browser will do redirect to new url
+ return true;
+
+ // Or if we've started out with a hash-based route, but we're currently
+ // in a browser where it could be `pushState`-based instead...
+ } else if (this._hasPushState && this.atRoot()) {
+ this.navigate(this.getHash(), {replace: true});
+ }
+
+ }
+
+ // Proxy an iframe to handle location events if the browser doesn't
+ // support the `hashchange` event, HTML5 history, or the user wants
+ // `hashChange` but not `pushState`.
+ if (!this._hasHashChange && this._wantsHashChange && (!this._wantsPushState || !this._hasPushState)) {
+ var iframe = document.createElement('iframe');
+ iframe.src = 'javascript:0';
+ iframe.style.display = 'none';
+ iframe.tabIndex = -1;
+ var body = document.body;
+ // Using `appendChild` will throw on IE < 9 if the document is not ready.
+ this.iframe = body.insertBefore(iframe, body.firstChild).contentWindow;
+ this.iframe.document.open().close();
+ this.iframe.location.hash = '#' + this.fragment;
+ }
+
+ // Add a cross-platform `addEventListener` shim for older browsers.
+ var addEventListener = window.addEventListener || function (eventName, listener) {
+ return attachEvent('on' + eventName, listener);
+ };
+
+ // Depending on whether we're using pushState or hashes, and whether
+ // 'onhashchange' is supported, determine how we check the URL state.
+ if (this._hasPushState) {
+ addEventListener('popstate', this.checkUrl, false);
+ } else if (this._wantsHashChange && this._hasHashChange && !this.iframe) {
+ addEventListener('hashchange', this.checkUrl, false);
+ } else if (this._wantsHashChange) {
+ this._checkUrlInterval = setInterval(this.checkUrl, this.interval);
+ }
+
+ if (!this.options.silent) return this.loadUrl();
+ },
+
+ // Disable BI.history, perhaps temporarily. Not useful in a real app,
+ // but possibly useful for unit testing Routers.
+ stop: function () {
+ // Add a cross-platform `removeEventListener` shim for older browsers.
+ var removeEventListener = window.removeEventListener || function (eventName, listener) {
+ return detachEvent('on' + eventName, listener);
+ };
+
+ // Remove window listeners.
+ if (this._hasPushState) {
+ removeEventListener('popstate', this.checkUrl, false);
+ } else if (this._wantsHashChange && this._hasHashChange && !this.iframe) {
+ removeEventListener('hashchange', this.checkUrl, false);
+ }
+
+ // Clean up the iframe if necessary.
+ if (this.iframe) {
+ document.body.removeChild(this.iframe.frameElement);
+ this.iframe = null;
+ }
+
+ // Some environments will throw when clearing an undefined interval.
+ if (this._checkUrlInterval) clearInterval(this._checkUrlInterval);
+ History.started = false;
+ },
+
+ // Add a route to be tested when the fragment changes. Routes added later
+ // may override previous routes.
+ route: function (route, callback) {
+ this.handlers.unshift({route: route, callback: callback});
+ },
+
+ // Checks the current URL to see if it has changed, and if it has,
+ // calls `loadUrl`, normalizing across the hidden iframe.
+ checkUrl: function (e) {
+ var current = this.getFragment();
+
+ // If the user pressed the back button, the iframe's hash will have
+ // changed and we should use that for comparison.
+ if (current === this.fragment && this.iframe) {
+ current = this.getHash(this.iframe);
+ }
+
+ if (current === this.fragment) return false;
+ if (this.iframe) this.navigate(current);
+ this.loadUrl();
+ },
+
+ // Attempt to load the current URL fragment. If a route succeeds with a
+ // match, returns `true`. If no defined routes matches the fragment,
+ // returns `false`.
+ loadUrl: function (fragment) {
+ fragment = this.fragment = this.getFragment(fragment);
+ return _.any(this.handlers, function (handler) {
+ if (handler.route.test(fragment)) {
+ handler.callback(fragment);
+ return true;
+ }
+ });
+ },
+
+ // Save a fragment into the hash history, or replace the URL state if the
+ // 'replace' option is passed. You are responsible for properly URL-encoding
+ // the fragment in advance.
+ //
+ // The options object can contain `trigger: true` if you wish to have the
+ // route callback be fired (not usually desirable), or `replace: true`, if
+ // you wish to modify the current URL without adding an entry to the history.
+ navigate: function (fragment, options) {
+ if (!History.started) return false;
+ if (!options || options === true) options = {trigger: !!options};
+
+ // Normalize the fragment.
+ fragment = this.getFragment(fragment || '');
+
+ // Don't include a trailing slash on the root.
+ var root = this.root;
+ if (fragment === '' || fragment.charAt(0) === '?') {
+ root = root.slice(0, -1) || '/';
+ }
+ var url = root + fragment;
+
+ // Strip the hash and decode for matching.
+ fragment = decodeURI(fragment.replace(pathStripper, ''));
+
+ if (this.fragment === fragment) return;
+ this.fragment = fragment;
+
+ // If pushState is available, we use it to set the fragment as a real URL.
+ if (this._hasPushState) {
+ this.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, url);
+
+ // If hash changes haven't been explicitly disabled, update the hash
+ // fragment to store history.
+ } else if (this._wantsHashChange) {
+ this._updateHash(this.location, fragment, options.replace);
+ if (this.iframe && (fragment !== this.getHash(this.iframe))) {
+ // Opening and closing the iframe tricks IE7 and earlier to push a
+ // history entry on hash-tag change. When replace is true, we don't
+ // want this.
+ if (!options.replace) this.iframe.document.open().close();
+ this._updateHash(this.iframe.location, fragment, options.replace);
+ }
+
+ // If you've told us that you explicitly don't want fallback hashchange-
+ // based history, then `navigate` becomes a page refresh.
+ } else {
+ return this.location.assign(url);
+ }
+ if (options.trigger) return this.loadUrl(fragment);
+ },
+
+ // Update the hash location, either replacing the current entry, or adding
+ // a new one to the browser history.
+ _updateHash: function (location, fragment, replace) {
+ if (replace) {
+ var href = location.href.replace(/(javascript:|#).*$/, '');
+ location.replace(href + '#' + fragment);
+ } else {
+ // Some browsers require that `hash` contains a leading #.
+ location.hash = '#' + fragment;
+ }
+ }
+
+ });
+
+ // Create the default BI.history.
+ BI.history = new History;
+
+ // Helpers
+ // -------
+
+ // Helper function to correctly set up the prototype chain, for subclasses.
+ // Similar to `goog.inherits`, but uses a hash of prototype properties and
+ // class properties to be extended.
+ var extend = function (protoProps, staticProps) {
+ var parent = this;
+ var child;
+
+ // The constructor function for the new subclass is either defined by you
+ // (the "constructor" property in your `extend` definition), or defaulted
+ // by us to simply call the parent's constructor.
+ if (protoProps && _.has(protoProps, 'constructor')) {
+ child = protoProps.constructor;
+ } else {
+ child = function () {
+ return parent.apply(this, arguments);
+ };
+ }
+
+ // Add static properties to the constructor function, if supplied.
+ _.extend(child, parent, staticProps);
+
+ // Set the prototype chain to inherit from `parent`, without calling
+ // `parent`'s constructor function.
+ var Surrogate = function () {
+ this.constructor = child;
+ };
+ Surrogate.prototype = parent.prototype;
+ child.prototype = new Surrogate;
+
+ // Add prototype properties (instance properties) to the subclass,
+ // if supplied.
+ if (protoProps) _.extend(child.prototype, protoProps);
+
+ // Set a convenience property in case the parent's prototype is needed
+ // later.
+ child.__super__ = parent.prototype;
+
+ return child;
+ };
+
+ // Set up inheritance for the model, collection, router, view and history.
+ M.extend = Collection.extend = Router.extend = V.extend = History.extend = extend;
+
+ // Throw an error when a URL is needed, and none is supplied.
+ var urlError = function () {
+ throw new Error('A "url" property or function must be specified');
+ };
+
+ // Wrap an optional error callback with a fallback error event.
+ var wrapError = function (model, options) {
+ var error = options.error;
+ options.error = function (resp) {
+ if (error) error(model, resp, options);
+ model.trigger('error', model, resp, options);
+ };
+ };
+
+ return BI;
+
+}));/**
+ * MVC路由
+ * @class BI.WRouter
+ * @extends BI.Router
+ * @type {*|void|Object}
+ */
+BI.WRouter = BI.Router.extend({
+ add: function(route, callback){
+ this.handlers || (this.handlers=[]);
+ this.handlers.unshift({route: route, callback: callback})
+ },
+
+ route: function(route, name, callback) {
+ if (!_.isRegExp(route)) route = this._routeToRegExp(route);
+ if (_.isFunction(name)) {
+ callback = name;
+ name = '';
+ }
+ if (!callback) callback = this[name];
+ var self = this;
+ this.add(route, function(fragment) {
+ var args = self._extractParameters(route, fragment);
+ var result = self.execute(callback, args, name)
+ if (result !== false) {
+ self.trigger.apply(self, ['route:' + name].concat(args));
+ self.trigger('route', name, args);
+ }
+ return result;
+ });
+ return this;
+ },
+
+ execute: function(callback, args, name) {
+ if (callback) return callback.apply(this, args);
+ return name;
+ },
+
+ get: function(fragment){
+ var result = null;
+ _.any(this.handlers, function(handler) {
+ if (handler.route.test(fragment)) {
+ result = handler.callback(fragment);
+ return true;
+ }
+ });
+ return result;
+ }
+});/**
+ * 基本函数
+ * Create By GUY 2014\11\17
+ *
+ */
+
+if (!window.BI) {
+ window.BI = {};
+}
+;
+!(function ($, undefined) {
+ var traverse = function (func, context) {
+ return function (value, key, obj) {
+ return func.call(context, key, value, obj);
+ }
+ };
+ var _apply = function (name) {
+ return function () {
+ return _[name].apply(_, arguments);
+ }
+ };
+ var _applyFunc = function (name) {
+ return function () {
+ var args = Array.prototype.slice.call(arguments, 0);
+ args[1] = _.isFunction(args[1]) ? traverse(args[1], args[2]) : args[1];
+ return _[name].apply(_, args);
+ }
+ };
+
+ //Utility
+ _.extend(BI, {
+ i18nText: function (key) {
+ var localeText = (BI.i18n && BI.i18n[key]) || "";
+ if (!localeText) {
+ localeText = key;
+ }
+ var len = arguments.length;
+ if (len > 1) {
+ for (var i = 1; i < len; i++) {
+ var key = "{R" + i + "}";
+ localeText = localeText.replaceAll(key, arguments[i] + "");
+ }
+ }
+ return localeText;
+ },
+
+ assert: function (v, is) {
+ if (this.isFunction(is)) {
+ if (!is(v)) {
+ throw new Error(v + " error");
+ } else {
+ return true;
+ }
+ }
+ if (!this.isArray(is)) {
+ is = [is];
+ }
+ if (!this.deepContains(is, v)) {
+ throw new Error(v + " error");
+ }
+ },
+
+ warn: function (message) {
+ console.warn(message)
+ },
+
+ UUID: function () {
+ var f = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
+ var str = "";
+ for (var i = 0; i < 16; i++) {
+ var r = parseInt(f.length * Math.random(), 10);
+ str += f[r];
+ }
+ return str;
+ },
+
+ isWidget: function (widget) {
+ return widget instanceof BI.Widget || (BI.View && widget instanceof BI.View);
+ },
+
+ createWidgets: function (items, options) {
+ if (!BI.isArray(items)) {
+ throw new Error("cannot create Widgets")
+ }
+ return BI.map(BI.flatten(items), function (i, item) {
+ return BI.createWidget(item, BI.deepClone(options));
+ });
+ },
+
+ createItems: function (data, innerAttr, outerAttr) {
+ innerAttr = BI.isArray(innerAttr) ? innerAttr : BI.makeArray(BI.flatten(data).length, innerAttr);
+ outerAttr = BI.isArray(outerAttr) ? outerAttr : BI.makeArray(BI.flatten(data).length, outerAttr);
+ return BI.map(data, function (i, item) {
+ if (BI.isArray(item)) {
+ return BI.createItems(item, innerAttr, outerAttr);
+ }
+ if (item instanceof BI.Widget) {
+ return BI.extend({}, innerAttr.shift(), outerAttr.shift(), {
+ type: null,
+ el: item
+ });
+ }
+ if (innerAttr[0] instanceof BI.Widget) {
+ outerAttr.shift();
+ return BI.extend({}, item, {
+ el: innerAttr.shift()
+ })
+ }
+ if (item.el instanceof BI.Widget || (BI.View && item.el instanceof BI.View)) {
+ innerAttr.shift();
+ return BI.extend({}, outerAttr.shift(), {type: null}, item);
+ }
+ if (item.el) {
+ return BI.extend({}, outerAttr.shift(), item, {
+ el: BI.extend({}, innerAttr.shift(), item.el)
+ })
+ }
+ return BI.extend({}, outerAttr.shift(), {
+ el: BI.extend({}, innerAttr.shift(), item)
+ })
+ })
+ },
+
+ //用容器包装items
+ packageItems: function (items, layouts) {
+ for (var i = layouts.length - 1; i >= 0; i--) {
+ items = BI.map(items, function (k, it) {
+ return BI.extend({}, layouts[i], {
+ items: [
+ BI.extend({}, layouts[i].el, {
+ el: it
+ })
+ ]
+ })
+ })
+ }
+ return items;
+ },
+
+ formatEL: function (obj) {
+ if (obj && !obj.type && obj.el) {
+ return obj;
+ }
+ return {
+ el: obj
+ };
+ },
+
+ //剥开EL
+ stripEL: function (obj) {
+ return obj.type && obj || obj.el || obj;
+ },
+
+ trans2Element: function (widgets) {
+ return BI.map(widgets, function (i, wi) {
+ return wi.element;
+ });
+ }
+ });
+
+ //集合相关方法
+ _.each(["where", "findWhere", "contains", "invoke", "pluck", "shuffle", "sample", "toArray", "size"], function (name) {
+ BI[name] = _apply(name)
+ });
+ _.each(["each", "map", "reduce", "reduceRight", "find", "filter", "reject", "every", "all", "some", "any", "max", "min",
+ "sortBy", "groupBy", "indexBy", "countBy", "partition"], function (name) {
+ BI[name] = _applyFunc(name)
+ });
+ _.extend(BI, {
+ clamp: function (value, minValue, maxValue) {
+ if (value < minValue) {
+ value = minValue;
+ }
+ if (value > maxValue) {
+ value = maxValue;
+ }
+ return value;
+ },
+ //数数
+ count: function (from, to, predicate) {
+ var t;
+ if (predicate) {
+ for (t = from; t < to; t++) {
+ predicate(t);
+ }
+ }
+ return to - from;
+ },
+
+ //倒数
+ inverse: function (from, to, predicate) {
+ return BI.count(to, from, predicate);
+ },
+
+ firstKey: function (obj) {
+ var res = undefined;
+ BI.any(obj, function (key, value) {
+ res = key;
+ return true;
+ });
+ return res;
+ },
+
+ lastKey: function (obj) {
+ var res = undefined;
+ BI.each(obj, function (key, value) {
+ res = key;
+ return true;
+ });
+ return res;
+ },
+
+ firstObject: function (obj) {
+ var res = undefined;
+ BI.any(obj, function (key, value) {
+ res = value;
+ return true;
+ });
+ return res;
+ },
+
+ lastObject: function (obj) {
+ var res = undefined;
+ BI.each(obj, function (key, value) {
+ res = value;
+ return true;
+ });
+ return res;
+ },
+
+ concat: function (obj1, obj2) {
+ if (BI.isKey(obj1)) {
+ return obj1 + "" + obj2;
+ }
+ if (BI.isArray(obj1)) {
+ return obj1.concat(obj2);
+ }
+ if (BI.isObject(obj1)) {
+ return _.extend({}, obj1, obj2);
+ }
+ },
+
+ backEach: function (obj, predicate, context) {
+ predicate = BI.iteratee(predicate, context);
+ for (var index = obj.length - 1; index >= 0; index--) {
+ predicate(index, obj[index], obj);
+ }
+ return false;
+ },
+
+ backAny: function (obj, predicate, context) {
+ predicate = BI.iteratee(predicate, context);
+ for (var index = obj.length - 1; index >= 0; index--) {
+ if (predicate(index, obj[index], obj)) {
+ return true;
+ }
+ }
+ return false;
+ },
+
+ backEvery: function (obj, predicate, context) {
+ predicate = BI.iteratee(predicate, context);
+ for (var index = obj.length - 1; index >= 0; index--) {
+ if (!predicate(index, obj[index], obj)) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ backFindKey: function (obj, predicate, context) {
+ predicate = BI.iteratee(predicate, context);
+ var keys = _.keys(obj), key;
+ for (var i = keys.length - 1; i >= 0; i--) {
+ key = keys[i];
+ if (predicate(obj[key], key, obj)) {
+ return key;
+ }
+ }
+ },
+
+ backFind: function (obj, predicate, context) {
+ var key;
+ if (BI.isArray(obj)) {
+ key = BI.findLastIndex(obj, predicate, context);
+ } else {
+ key = BI.backFindKey(obj, predicate, context);
+ }
+ if (key !== void 0 && key !== -1) {
+ return obj[key];
+ }
+ },
+
+ remove: function (obj, target, context) {
+ var isFunction = BI.isFunction(target);
+ target = isFunction || BI.isArray(target) ? target : [target];
+ var i;
+ if (BI.isArray(obj)) {
+ for (i = 0; i < obj.length; i++) {
+ if ((isFunction && target.apply(context, [i, obj[i]]) === true) || (!isFunction && target.contains(obj[i]))) {
+ obj.splice(i--, 1);
+ }
+ }
+ } else {
+ BI.each(obj, function (i, v) {
+ if ((isFunction && target.apply(context, [i, obj[i]]) === true) || (!isFunction && target.contains(obj[i]))) {
+ delete obj[i];
+ }
+ });
+ }
+ },
+
+ removeAt: function (obj, index) {
+ index = BI.isArray(index) ? index : [index];
+ var isArray = BI.isArray(obj), i;
+ for (i = 0; i < index.length; i++) {
+ if (isArray) {
+ obj[index[i]] = "$deleteIndex";
+ } else {
+ delete obj[index[i]];
+ }
+ }
+ if (isArray) {
+ BI.remove(obj, "$deleteIndex");
+ }
+ },
+
+ string2Array: function (str) {
+ return str.split('&-&');
+ },
+
+ array2String: function (array) {
+ return array.join("&-&");
+ },
+
+ abc2Int: function (str) {
+ var idx = 0, start = 'A', str = str.toUpperCase();
+ for (var i = 0, len = str.length; i < len; ++i) {
+ idx = str.charAt(i).charCodeAt(0) - start.charCodeAt(0) + 26 * idx + 1;
+ if (idx > (2147483646 - str.charAt(i).charCodeAt(0) + start.charCodeAt(0)) / 26) {
+ return 0;
+ }
+ }
+ return idx;
+ },
+
+ int2Abc: function (num) {
+ var DIGITS = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
+ var idx = num, str = "";
+ if (num === 0) {
+ return "";
+ }
+ while (idx !== 0) {
+ var t = idx % 26;
+ if (t === 0) {
+ t = 26;
+ }
+ str = DIGITS[t - 1] + str;
+ idx = (idx - t) / 26;
+ }
+ return str;
+ }
+ });
+
+ //数组相关的方法
+ _.each(["first", "initial", "last", "rest", "compact", "flatten", "without", "union", "intersection",
+ "difference", "zip", "unzip", "object", "indexOf", "lastIndexOf", "sortedIndex", "range"], function (name) {
+ BI[name] = _apply(name)
+ });
+ _.each(["findIndex", "findLastIndex"], function (name) {
+ BI[name] = _applyFunc(name)
+ });
+ _.extend(BI, {
+ //构建一个长度为length的数组
+ makeArray: function (length, value) {
+ var res = [];
+ for (var i = 0; i < length; i++) {
+ if (BI.isNull(value)) {
+ res.push(i);
+ } else {
+ res.push(BI.deepClone(value));
+ }
+ }
+ return res;
+ },
+
+ makeObject: function (array, value) {
+ var map = {};
+ for (var i = 0; i < array.length; i++) {
+ if (BI.isNull(value)) {
+ map[array[i]] = array[i];
+ } else {
+ map[array[i]] = BI.deepClone(value);
+ }
+ }
+ return map;
+ },
+
+ makeArrayByArray: function (array, value) {
+ var res = [];
+ if (!array) {
+ return res;
+ }
+ for (var i = 0, len = array.length; i < len; i++) {
+ if (BI.isArray(array[i])) {
+ res.push(arguments.callee(array[i], value));
+ } else {
+ res.push(BI.deepClone(value));
+ }
+ }
+ return res;
+ },
+
+ uniq: function (array, isSorted, iteratee, context) {
+ if (array == null) {
+ return [];
+ }
+ if (!_.isBoolean(isSorted)) {
+ context = iteratee;
+ iteratee = isSorted;
+ isSorted = false;
+ }
+ iteratee && (iteratee = traverse(iteratee, context));
+ return _.uniq.call(_, array, isSorted, iteratee, context);
+ }
+ });
+
+ //对象相关方法
+ _.each(["keys", "allKeys", "values", "pairs", "invert", "create", "functions", "extend", "extendOwn",
+ "defaults", "clone", "property", "propertyOf", "matcher", "isEqual", "isMatch", "isEmpty",
+ "isElement", "isNumber", "isString", "isArray", "isObject", "isArguments", "isFunction", "isFinite",
+ "isBoolean", "isDate", "isRegExp", "isError", "isNaN", "isUndefined"], function (name) {
+ BI[name] = _apply(name)
+ });
+ _.each(["mapObject", "findKey", "pick", "omit", "tap"], function (name) {
+ BI[name] = _applyFunc(name)
+ });
+ _.extend(BI, {
+
+ inherit: function (sb, sp, overrides) {
+ if (typeof sp == 'object') {
+ overrides = sp;
+ sp = sb;
+ sb = function () {
+ sp.apply(this, arguments);
+ };
+ }
+ var F = function () {
+ }, spp = sp.prototype;
+ F.prototype = spp;
+ sb.prototype = new F();
+ sb.superclass = spp;
+ _.extend(sb.prototype, overrides, {
+ superclass: sp
+ });
+ return sb;
+ },
+
+ has: function (obj, keys) {
+ if (BI.isArray(keys)) {
+ if (keys.length === 0) {
+ return false;
+ }
+ return BI.every(keys, function (i, key) {
+ return _.has(obj, key);
+ });
+ }
+ return _.has.apply(_, arguments);
+ },
+
+ //数字和字符串可以作为key
+ isKey: function (key) {
+ return BI.isNumber(key) || (BI.isString(key) && key.length > 0);
+ },
+
+ //忽略大小写的等于
+ isCapitalEqual: function (a, b) {
+ a = BI.isNull(a) ? a : ("" + a).toLowerCase();
+ b = BI.isNull(b) ? b : ("" + b).toLowerCase();
+ return BI.isEqual(a, b);
+ },
+
+ isWidthOrHeight: function (w) {
+ if (typeof w == 'number') {
+ return w >= 0;
+ } else if (typeof w == 'string') {
+ return /^\d{1,3}%$/.exec(w) || w == 'auto' || /^\d+px$/.exec(w);
+ }
+ },
+
+ isNotNull: function (obj) {
+ return !BI.isNull(obj);
+ },
+
+ isNull: function (obj) {
+ return typeof obj === "undefined" || obj === null;
+ },
+
+ isPlainObject: function () {
+ return $.isPlainObject.apply($, arguments);
+ },
+
+ isEmptyArray: function (arr) {
+ return BI.isArray(arr) && BI.isEmpty(arr);
+ },
+
+ isNotEmptyArray: function (arr) {
+ return BI.isArray(arr) && !BI.isEmpty(arr);
+ },
+
+ isEmptyObject: function (obj) {
+ return BI.isEqual(obj, {});
+ },
+
+ isNotEmptyObject: function (obj) {
+ return BI.isPlainObject(obj) && !BI.isEmptyObject(obj);
+ },
+
+ isEmptyString: function (obj) {
+ return BI.isString(obj) && obj.length === 0;
+ },
+
+ isNotEmptyString: function (obj) {
+ return BI.isString(obj) && !BI.isEmptyString(obj);
+ },
+
+ isWindow: function () {
+ return $.isWindow.apply($, arguments);
+ }
+ });
+
+ //deep方法
+ _.extend(BI, {
+ /**
+ *完全克隆�?个js对象
+ * @param obj
+ * @returns {*}
+ */
+ deepClone: function (obj) {
+ if (obj === null || obj === undefined) {
+ return obj;
+ }
+
+ var type = Object.prototype.toString.call(obj);
+
+ // Date
+ if (type === '[object Date]') {
+ return new Date(obj.getTime());
+ }
+
+ var i, clone, key;
+
+ // Array
+ if (type === '[object Array]') {
+ i = obj.length;
+
+ clone = [];
+
+ while (i--) {
+ clone[i] = BI.deepClone(obj[i]);
+ }
+ }
+ // Object
+ else if (type === '[object Object]' && obj.constructor === Object) {
+ clone = {};
+
+ for (var i in obj) {
+ if (_.has(obj, i)) {
+ clone[i] = BI.deepClone(obj[i]);
+ }
+ }
+ }
+
+ return clone || obj;
+ },
+
+ isDeepMatch: function (object, attrs) {
+ var keys = BI.keys(attrs), length = keys.length;
+ if (object == null) {
+ return !length;
+ }
+ var obj = Object(object);
+ for (var i = 0; i < length; i++) {
+ var key = keys[i];
+ if (!BI.isEqual(attrs[key], obj[key]) || !(key in obj)) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ deepContains: function (obj, copy) {
+ if (BI.isObject(copy)) {
+ return BI.any(obj, function (i, v) {
+ if (BI.isEqual(v, copy)) {
+ return true;
+ }
+ })
+ }
+ return BI.contains(obj, copy);
+ },
+
+ deepIndexOf: function (obj, target) {
+ for (var i = 0; i < obj.length; i++) {
+ if (BI.isEqual(target, obj[i])) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ deepRemove: function (obj, target) {
+ var done = false;
+ var i;
+ if (BI.isArray(obj)) {
+ for (i = 0; i < obj.length; i++) {
+ if (BI.isEqual(target, obj[i])) {
+ obj.splice(i--, 1);
+ done = true;
+ }
+ }
+ } else {
+ BI.each(obj, function (i, v) {
+ if (BI.isEqual(target, obj[i])) {
+ delete obj[i];
+ done = true;
+ }
+ });
+ }
+ return done;
+ },
+
+ deepWithout: function (obj, target) {
+ if (BI.isArray(obj)) {
+ var result = [];
+ for (var i = 0; i < obj.length; i++) {
+ if (!BI.isEqual(target, obj[i])) {
+ result.push(obj[i]);
+ }
+ }
+ return result;
+ } else {
+ var result = {};
+ BI.each(obj, function (i, v) {
+ if (!BI.isEqual(target, obj[i])) {
+ result[i] = v;
+ }
+ });
+ return result;
+ }
+ },
+
+ deepUnique: function (array) {
+ var result = [];
+ BI.each(array, function (i, item) {
+ if (!BI.deepContains(result, item)) {
+ result.push(item);
+ }
+ });
+ return result;
+ },
+
+ //比较两个对象得出不一样的key值
+ deepDiff: function (object, other) {
+ object || (object = {});
+ other || (other = {});
+ var result = [];
+ var used = [];
+ for (var b in object) {
+ if (this.has(object, b)) {
+ if (!this.isEqual(object[b], other[b])) {
+ result.push(b);
+ }
+ used.push(b);
+ }
+ }
+ for (var b in other) {
+ if (this.has(other, b) && !used.contains(b)) {
+ result.push(b);
+ }
+ }
+ return result;
+ }
+ });
+
+ //通用方法
+ _.each(["uniqueId", "result", "chain", "iteratee", "escape", "unescape"], function (name) {
+ BI[name] = function () {
+ return _[name].apply(_, arguments);
+ }
+ });
+
+ //事件相关方法
+ _.each(["bind", "once", "partial", "debounce", "throttle", "delay", "defer", "wrap"], function (name) {
+ BI[name] = function () {
+ return _[name].apply(_, arguments);
+ }
+ });
+
+ _.extend(BI, {
+ nextTick: (function () {
+ var callbacks = [];
+ var pending = false;
+ var timerFunc;
+
+ function nextTickHandler() {
+ pending = false;
+ var copies = callbacks.slice(0);
+ callbacks = [];
+ for (var i = 0; i < copies.length; i++) {
+ copies[i]();
+ }
+ }
+
+ if (typeof Promise !== 'undefined') {
+ var p = Promise.resolve();
+ timerFunc = function () {
+ p.then(nextTickHandler);
+ }
+ } else
+
+ /* istanbul ignore if */
+ if (typeof MutationObserver !== 'undefined') {
+ var counter = 1;
+ var observer = new MutationObserver(nextTickHandler);
+ var textNode = document.createTextNode(counter + "");
+ observer.observe(textNode, {
+ characterData: true
+ });
+ timerFunc = function () {
+ counter = (counter + 1) % 2;
+ textNode.data = counter + "";
+ }
+ } else {
+ timerFunc = function () {
+ setTimeout(nextTickHandler, 0)
+ }
+ }
+ return function queueNextTick(cb) {
+ var _resolve;
+ var args = [].slice.call(arguments, 1);
+ callbacks.push(function () {
+ if (cb) {
+ cb.apply(null, args);
+ }
+ if (_resolve) {
+ _resolve.apply(null, args);
+ }
+ });
+ if (!pending) {
+ pending = true;
+ timerFunc();
+ }
+ if (!cb && typeof Promise !== 'undefined') {
+ return new Promise(function (resolve) {
+ _resolve = resolve
+ })
+ }
+ }
+ })()
+ });
+
+ //数字相关方法
+ _.each(["random"], function (name) {
+ BI[name] = _apply(name)
+ });
+ _.extend(BI, {
+ getTime: function () {
+ if (window.performance && window.performance.now) {
+ return window.performance.now();
+ } else {
+ if (window.performance && window.performance.webkitNow) {
+ return window.performance.webkitNow();
+ } else {
+ if (Date.now) {
+ return Date.now();
+ } else {
+ return new Date().getTime();
+ }
+ }
+ }
+ },
+
+ parseInt: function (number) {
+ var radix = 10;
+ if (/^0x/g.test(number)) {
+ radix = 16;
+ }
+ try {
+ return parseInt(number, radix);
+ } catch (e) {
+ throw new Error(number + "parse int error");
+ return NaN;
+ }
+ },
+
+ parseSafeInt: function (value) {
+ var MAX_SAFE_INTEGER = 9007199254740991;
+ return value
+ ? this.clamp(this.parseInt(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER)
+ : (value === 0 ? value : 0);
+ },
+
+ parseFloat: function (number) {
+ try {
+ return parseFloat(number);
+ } catch (e) {
+ throw new Error(number + "parse float error");
+ return NaN;
+ }
+ },
+
+ isNaturalNumber: function (number) {
+ if (/^\d+$/.test(number)) {
+ return true;
+ }
+ return false;
+ },
+
+ isPositiveInteger: function (number) {
+ if (/^\+?[1-9][0-9]*$/.test(number)) {
+ return true;
+ }
+ return false;
+ },
+
+ isNegativeInteger: function (number) {
+ if (/^\-[1-9][0-9]*$/.test(number)) {
+ return true;
+ }
+ return false;
+ },
+
+ isInteger: function (number) {
+ if (/^\-?\d+$/.test(number)) {
+ return true;
+ }
+ return false;
+ },
+
+ isNumeric: function (number) {
+ return $.isNumeric(number);
+ },
+
+ isFloat: function (number) {
+ if (/^([+-]?)\\d*\\.\\d+$/.test(number)) {
+ return true;
+ }
+ return false;
+ },
+
+ isOdd: function (number) {
+ if (!BI.isInteger(number)) {
+ return false;
+ }
+ return number & 1 === 1;
+ },
+
+ isEven: function (number) {
+ if (!BI.isInteger(number)) {
+ return false;
+ }
+ return number & 1 === 0;
+ },
+
+ sum: function (array, iteratee, context) {
+ var sum = 0;
+ BI.each(array, function (i, item) {
+ if (iteratee) {
+ sum += Number(iteratee.apply(context, [i, item]));
+ } else {
+ sum += Number(item);
+ }
+ });
+ return sum;
+ },
+
+ average: function (array, iteratee, context) {
+ var sum = BI.sum(array, iteratee, context);
+ return sum / array.length;
+ }
+ });
+
+ //字符串相关方法
+ _.extend(BI, {
+ trim: function () {
+ return $.trim.apply($, arguments);
+ },
+
+ toUpperCase: function (string) {
+ return (string + "").toLocaleUpperCase();
+ },
+
+ toLowerCase: function (string) {
+ return (string + "").toLocaleLowerCase();
+ },
+
+ isEndWithBlank: function (string) {
+ return /(\s|\u00A0)$/.test(string);
+ },
+
+ isLiteral: function (exp) {
+ var literalValueRE = /^\s?(true|false|-?[\d\.]+|'[^']*'|"[^"]*")\s?$/
+ return literalValueRE.test(exp)
+ },
+
+ stripQuotes: function (str) {
+ var a = str.charCodeAt(0)
+ var b = str.charCodeAt(str.length - 1)
+ return a === b && (a === 0x22 || a === 0x27)
+ ? str.slice(1, -1)
+ : str
+ },
+
+ //background-color => backgroundColor
+ camelize: function (str) {
+ return str.replace(/-(.)/g, function (_, character) {
+ return character.toUpperCase();
+ });
+ },
+
+ //backgroundColor => background-color
+ hyphenate: function (str) {
+ return str.replace(/([A-Z])/g, '-$1').toLowerCase();
+ },
+
+ isNotEmptyString: function (str) {
+ return BI.isString(str) && !BI.isEmpty(str);
+ },
+
+ isEmptyString: function (str) {
+ return BI.isString(str) && BI.isEmpty(str);
+ },
+
+ /**
+ * 对字符串进行加密 {@link #decrypt}
+ * @static
+ * @param str 原始字符�?
+ * @param keyt 密钥
+ * @returns {String} 加密后的字符�?
+ */
+ encrypt: function (str, keyt) {
+ if (str == "") {
+ return "";
+ }
+ str = escape(str);
+ if (!keyt || keyt == "") {
+ keyt = "655";
+ }
+ keyt = escape(keyt);
+ if (keyt == null || keyt.length <= 0) {
+ alert("Please enter a password with which to encrypt the message.");
+ return null;
+ }
+ var prand = "";
+ for (var i = 0; i < keyt.length; i++) {
+ prand += keyt.charCodeAt(i).toString();
+ }
+ var sPos = Math.floor(prand.length / 5);
+ var mult = parseInt(prand.charAt(sPos) + prand.charAt(sPos * 2) + prand.charAt(sPos * 3) + prand.charAt(sPos * 4) + prand.charAt(sPos * 5));
+
+ var incr = Math.ceil(keyt.length / 2);
+ var modu = Math.pow(2, 31) - 1;
+ if (mult < 2) {
+ alert("Algorithm cannot find a suitable hash. Please choose a different password. \nPossible considerations are to choose a more complex or longer password.");
+ return null;
+ }
+// var salt = Math.round(Math.random() * 1000000000) % 100000000;
+ var salt = 101;
+ prand += salt;
+ while (prand.length > 10) {
+ prand = (parseInt(prand.substring(0, 10)) + parseInt(prand.substring(10, prand.length), 10)).toString();
+ }
+ prand = (mult * prand + incr) % modu;
+ var enc_chr = "";
+ var enc_str = "";
+ for (var i = 0; i < str.length; i++) {
+ enc_chr = parseInt(str.charCodeAt(i) ^ Math.floor((prand / modu) * 255));
+ if (enc_chr < 16) {
+ enc_str += "0" + enc_chr.toString(16);
+ } else {
+ enc_str += enc_chr.toString(16);
+ }
+ prand = (mult * prand + incr) % modu;
+ }
+ salt = salt.toString(16);
+ while (salt.length < 8) {
+ salt = "0" + salt;
+ }
+ enc_str += salt;
+ return enc_str;
+ },
+
+ /**
+ * 对加密后的字符串解密 {@link #encrypt}
+ * @static
+ * @param str 加密过的字符�?
+ * @param keyt 密钥
+ * @returns {String} 解密后的字符�?
+ */
+ decrypt: function (str, keyt) {
+ if (str == "") {
+ return "";
+ }
+ if (!keyt || keyt == "") {
+ keyt = "655";
+ }
+ keyt = escape(keyt);
+ if (str == null || str.length < 8) {
+ return;
+ }
+ if (keyt == null || keyt.length <= 0) {
+ return;
+ }
+ var prand = "";
+ for (var i = 0; i < keyt.length; i++) {
+ prand += keyt.charCodeAt(i).toString();
+ }
+ var sPos = Math.floor(prand.length / 5);
+ var tempmult = prand.charAt(sPos) + prand.charAt(sPos * 2) + prand.charAt(sPos * 3) + prand.charAt(sPos * 4);
+ if (sPos * 5 < prand.length) {
+ tempmult += prand.charAt(sPos * 5);
+ }
+ var mult = parseInt(tempmult);
+ var incr = Math.round(keyt.length / 2);
+ var modu = Math.pow(2, 31) - 1;
+ var salt = parseInt(str.substring(str.length - 8, str.length), 16);
+ str = str.substring(0, str.length - 8);
+ prand += salt;
+ while (prand.length > 10) {
+ prand = (parseInt(prand.substring(0, 10), 10) + parseInt(prand.substring(10, prand.length), 10)).toString();
+ }
+ prand = (mult * prand + incr) % modu;
+ var enc_chr = "";
+ var enc_str = "";
+ for (var i = 0; i < str.length; i += 2) {
+ enc_chr = parseInt(parseInt(str.substring(i, i + 2), 16) ^ Math.floor((prand / modu) * 255));
+ enc_str += String.fromCharCode(enc_chr);
+ prand = (mult * prand + incr) % modu;
+ }
+ return unescape(enc_str);
+ }
+ });
+
+ //浏览器相关方法
+ _.extend(BI, {
+ isIE: function () {
+ return /(msie|trident)/i.test(navigator.userAgent.toLowerCase());
+ },
+
+ isIE9Below: function () {
+ if (!BI.isIE()) {
+ return false;
+ }
+ var version = 0;
+ var agent = navigator.userAgent.toLowerCase();
+ var v1 = agent.match(/(?:msie\s([\w.]+))/);
+ var v2 = agent.match(/(?:trident.*rv:([\w.]+))/);
+ if (v1 && v2 && v1[1] && v2[1]) {
+ version = Math.max(v1[1] * 1, v2[1] * 1);
+ } else if (v1 && v1[1]) {
+ version = v1[1] * 1;
+ } else if (v2 && v2[1]) {
+ version = v2[1] * 1;
+ } else {
+ version = 0;
+ }
+ return version < 9;
+ },
+
+ isEdge: function () {
+ return /edge/i.test(navigator.userAgent.toLowerCase());
+ },
+
+ isChrome: function () {
+ return /chrome/i.test(navigator.userAgent.toLowerCase());
+ },
+
+ isFireFox: function () {
+ return /firefox/i.test(navigator.userAgent.toLowerCase());
+ },
+
+ isOpera: function () {
+ return /opera/i.test(navigator.userAgent.toLowerCase());
+ },
+
+ isSafari: function () {
+ return /safari/i.test(navigator.userAgent.toLowerCase());
+ },
+
+ isKhtml: function () {
+ return /Konqueror|Safari|KHTML/i.test(navigator.userAgent);
+ },
+
+ isMac: function () {
+ return /macintosh|mac os x/i.test(navigator.userAgent);
+ },
+
+ isWindows: function () {
+ return /windows|win32/i.test(navigator.userAgent);
+ },
+
+ isSupportCss3: function (style) {
+ var prefix = ['webkit', 'Moz', 'ms', 'o'],
+ i, len,
+ humpString = [],
+ htmlStyle = document.documentElement.style,
+ _toHumb = function (string) {
+ return string.replace(/-(\w)/g, function ($0, $1) {
+ return $1.toUpperCase();
+ });
+ };
+
+ for (i in prefix) {
+ humpString.push(_toHumb(prefix[i] + '-' + style));
+ }
+ humpString.push(_toHumb(style));
+
+ for (i = 0, len = humpString.length; i < len; i++) {
+ if (humpString[i] in htmlStyle) {
+ return true;
+ }
+ }
+ return false;
+ }
+ });
+ //BI请求
+ _.extend(BI, {
+
+ ajax: function (option) {
+ option || (option = {});
+ var async = option.async;
+ option.data = BI.cjkEncodeDO(option.data || {});
+
+ $.ajax({
+ url: option.url,
+ type: "POST",
+ data: option.data,
+ async: async,
+ error: option.error,
+ complete: function (res, status) {
+ if (BI.isFunction(option.complete)) {
+ option.complete(BI.jsonDecode(res.responseText), status);
+ }
+ }
+ });
+ }
+ });
+})(jQuery);/**
+ * 客户端观察者,主要处理事件的添加、删除、执行等
+ * @class BI.OB
+ * @abstract
+ */
+BI.OB = function (config) {
+ var props = this.props;
+ if (BI.isFunction(this.props)) {
+ props = this.props(config);
+ }
+ this.options = $.extend(this._defaultConfig(config), props, config);
+ this._init();
+ this._initRef();
+};
+$.extend(BI.OB.prototype, {
+ props: {},
+ init: null,
+ destroyed: null,
+
+ _defaultConfig: function (config) {
+ return {};
+ },
+
+ _init: function () {
+ this._initListeners();
+ this.init && this.init();
+ },
+
+ _initListeners: function () {
+ var self = this;
+ if (this.options.listeners != null) {
+ $.each(this.options.listeners, function (i, lis) {
+ (lis.target ? lis.target : self)[lis.once ? 'once' : 'on']
+ (lis.eventName, _.bind(lis.action, self))
+ });
+ delete this.options.listeners;
+ }
+ },
+
+ //获得一个当前对象的引用
+ _initRef: function () {
+ if (this.options.ref) {
+ this.options.ref.call(this, this);
+ }
+ },
+
+ _getEvents: function () {
+ if (!$.isArray(this.events)) {
+ this.events = []
+ }
+ return this.events;
+ },
+
+ /**
+ * 给观察者绑定一个事件
+ * @param {String} eventName 事件的名字
+ * @param {Function} fn 事件对应的执行函数
+ */
+ on: function (eventName, fn) {
+ eventName = eventName.toLowerCase();
+ var fns = this._getEvents()[eventName];
+ if (!$.isArray(fns)) {
+ fns = [];
+ this._getEvents()[eventName] = fns;
+ }
+ fns.push(fn);
+ },
+
+ /**
+ * 给观察者绑定一个只执行一次的事件
+ * @param {String} eventName 事件的名字
+ * @param {Function} fn 事件对应的执行函数
+ */
+ once: function (eventName, fn) {
+ var proxy = function () {
+ fn.apply(this, arguments);
+ this.un(eventName, proxy);
+ };
+ this.on(eventName, proxy);
+ },
+ /**
+ * 解除观察者绑定的指定事件
+ * @param {String} eventName 要解除绑定事件的名字
+ * @param {Function} fn 事件对应的执行函数,该参数是可选的,没有该参数时,将解除绑定所有同名字的事件
+ */
+ un: function (eventName, fn) {
+ eventName = eventName.toLowerCase();
+
+ /*alex:如果fn是null,就是把eventName上面所有方法都un掉*/
+ if (fn == null) {
+ delete this._getEvents()[eventName];
+ } else {
+ var fns = this._getEvents()[eventName];
+ if ($.isArray(fns)) {
+ var newFns = [];
+ $.each(fns, function (idx, ifn) {
+ if (ifn != fn) {
+ newFns.push(ifn);
+ }
+ })
+ this._getEvents()[eventName] = newFns;
+ }
+ }
+ },
+ /**
+ * 清除观察者的所有事件绑定
+ */
+ purgeListeners: function () {
+ /*alex:清空events*/
+ this.events = [];
+ },
+ /**
+ * 触发绑定过的事件
+ *
+ * @param {String} eventName 要触发的事件的名字
+ * @returns {Boolean} 如果事件函数返回false,则返回false并中断其他同名事件的执行,否则执行所有的同名事件并返回true
+ */
+ fireEvent: function () {
+ var eventName = arguments[0].toLowerCase();
+ var fns = this._getEvents()[eventName];
+ if (BI.isArray(fns)) {
+ if (BI.isArguments(arguments[1])) {
+ for (var i = 0; i < fns.length; i++) {
+ if (fns[i].apply(this, arguments[1]) === false) {
+ return false;
+ }
+ }
+ } else {
+ var args = Array.prototype.slice.call(arguments, 1);
+ for (var i = 0; i < fns.length; i++) {
+ if (fns[i].apply(this, args) === false) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ },
+
+ destroy: function () {
+ this.destroyed && this.destroyed();
+ this.purgeListeners();
+ }
+});/**
+ * Widget超类
+ * @class BI.Widget
+ * @extends BI.OB
+ *
+ * @cfg {JSON} options 配置属性
+ */
+BI.Widget = BI.inherit(BI.OB, {
+ _defaultConfig: function () {
+ return BI.extend(BI.Widget.superclass._defaultConfig.apply(this), {
+ root: false,
+ tagName: "div",
+ attributes: null,
+ data: null,
+
+ tag: null,
+ disabled: false,
+ invisible: false,
+ invalid: false,
+ baseCls: "",
+ extraCls: "",
+ cls: ""
+ })
+ },
+
+ //生命周期函数
+ beforeCreate: null,
+
+ created: null,
+
+ render: null,
+
+ beforeMounted: null,
+
+ mounted: null,
+
+ update: function () {
+ },
+
+ beforeDestroyed: null,
+
+ destroyed: null,
+
+ _init: function () {
+ BI.Widget.superclass._init.apply(this, arguments);
+ this.beforeCreate && this.beforeCreate();
+ this._initRoot();
+ this._initElementWidth();
+ this._initElementHeight();
+ this._initVisual();
+ this._initState();
+ this._initElement();
+ this._initEffects();
+ this.created && this.created();
+ },
+
+ /**
+ * 初始化根节点
+ * @private
+ */
+ _initRoot: function () {
+ var o = this.options;
+ this.widgetName = o.widgetName || BI.uniqueId("widget");
+ this._isRoot = o.root;
+ if (BI.isWidget(o.element)) {
+ if (o.element instanceof BI.Widget) {
+ this._parent = o.element;
+ this._parent.addWidget(this.widgetName, this);
+ } else {
+ this._isRoot = true;
+ }
+ this.element = this.options.element.element;
+ } else if (o.element) {
+ // if (o.root !== true) {
+ // throw new Error("root is a required property");
+ // }
+ this.element = $(o.element);
+ this._isRoot = true;
+ } else {
+ this.element = $(document.createElement(o.tagName));
+ }
+ if (o.baseCls || o.extraCls || o.cls) {
+ this.element.addClass((o.baseCls || "") + " " + (o.extraCls || "") + " " + (o.cls || ""));
+ }
+ if (o.attributes) {
+ this.element.attr(o.attributes);
+ }
+ if (o.data) {
+ this.element.data(o.data);
+ }
+ this._children = {};
+ },
+
+ _initElementWidth: function () {
+ var o = this.options;
+ if (BI.isWidthOrHeight(o.width)) {
+ this.element.css("width", o.width);
+ }
+ },
+
+ _initElementHeight: function () {
+ var o = this.options;
+ if (BI.isWidthOrHeight(o.height)) {
+ this.element.css("height", o.height);
+ }
+ },
+
+ _initVisual: function () {
+ var o = this.options;
+ if (o.invisible) {
+ //用display属性做显示和隐藏,否则jquery会在显示时将display设为block会覆盖掉display:flex属性
+ this.element.css("display", "none");
+ }
+ },
+
+ _initEffects: function () {
+ var o = this.options;
+ if (o.disabled || o.invalid) {
+ if (this.options.disabled) {
+ this.setEnable(false);
+ }
+ if (this.options.invalid) {
+ this.setValid(false);
+ }
+ }
+ },
+
+ _initState: function () {
+ this._isMounted = false;
+ },
+
+ _initElement: function () {
+ var self = this;
+ var els = this.render && this.render();
+ if (BI.isPlainObject(els)) {
+ els = [els];
+ }
+ if (BI.isArray(els)) {
+ BI.each(els, function (i, el) {
+ BI.createWidget(el, {
+ element: self
+ })
+ })
+ }
+ // if (this._isRoot === true || !(this instanceof BI.Layout)) {
+ this._mount();
+ // }
+ },
+
+ _setParent: function (parent) {
+ this._parent = parent;
+ },
+
+ _mount: function () {
+ var self = this;
+ var isMounted = this._isMounted;
+ if (isMounted || !this.isVisible()) {
+ return;
+ }
+ if (this._isRoot === true) {
+ isMounted = true;
+ } else if (this._parent && this._parent._isMounted === true) {
+ isMounted = true;
+ }
+ if (!isMounted) {
+ return;
+ }
+ this.beforeMounted && this.beforeMounted();
+ this._isMounted = true;
+ this._mountChildren && this._mountChildren();
+ BI.each(this._children, function (i, widget) {
+ !self.isEnabled() && widget._setEnable(false);
+ !self.isValid() && widget._setValid(false);
+ widget._mount && widget._mount();
+ });
+ this.mounted && this.mounted();
+ },
+
+ _mountChildren: null,
+
+ isMounted: function () {
+ return this._isMounted;
+ },
+
+ setWidth: function (w) {
+ this.options.width = w;
+ this._initElementWidth();
+ },
+
+ setHeight: function (h) {
+ this.options.height = h;
+ this._initElementHeight();
+ },
+
+ _setEnable: function (enable) {
+ if (enable === true) {
+ this.options.disabled = false;
+ } else if (enable === false) {
+ this.options.disabled = true;
+ }
+ //递归将所有子组件使能
+ BI.each(this._children, function (i, child) {
+ !child._manualSetEnable && child._setEnable && child._setEnable(enable);
+ });
+ },
+
+ _setValid: function (valid) {
+ if (valid === true) {
+ this.options.invalid = false;
+ } else if (valid === false) {
+ this.options.invalid = true;
+ }
+ //递归将所有子组件使有效
+ BI.each(this._children, function (i, child) {
+ !child._manualSetValid && child._setValid && child._setValid(valid);
+ });
+ },
+
+ _setVisible: function (visible) {
+ if (visible === true) {
+ this.options.invisible = false;
+ } else if (visible === false) {
+ this.options.invisible = true;
+ }
+ },
+
+ setEnable: function (enable) {
+ this._manualSetEnable = true;
+ this._setEnable(enable);
+ if (enable === true) {
+ this.element.removeClass("base-disabled disabled");
+ } else if (enable === false) {
+ this.element.addClass("base-disabled disabled");
+ }
+ },
+
+ setVisible: function (visible) {
+ this._setVisible(visible);
+ if (visible === true) {
+ //用this.element.show()会把display属性改成block
+ this.element.css("display", "");
+ this._mount();
+ } else if (visible === false) {
+ this.element.css("display", "none");
+ }
+ this.fireEvent(BI.Events.VIEW, visible);
+ },
+
+ setValid: function (valid) {
+ this._manualSetValid = true;
+ this._setValid(valid);
+ if (valid === true) {
+ this.element.removeClass("base-invalid invalid");
+ } else if (valid === false) {
+ this.element.addClass("base-invalid invalid");
+ }
+ },
+
+ doBehavior: function () {
+ var args = arguments;
+ //递归将所有子组件使有效
+ BI.each(this._children, function (i, child) {
+ child.doBehavior && child.doBehavior.apply(child, args);
+ });
+ },
+
+ getWidth: function () {
+ return this.options.width;
+ },
+
+ getHeight: function () {
+ return this.options.height;
+ },
+
+ isValid: function () {
+ return !this.options.invalid;
+ },
+
+ addWidget: function (name, widget) {
+ var self = this;
+ if (name instanceof BI.Widget) {
+ widget = name;
+ name = widget.getName();
+ }
+ if (BI.isKey(name)) {
+ name = name + "";
+ }
+ name = name || widget.getName() || BI.uniqueId("widget");
+ if (this._children[name]) {
+ throw new Error("name has already been existed");
+ }
+ widget._setParent && widget._setParent(this);
+ widget.on(BI.Events.DESTROY, function () {
+ BI.remove(self._children, this);
+ });
+ return (this._children[name] = widget);
+ },
+
+ getWidgetByName: function (name) {
+ if (!BI.isKey(name) || name === this.getName()) {
+ return this;
+ }
+ name = name + "";
+ var widget = void 0, other = {};
+ BI.any(this._children, function (i, wi) {
+ if (i === name) {
+ widget = wi;
+ return true;
+ }
+ other[i] = wi;
+ });
+ if (!widget) {
+ BI.any(other, function (i, wi) {
+ return (widget = wi.getWidgetByName(i));
+ });
+ }
+ return widget;
+ },
+
+ removeWidget: function (nameOrWidget) {
+ var self = this;
+ if (BI.isWidget(nameOrWidget)) {
+ BI.remove(this._children, nameOrWidget);
+ } else {
+ delete this._children[nameOrWidget];
+ }
+ },
+
+ hasWidget: function (name) {
+ return this._children[name] != null;
+ },
+
+ getName: function () {
+ return this.widgetName;
+ },
+
+ setTag: function (tag) {
+ this.options.tag = tag;
+ },
+
+ getTag: function () {
+ return this.options.tag;
+ },
+
+ attr: function (key, value) {
+ if (BI.isNotNull(value)) {
+ return this.options[key] = value;
+ }
+ return this.options[key];
+ },
+
+ getText: function () {
+
+ },
+
+ setText: function (text) {
+
+ },
+
+ getValue: function () {
+
+ },
+
+ setValue: function (value) {
+
+ },
+
+ isEnabled: function () {
+ return !this.options.disabled;
+ },
+
+ isVisible: function () {
+ return !this.options.invisible;
+ },
+
+ disable: function () {
+ this.setEnable(false);
+ },
+
+ enable: function () {
+ this.setEnable(true);
+ },
+
+ valid: function () {
+ this.setValid(true);
+ },
+
+ invalid: function () {
+ this.setValid(false);
+ },
+
+ invisible: function () {
+ this.setVisible(false);
+ },
+
+ visible: function () {
+ this.setVisible(true);
+ },
+
+ __d: function () {
+ this.beforeDestroyed && this.beforeDestroyed();
+ BI.each(this._children, function (i, widget) {
+ widget._unMount && widget._unMount();
+ });
+ this._children = {};
+ this._parent = null;
+ this._isMounted = false;
+ this.destroyed && this.destroyed();
+ },
+
+ _unMount: function () {
+ this.__d();
+ this.fireEvent(BI.Events.UNMOUNT);
+ this.purgeListeners();
+ },
+
+ isolate: function () {
+ if (this._parent) {
+ this._parent.removeWidget(this);
+ }
+ BI.DOM.hang([this]);
+ },
+
+ empty: function () {
+ BI.each(this._children, function (i, widget) {
+ widget._unMount && widget._unMount();
+ });
+ this._children = {};
+ this.element.empty();
+ },
+
+ _destroy: function () {
+ this.__d();
+ this.element.destroy();
+ this.purgeListeners();
+ },
+
+ destroy: function () {
+ this.__d();
+ this.element.destroy();
+ this.fireEvent(BI.Events.DESTROY);
+ this.purgeListeners();
+ }
+});BI.Model = BI.inherit(BI.M, {
+ props: {},
+ init: null,
+ destroyed: null,
+
+ _defaultConfig: function () {
+ return BI.extend({
+ "default": "just a default",
+ "current": void 0
+ }, this.props)
+ },
+
+ _static: function () {
+ return {};
+ },
+
+ _init: function () {
+ BI.Model.superclass._init.apply(this, arguments);
+ this.on("change:current", function (obj, val) {
+ BI.isNotNull(val) && this.refresh(val);
+ }).on("change", function (changed, prev, context, options) {
+ if (this._start === true || BI.has(changed, "current")) {
+ return;
+ }
+ this.actionStart();
+ if (!this.local()) {
+ !BI.has(this._tmp, BI.keys(changed)) && this.parent && this.parent._change(this);
+ this._changing_ = true;
+ this.change(changed, prev, context, options);
+ this._changing_ = false;
+ }
+ });
+
+ this._tmp = {};//过渡属性
+
+ this._hass = {};
+ this._gets = [];//记录交互行为
+ this._start = false;
+ this._changing_ = false;
+
+ this._read = BI.debounce(BI.bind(this.fetch, this), 30);
+ this._save = BI.debounce(BI.bind(this.save, this), 30);
+ this._F = [];
+ this.init && this.init();
+ },
+
+ toJSON: function () {
+ var json = BI.Model.superclass.toJSON.apply(this, arguments);
+ delete json["baseCls"];
+ delete json["current"];
+ delete json["default"];
+ delete json["parent"];
+ delete json["rootURL"];
+ delete json["id"];
+ delete json["tag"];
+ BI.each(this._gets, function (i, action) {
+ delete json[action];
+ });
+ return json;
+ },
+
+ copy: function () {
+ if (this._start === true || this._changing_ === true) {
+ this._F.push({f: this.copy, arg: arguments});
+ return;
+ }
+ this.trigger("copy");
+ },
+ //子节点的一个类似副本
+ similar: function (value, key1, key2, key3) {
+ return value;
+ },
+
+ _map: function (child) {
+ var self = this;
+ var map = {}, current = {};
+ var mapping = function (key, ch) {
+ key = key + "";
+ if (key === "") {
+ return;
+ }
+ var keys = key.split('.');
+ if (!map[keys[0]]) {
+ map[keys[0]] = self.get(keys[0]);
+ }
+ var parent = map, last = void 0;
+ BI.each(keys, function (i, k) {
+ last && (parent = parent[last] || (parent[last] = {}));
+ last = k;
+ });
+ parent[last] = ch.toJSON();
+ };
+ BI.each(this._childs, function (key, chs) {
+ if (!BI.isArray(chs)) {
+ chs = [chs];
+ }
+ BI.each(chs, function (i, ch) {
+ if (ch === child) {
+ current[key] = child;
+ return;
+ }
+ //mapping(key, ch);
+ })
+ });
+ BI.each(current, function (key, ch) {
+ mapping(key, ch);
+ });
+ var tmp = {};
+ BI.each(this._tmp, function (k) {
+ if (map[k]) {
+ tmp[k] = map[k];
+ delete map[k];
+ }
+ });
+ this.tmp(tmp);
+ return map;
+ },
+
+ _change: function (child) {
+ this.set(this._map(child));
+ return this;
+ },
+
+ splice: function (old, key1, key2, key3) {
+
+ },
+
+ duplicate: function (copy, key1, key2, key3) {
+
+ },
+
+ change: function (changed, prev) {
+
+ },
+
+ actionStart: function () {
+ this._start = true;
+ return this;
+ },
+
+ actionEnd: function () {
+ var self = this;
+ this._start = false;
+ var _gets = this._gets.slice(0), _F = this._F.slice(0);
+ this._gets = [];
+ this._hass = {};
+ this._F = [];
+ BI.each(_gets, function (i, action) {
+ self.unset(action, {silent: true});
+ });
+ BI.each(_F, function (i, fn) {
+ fn.f.apply(self, fn.arg);
+ });
+ return this;
+ },
+
+ addChild: function (name, child) {
+ name = name + "";
+ var self = this;
+ this._childs || (this._childs = {});
+ if (this._childs[name]) {
+ if (BI.isArray(this._childs[name])) {
+ this._childs[name].push(child);
+ } else {
+ this._childs[name] = [this._childs[name]].concat(child)
+ }
+ } else {
+ this._childs[name] = child;
+ }
+ child && child.on("destroy", function () {
+ var keys = name.split('.');
+ var g = self.get(keys[0]), p, c;
+ var sset = !!self._tmp[keys[0]] ? "tmp" : "set", unset = "un" + sset;
+
+ BI.each(keys, function (i, k) {
+ if (i === 0) {
+ c = g;
+ return;
+ }
+ p = c;
+ c = c[k];
+ });
+ self.removeChild(name, child);
+ var newKeys = BI.clone(keys);
+ keys.length > 1 ? newKeys.unshift(BI.deepClone(p[keys[keys.length - 1]])) : newKeys.unshift(BI.deepClone(g));
+ keys.length > 1 ? (delete p[keys[keys.length - 1]], self[sset](keys[0], g, {silent: true})) : self[unset](name, {silent: true});
+ !BI.has(self._tmp, keys[0]) && self.parent && self.parent._change(self);
+ self.splice.apply(self, newKeys);
+ self.trigger("splice", newKeys);
+ BI.remove(self._childs, child);
+ }).on("copy", function () {
+ var keys = name.split('.');
+ var g = self.get(keys[0]), p, c;
+ var sset = !!self._tmp[keys[0]] ? "tmp" : "set";
+ BI.each(keys, function (i, k) {
+ if (i === 0) {
+ c = g;
+ return;
+ }
+ p = c;
+ c = c[k];
+ });
+ var copy = BI.UUID(), newKeys = BI.clone(keys);
+ keys.length > 1 ? newKeys.unshift(BI.deepClone(p[keys[keys.length - 1]])) : newKeys.unshift(BI.deepClone(g));
+ var backup = self.similar.apply(self, newKeys);
+ if (BI.isKey(backup.id)) {
+ copy = backup.id;
+ delete backup.id;
+ }
+ keys.length > 1 ? (p[copy] = backup, self[sset](keys[0], g, {silent: true})) : self[sset](copy, backup, {silent: true});
+ keys.unshift(copy);
+ !BI.has(self._tmp, keys[0]) && self.parent && self.parent._change(self);
+ self.duplicate.apply(self, keys);
+ self.trigger("duplicate", keys);
+ });
+ },
+
+ removeChild: function (name, child) {
+ if (BI.isArray(this._childs[name])) {
+ BI.remove(this._childs[name], child);
+ if (BI.isEmpty(this._childs[name])) {
+ delete this._childs[name];
+ }
+ return;
+ }
+ delete this._childs[name];
+ },
+
+ has: function (attr, istemp) {
+ if (istemp === true) {
+ return _.has(this.tmp, attr);
+ }
+ if (this._start === true && this._changing_ === false) {
+ this._hass[attr] = true;
+ }
+ return BI.Model.superclass.has.apply(this, arguments);
+ },
+
+ cat: function (attr) {
+ if (_.has(this._tmp, attr)) {
+ return this._tmp[attr];
+ }
+ if (this._start === true && this._hass[attr]) {
+ delete this._hass[attr];
+ switch (attr) {
+ case "default":
+ break;
+ case "current":
+ break;
+ default :
+ this._gets.push(attr);
+ break;
+ }
+ }
+ if (_.has(this.attributes, attr)) {
+ return this.attributes[attr];
+ }
+ var sta = _.result(this, "_static");
+ return BI.isFunction(sta[attr]) ? sta[attr].apply(this, BI.values(arguments).slice(1)) : sta[attr];
+ },
+
+ get: function () {
+ return BI.deepClone(this.cat.apply(this, arguments));
+ },
+
+ set: function (key, val, options) {
+ if (this._start === true || this._changing_ === true) {
+ this._F.push({f: this.set, arg: arguments});
+ return this;
+ }
+ return BI.Model.superclass.set.apply(this, arguments);
+ },
+
+ unset: function (attr, options) {
+ var self = this;
+ BI.each(this._childs, function (key, model) {
+ key = key + "";
+ var keys = key.split('.');
+ if (_.isEqual(attr, keys[0])) {
+ delete self._childs[attr];
+ if (!BI.isArray(model)) {
+ model = [model];
+ }
+ BI.each(model, function (i, m) {
+ m.trigger("unset");
+ });
+ }
+ });
+ return BI.Model.superclass.unset.apply(this, arguments);
+ },
+
+ tmp: function (key, val, options) {
+ if (this._start === true || this._changing_ === true) {
+ this._F.push({f: this.tmp, arg: arguments});
+ return this;
+ }
+ var attr, attrs, unset, changes, silent, changing, changed, prev, current;
+ if (key == null) return this;
+ if (typeof key === 'object') {
+ attrs = key;
+ options = val;
+ } else {
+ (attrs = {})[key] = val;
+ }
+ options || (options = {});
+
+ unset = options.unset;
+ silent = options.silent;
+ changes = [];
+ changing = this._changingTmp;
+ this._changingTmp = true;
+
+ if (!changing) {
+ this._previousTmp = _.clone(this._tmp);
+ this.changedTmp = {};
+ }
+ if (!this._previousTmp) {
+ this._previousTmp = _.clone(this._tmp);
+ }
+ current = this._tmp, prev = this._previousTmp;
+
+ for (attr in attrs) {
+ val = attrs[attr];
+ if (!_.isEqual(current[attr], val)) changes.push(attr);
+ if (!_.isEqual(prev[attr], val)) {
+ this.changedTmp[attr] = val;
+ } else {
+ delete this.changedTmp[attr];
+ }
+ unset ? delete current[attr] : current[attr] = val;
+ }
+
+ if (!silent) {
+ if (changes.length) this._pendingTmp = options;
+ for (var i = 0, length = changes.length; i < length; i++) {
+ this.trigger('change:' + changes[i], this, current[changes[i]], options);
+ }
+ }
+
+ if (changing) return this;
+ changed = BI.clone(this.changedTmp);
+ if (!silent) {
+ while (this._pendingTmp) {
+ options = this._pendingTmp;
+ this._pendingTmp = false;
+ this.trigger('change', changed, prev, this, options);
+ }
+ }
+ this._pendingTmp = false;
+ this._changingTmp = false;
+ if (!silent && changes.length) this.trigger("changed", changed, prev, this, options);
+ return this;
+ },
+
+ untmp: function (attr, options) {
+ var self = this;
+ BI.each(this._childs, function (key, model) {
+ key = key + "";
+ var keys = key.split('.');
+ if (_.isEqual(attr, keys[0])) {
+ delete self._childs[attr];
+ if (!BI.isArray(model)) {
+ model = [model];
+ }
+ BI.each(model, function (i, m) {
+ m.trigger("unset");
+ });
+ }
+ });
+ return this.tmp(attr, void 0, _.extend({}, options, {unset: true}));
+ },
+
+ cancel: function (options) {
+ var self = this;
+ var tmp = BI.clone(this._tmp);
+ this._tmp = {};
+ BI.each(tmp, function (k) {
+ self.untmp(k, options);
+ });
+ },
+
+ submit: function () {
+ var tmp = BI.clone(this._tmp);
+ this._tmp = {};
+ this.set(tmp);
+ return this;
+ },
+
+ urlRoot: function () {
+ return BI.servletURL;
+ },
+
+ parse: function (data) {
+ return data;
+ },
+
+ setEditing: function (edit) {
+ this._editing = edit;
+ },
+
+ getEditing: function () {
+ if (this._start !== true) {
+ throw new Error("getEditing函数只允许在local中调用");
+ }
+ return this._editing;
+ },
+
+ local: function () {
+
+ },
+
+ load: function (data) {
+
+ },
+
+ refresh: function () {
+
+ },
+
+ /**
+ * 更新整个model
+ */
+ updateURL: function () {
+
+ },
+ /**
+ * 添加一个元素或删除一个元素或修改一个元素
+ */
+ patchURL: function () {
+
+ },
+ /**
+ * 删除整个model, destroy方法调用
+ */
+ deleteURL: function () {
+
+ },
+ /**
+ * 读取model
+ */
+ readURL: function () {
+
+ },
+
+ read: function (options) {
+ if (this._start == true || this._changing_ === true) {
+ this._F.push({f: this.read, arg: arguments});
+ return;
+ }
+ this._read(options);
+ },
+
+ update: function (options) {
+ if (this._start == true || this._changing_ === true) {
+ this._F.push({f: this.update, arg: arguments});
+ return;
+ }
+ this._save(null, options);
+ },
+
+ patch: function (options) {
+ if (this._start == true || this._changing_ === true) {
+ this._F.push({f: this.patch, arg: arguments});
+ return;
+ }
+ this._save(null, BI.extend({}, options, {
+ patch: true
+ }));
+ },
+
+ _destroy: function () {
+ var children = BI.extend({}, this._childs);
+ this._childs = {};
+ BI.each(children, function (i, child) {
+ child._destroy();
+ });
+ this.destroyed && this.destroyed();
+ },
+
+ destroy: function () {
+ this._destroy();
+ BI.Model.superclass.destroy.apply(this, arguments);
+ }
+});/**
+ * @class BI.View
+ * @extends BI.V
+ * @type {*|void|Object}
+ */
+BI.View = BI.inherit(BI.V, {
+
+ //生命周期函数
+ beforeCreate: null,
+
+ created: null,
+
+ beforeDestroyed: null,
+
+ destroyed: null,
+
+ _init: function () {
+ BI.View.superclass._init.apply(this, arguments);
+ this.beforeCreate && this.beforeCreate();
+ var self = this;
+ this.listenTo(this.model, "change:current", function (obj, val) {
+ if (BI.isNotNull(val) && val.length > 0) {
+ this.refresh(val);
+ }
+ }).listenTo(this.model, "change", function (changed) {
+ this.delegateEvents();
+ }).listenTo(this.model, "changed", function (changed, prev, context, options) {
+ if (BI.has(changed, "current") && BI.size(changed) > 1) {
+ throw new Error("refresh操作不能调用set操作");
+ }
+ var notLocal = !BI.has(changed, "current") && !this.local() && this.notifyParent().notify();
+ this.model.actionEnd() && this.actionEnd();
+ this.model._changing_ = true;
+ notLocal && !BI.isEmpty(changed) && this.change(changed, prev, context, options);
+ this.model._changing_ = false;
+ this.model.actionEnd() && this.actionEnd();
+ }).listenTo(this.model, "destroy", function () {
+ this._destroy();
+ }).listenTo(this.model, "unset", function () {
+ this._destroy();
+ }).listenTo(this.model, "splice", function (arg) {
+ this.splice.apply(this, arg);
+ }).listenTo(this.model, "duplicate", function (arg) {
+ this.duplicate.apply(this, arg);
+ });
+ this._F = [];
+ var flatten = ["_init", "_defaultConfig", "_vessel", "_render", "getName", "listenEnd", "local", "refresh", "load", "change"];
+ flatten = BI.makeObject(flatten, true);
+ BI.each(this.constructor.caller.caller.prototype, function (key) {
+ if (flatten[key]) {
+ return;
+ }
+ var f = self[key];
+ if (BI.isFunction(f)) {
+ self[key] = BI.bind(function () {
+ if (this.model._start === true) {
+ this._F.push({f: f, arg: arguments});
+ return;
+ }
+ return f.apply(this, arguments);
+ }, self);
+ }
+ });
+ this.created && this.created();
+ },
+
+ change: function (changed, prev) {
+
+ },
+
+ actionEnd: function () {
+ var self = this;
+ var _F = this._F.slice(0);
+ this._F = [];
+ BI.each(_F, function (i, f) {
+ f.f.apply(self, f.arg);
+ });
+ return this;
+ },
+
+ delegateEvents: function (events) {
+ if (!(events || (events = BI.deepClone(_.result(this, 'events'))))) return this;
+ var delegateEventSplitter = /^(\S+)\s*(.*)$/;
+ for (var key in events) {
+ var method = events[key];
+ if (!_.isFunction(method)) method = this[events[key]];
+ if (!method) continue;
+ var match = key.match(delegateEventSplitter);
+ var ev = true;
+ switch (match[1]) {
+ case "draggable":
+ break;
+ case "droppable":
+ break;
+ case "sortable":
+ break;
+ case "resizable":
+ break;
+ case "hover":
+ break;
+ default :
+ ev = false;
+ break;
+ }
+
+ var off = new BI.OffList({
+ event: match[1] + '.delegateEvents' + this.cid
+ });
+
+ var keys = match[2].split('.');
+ var handle = keys[1];
+ var bind = ev ? new BI.EventList({
+ event: match[1],
+ handle: handle,
+ callback: BI.bind(method, this)
+ }) : new BI.ListenerList({
+ event: match[1] + '.delegateEvents' + this.cid,
+ handle: handle,
+ callback: BI.bind(method, this),
+ context: this
+ });
+
+ var list = [];
+ if (this[keys[0]] && (this[keys[0]] instanceof $ || this[keys[0]].element instanceof $)) {
+ list = [this[keys[0]]]
+ delete events[key];
+ } else if (BI.isArray(this[keys[0]]) || BI.isPlainObject(this[keys[0]])) {
+ list = this[keys[0]]
+ delete events[key];
+ }
+ off.populate(list);
+ bind.populate(list);
+ }
+ return BI.View.superclass.delegateEvents.apply(this, [events]);
+ },
+
+ _vessel: function () {
+ this._cardLayouts = {};
+ this._cardLayouts[this.getName()] = new BI.CardLayout({
+ element: this
+ });
+ var vessel = BI.createWidget();
+ this._cardLayouts[this.getName()].addCardByName(this.getName(), vessel);
+ return vessel;
+ },
+
+ render: function (vessel) {
+ return this;
+ },
+
+ /**
+ * 创建儿子所在容器
+ * @param key
+ * @param vessel
+ * @param options isLayer:是否是弹出层, defaultShowName:默认显示项
+ * @returns {BI.View}
+ */
+ addSubVessel: function (key, vessel, options) {
+ options || (options = {});
+ this._cardLayouts || (this._cardLayouts = {});
+ var id = key + this.cid;
+ options.isLayer && (vessel = BI.Layers.has(id) ? BI.Layers.get(id) : BI.Layers.create(id, vessel));
+ if (this._cardLayouts[key]) {
+ options.defaultShowName && this._cardLayouts[key].setDefaultShowName(options.defaultShowName);
+ return this;
+ }
+ this._cardLayouts[key] = BI.createWidget({
+ type: "bi.card",
+ element: vessel,
+ defaultShowName: options.defaultShowName
+ });
+ return this;
+ },
+
+ removeSubVessel: function (key) {
+ var self = this, id = key + this.cid;
+ BI.Layers.remove(id);
+ var cardNames = this._cardLayouts[key] && this._cardLayouts[key].getAllCardNames();
+ BI.each(cardNames, function (i, name) {
+ delete self._cards[name];
+ });
+ this._cardLayouts[key] && this._cardLayouts[key]._destroy();
+ return this;
+ },
+
+ createView: function (url, modelData, viewData) {
+ return BI.Factory.createView(url, this.get(url), modelData, viewData);
+ },
+
+ /**
+ * 跳转到指定的card
+ * @param cardName
+ */
+ skipTo: function (cardName, layout, modelData, viewData, options) {
+ if (this.model._start === true || this._changing_ === true) {
+ this._F.push({f: this.skipTo, arg: arguments});
+ return this;
+ }
+ var self = this, isValid = BI.isKey(modelData), data = void 0;
+ BI.isKey(layout) && (layout = layout + "");
+ layout = layout || this.getName();
+ options || (options = {});
+ if (isValid) {
+ modelData = modelData + "";//避免modelData是数字
+ var keys = modelData.split('.');
+ BI.each(keys, function (i, k) {
+ if (i === 0) {
+ data = self.model.get(k) || {};
+ } else {
+ data = data[k] || {};
+ }
+ });
+ data.id = options.id || keys[keys.length - 1];
+ } else {
+ data = modelData;
+ }
+ BI.extend(data, options.data);
+ var action = options.action || new BI.ShowAction();
+ var cardLayout = this._cardLayouts[layout];
+ if (!cardLayout) {
+ return this;
+ }
+ cardLayout.setVisible(true);
+ if (BI.isKey(cardName) && !cardLayout.isCardExisted(cardName)) {
+ var view = this.createView(this.rootURL + "/" + cardName, data, viewData);
+ isValid && this.model.addChild(modelData, view.model);
+ view.listenTo(view.model, "destroy", function () {
+ delete self._cards[cardName];
+ cardLayout.deleteCardByName(cardName);
+ if (cardLayout.isAllCardHide()) {
+ cardLayout.setVisible(false);
+ BI.Layers.hide(layout + self.cid);
+ }
+ }).listenTo(view.model, "unset", function () {
+ delete self._cards[cardName];
+ cardLayout.deleteCardByName(cardName);
+ });
+ cardLayout.addCardByName(cardName, view);
+ this._cards || (this._cards = {});
+ this._cards[cardName] = view;
+ data = {};
+ this.on("end:" + view.cid, function () {
+ var isNew = false, t, keys;
+ if (isValid) {
+ keys = modelData.split('.');
+ BI.each(keys, function (i, k) {
+ if (i === 0) {
+ t = self.model.get(k) || (isNew = true);
+ } else {
+ t = t[k] || (isNew = true);
+ }
+ });
+ }
+ if (isNew) {
+ delete self._cards[cardName];
+ self.model.removeChild(modelData, view.model);
+ cardLayout.deleteCardByName(cardName);
+ view._destroy();
+ cardLayout.setVisible(false);
+ }
+ action.actionBack(view, null, function () {
+ if (cardLayout.isAllCardHide()) {
+ cardLayout.setVisible(false);
+ BI.Layers.hide(layout + self.cid);
+ }
+ !isNew && (self.listenEnd.apply(self, isValid ? keys : [modelData]) !== false) && self.populate();
+ })
+ }).on("change:" + view.cid, _.bind(this.notifyParent, this));
+ }
+ BI.isKey(cardName) && BI.Layers.show(layout + this.cid);
+ cardLayout.showCardByName(cardName, action, function () {
+ BI.isKey(cardName) && self._cards[cardName].populate(data, options);
+ });
+ !BI.isKey(cardName) && BI.Layers.hide(layout + this.cid);
+ return this._cards[cardName];
+ },
+
+ listenEnd: function (key1, key2, key3) {
+ return this;
+ },
+
+ /**
+ * 告诉父亲我的操作结束了,后面的事情任由父亲处置
+ * @param force 强制下次再次进入该节点时不进行刷新操作, 默认执行刷新
+ * @returns {BI.View}
+ */
+ notifyParentEnd: function (force) {
+ this.parent && this.parent.trigger("end:" + this.cid);
+ this.trigger("end");
+ !force && this.notify();
+ return this;
+ },
+
+ /**
+ * 通知父亲我的数据发生了变化
+ */
+ notifyParent: function () {
+ this.parent && this.parent.notify().trigger("change:" + this.cid);
+ return this;
+ },
+
+ /**
+ * 告诉Model数据改变了
+ */
+ notify: function () {
+ this.model.unset("current", {silent: true});
+ return this;
+ },
+
+ getName: function () {
+ return "VIEW"
+ },
+
+ /**
+ * 全局刷新
+ * @param current
+ */
+ refresh: function (current) {
+ },
+ /**
+ * 局部刷新
+ */
+ local: function () {
+ return false;
+ },
+
+ load: function (data) {
+
+ },
+
+ readData: function (force, options) {
+ options || (options = {});
+ var self = this;
+ var args = [].slice.call(arguments, 2);
+ if (!force && this._readed === true) {//只从后台获取一次数据
+ callback(this.model.toJSON());
+ return;
+ }
+ //采用静默方式读数据,该数据变化不引起data的change事件触发
+ var success = options.success;
+ this.model.read(BI.extend({
+ silent: true
+ }, options, {
+ success: function (data, model) {
+ callback(data);
+ !force && (self._readed = true);
+ self.delegateEvents();
+ success && success(data, model);
+ }
+ }));
+ function callback(data) {
+ self.model.load(data);
+ self.load(data);
+ BI.each(args, function (i, arg) {
+ if (BI.isFunction(arg)) {
+ arg.apply(self, [data]);
+ }
+ })
+ }
+ },
+
+ //处理model的通用方法
+ cat: function () {
+ return this.model.cat.apply(this.model, arguments);
+ },
+
+ get: function () {
+ return this.model.get.apply(this.model, arguments);
+ },
+
+ set: function () {
+ return this.model.set.apply(this.model, arguments);
+ },
+
+ has: function () {
+ return this.model.has.apply(this.model, arguments);
+ },
+
+ getEditing: function () {
+ return this.model.getEditing();
+ },
+
+ reading: function (options) {
+ var self = this;
+ var name = BI.UUID();
+ this.model.read(BI.extend({}, options, {
+ beforeSend: function () {
+ var loading = BI.createWidget({
+ type: 'bi.vertical',
+ items: [{
+ type: "bi.layout",
+ height: 30,
+ cls: "loading-background"
+ }],
+ element: BI.Maskers.make(name, self)
+ });
+ loading.setVisible(true);
+ },
+ complete: function (data) {
+ options.complete && options.complete(data);
+ BI.Maskers.remove(name);
+ }
+ }));
+ },
+
+ updating: function (options) {
+ var self = this;
+ var name = BI.UUID();
+ this.model.update(BI.extend({}, options, {
+ noset: true,
+ beforeSend: function () {
+ var loading = BI.createWidget({
+ type: 'bi.vertical',
+ items: [{
+ type: "bi.layout",
+ height: 30,
+ cls: "loading-background"
+ }],
+ element: BI.Maskers.make(name, self)
+ });
+ loading.setVisible(true);
+ },
+ complete: function (data) {
+ options.complete && options.complete(data);
+ BI.Maskers.remove(name);
+ }
+ }));
+ },
+
+ patching: function (options) {
+ var self = this;
+ var name = BI.UUID();
+ this.model.patch(BI.extend({}, options, {
+ noset: true,
+ beforeSend: function () {
+ var loading = BI.createWidget({
+ type: 'bi.vertical',
+ items: [{
+ type: "bi.layout",
+ height: 30,
+ cls: "loading-background"
+ }],
+ element: BI.Maskers.make(name, self)
+ });
+ loading.setVisible(true);
+ },
+ complete: function (data) {
+ options.complete && options.complete(data);
+ BI.Maskers.remove(name);
+ }
+ }));
+ },
+
+ populate: function (modelData, options) {
+ var self = this;
+ options || (options = {});
+ if (options.force === true) {
+ this.notify();
+ }
+ if (this._cardLayouts && this._cardLayouts[this.getName()]) {
+ this._cardLayouts[this.getName()].showCardByName(this.getName());
+ }
+ //BI.each(this._cardLayouts, function (key, layout) {
+ // layout.showCardByName(layout.getDefaultShowName() || self.getName());
+ //});
+ //BI.each(this._cards, function (i, card) {
+ // card.notify && card.notify();
+ //});
+ if (this._F.length > 0) {
+ throw new Error("流程错误");
+ }
+ if (options.force === true) {
+ this.model.set(modelData, options).set({current: this.model.get("default")});
+ return;
+ }
+ if (options.force === false) {
+ this.model.set(modelData);
+ return;
+ }
+ var filter = BI.clone(modelData || {});
+ delete filter.id;
+ var contains = BI.has(this.model.toJSON(), _.keys(filter));
+ var match = BI.isEmpty(filter) || (contains && this.model.matches(modelData));
+ if (match === true) {
+ this.model.set({current: this.model.get("default")});
+ } else if (contains === false) {
+ this.model.set(modelData);
+ } else {
+ this.model.set(modelData, options).set({current: this.model.get("default")});
+ }
+ },
+
+ //删除子节点触发
+ splice: function (old, key1, key2, key3) {
+
+ },
+
+ //复制子节点触发
+ duplicate: function (copy, key1, key2, key3) {
+
+ },
+
+ _unMount: function () {
+ this.beforeDestroyed && this.beforeDestroyed();
+ BI.each(this._cardLayouts, function (name, card) {
+ card && card._unMount();
+ });
+ delete this._cardLayouts;
+ delete this._cards;
+ this.destroyed && this.destroyed();
+ this.trigger(BI.Events.UNMOUNT);
+ this.off();
+ },
+
+ _destroy: function () {
+ var self = this;
+ BI.each(this._cardLayouts, function (name, card) {
+ card && card._unMount();
+ BI.Layers.remove(name + self.cid);
+ });
+ delete this._cardLayouts;
+ delete this._cards;
+ this.destroyed && this.destroyed();
+ this.remove();
+ this.trigger(BI.Events.DESTROY);
+ this.off();
+ }
+});(function () {
+
+ var kv = {}; // alex:键(编辑器简称,如text)值(也是一个字符串,如FR.TextEditor)对
+ BI.shortcut = function (xtype, cls) {
+ if (kv[xtype] != null) {
+ throw ("shortcut:[" + xtype + "] has been registed");
+ }
+ kv[xtype] = cls;
+ _.extend(cls.prototype, {
+ xtype: xtype
+ })
+ };
+
+ // 根据配置属性生成widget
+ var createWidget = function (config) {
+ if (config['classType']) {
+ return new (new Function('return ' + config['classType'] + ';')())(config);
+ }
+
+ if (!config.type) {
+
+ }
+ var xtype = config.type.toLowerCase();
+ var cls = kv[xtype];
+ return new cls(config);
+ };
+
+ BI.createWidget = function (item, options) {
+ var el;
+ options || (options = {});
+ if (BI.isEmpty(item) && BI.isEmpty(options)) {
+ return BI.createWidget({
+ type: "bi.layout"
+ });
+ }
+ if (BI.isWidget(item)) {
+ return item;
+ }
+ if (item && (item.type || options.type)) {
+ el = BI.extend({}, options, item);
+ return BI.Plugin.getObject(el.type, createWidget(BI.Plugin.getWidget(el.type, el)));
+ }
+ if (item && item.el && (item.el.type || options.type)) {
+ el = BI.extend({}, options, item.el);
+ return BI.Plugin.getObject(el.type, createWidget(BI.Plugin.getWidget(el.type, el)));
+ }
+ if (item && BI.isWidget(item.el)) {
+ return item.el;
+ }
+ throw new Error('无法根据item创建组件');
+ }
+
+})();(function (window, undefined) {
+ function aspect(type) {
+ return function (target, methodName, advice) {
+ var exist = target[methodName],
+ dispatcher;
+
+ if (!exist || exist.target != target) {
+ dispatcher = target[methodName] = function () {
+ // before methods
+ var beforeArr = dispatcher.before;
+ var args = arguments, next;
+ for (var l = beforeArr.length; l--;) {
+ next = beforeArr[l].advice.apply(this, args);
+ if (next === false) {
+ return false;
+ }
+ args = next || args;
+ }
+ // target method
+ var rs = dispatcher.method.apply(this, args);
+ // after methods
+ var afterArr = dispatcher.after;
+ for (var i = 0, ii = afterArr.length; i < ii; i++) {
+ next = afterArr[i].advice.call(this, rs, args);
+ if (rs === false) {
+ return false;
+ }
+ args = next || args;
+ }
+ return rs;
+ };
+
+ dispatcher.before = [];
+ dispatcher.after = [];
+
+ if (exist) {
+ dispatcher.method = exist;
+ }
+ dispatcher.target = target;
+ }
+
+ var aspectArr = (dispatcher || exist)[type];
+ var obj = {
+ advice: advice,
+ _index: aspectArr.length,
+ remove: function () {
+ aspectArr.splice(this._index, 1);
+ }
+ };
+ aspectArr.push(obj);
+
+ return obj;
+ };
+ }
+
+ BI.aspect = {
+ before: aspect("before"),
+ after: aspect("after")
+ };
+
+ return BI.aspect;
+
+})(window);;
+!(function () {
+
+ var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+
+
+ // private method for UTF-8 encoding
+ var _utf8_encode = function (string) {
+ string = string.replace(/\r\n/g, "\n");
+ var utftext = "";
+
+ for (var n = 0; n < string.length; n++) {
+
+ var c = string.charCodeAt(n);
+
+ if (c < 128) {
+ utftext += String.fromCharCode(c);
+ } else if ((c > 127) && (c < 2048)) {
+ utftext += String.fromCharCode((c >> 6) | 192);
+ utftext += String.fromCharCode((c & 63) | 128);
+ } else {
+ utftext += String.fromCharCode((c >> 12) | 224);
+ utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+
+ }
+
+ return utftext;
+ };
+
+ // private method for UTF-8 decoding
+ var _utf8_decode = function (utftext) {
+ var string = "";
+ var i = 0;
+ var c = 0, c3 = 0, c2 = 0;
+
+ while (i < utftext.length) {
+
+ c = utftext.charCodeAt(i);
+
+ if (c < 128) {
+ string += String.fromCharCode(c);
+ i++;
+ } else if ((c > 191) && (c < 224)) {
+ c2 = utftext.charCodeAt(i + 1);
+ string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
+ i += 2;
+ } else {
+ c2 = utftext.charCodeAt(i + 1);
+ c3 = utftext.charCodeAt(i + 2);
+ string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+ i += 3;
+ }
+
+ }
+ return string;
+ };
+
+ _.extend(BI, {
+
+ encode: function (input) {
+ var output = "";
+ var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
+ var i = 0;
+
+ input = _utf8_encode(input);
+
+ while (i < input.length) {
+
+ chr1 = input.charCodeAt(i++);
+ chr2 = input.charCodeAt(i++);
+ chr3 = input.charCodeAt(i++);
+
+ enc1 = chr1 >> 2;
+ enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+ enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+ enc4 = chr3 & 63;
+
+ if (isNaN(chr2)) {
+ enc3 = enc4 = 64;
+ } else if (isNaN(chr3)) {
+ enc4 = 64;
+ }
+
+ output = output + _keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4);
+
+ }
+
+ return output;
+ },
+
+ // public method for decoding
+ decode: function (input) {
+ var output = "";
+ var chr1, chr2, chr3;
+ var enc1, enc2, enc3, enc4;
+ var i = 0;
+
+ input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+
+ while (i < input.length) {
+
+ enc1 = _keyStr.indexOf(input.charAt(i++));
+ enc2 = _keyStr.indexOf(input.charAt(i++));
+ enc3 = _keyStr.indexOf(input.charAt(i++));
+ enc4 = _keyStr.indexOf(input.charAt(i++));
+
+ chr1 = (enc1 << 2) | (enc2 >> 4);
+ chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+ chr3 = ((enc3 & 3) << 6) | enc4;
+
+ output = output + String.fromCharCode(chr1);
+
+ if (enc3 != 64) {
+ output = output + String.fromCharCode(chr2);
+ }
+ if (enc4 != 64) {
+ output = output + String.fromCharCode(chr3);
+ }
+
+ }
+
+ output = _utf8_decode(output);
+
+ return output;
+
+ }
+ })
+})();BI.CellSizeAndPositionManager = function (cellCount, cellSizeGetter, estimatedCellSize) {
+ this._cellSizeGetter = cellSizeGetter;
+ this._cellCount = cellCount;
+ this._estimatedCellSize = estimatedCellSize;
+ this._cellSizeAndPositionData = {};
+ this._lastMeasuredIndex = -1;
+};
+
+BI.CellSizeAndPositionManager.prototype = {
+ constructor: BI.CellSizeAndPositionManager,
+ configure: function (cellCount, estimatedCellSize) {
+ this._cellCount = cellCount;
+ this._estimatedCellSize = estimatedCellSize;
+ },
+
+ getCellCount: function () {
+ return this._cellCount;
+ },
+
+ getEstimatedCellSize: function () {
+ return this._estimatedCellSize;
+ },
+
+ getLastMeasuredIndex: function () {
+ return this._lastMeasuredIndex;
+ },
+
+ getSizeAndPositionOfCell: function (index) {
+ if (index < 0 || index >= this._cellCount) {
+ return;
+ }
+ if (index > this._lastMeasuredIndex) {
+ var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell();
+ var offset = lastMeasuredCellSizeAndPosition.offset + lastMeasuredCellSizeAndPosition.size;
+
+ for (var i = this._lastMeasuredIndex + 1; i <= index; i++) {
+ var size = this._cellSizeGetter(i);
+
+ if (size == null || isNaN(size)) {
+ continue;
+ }
+
+ this._cellSizeAndPositionData[i] = {
+ offset: offset,
+ size: size
+ };
+
+ offset += size;
+ }
+
+ this._lastMeasuredIndex = index;
+ }
+ return this._cellSizeAndPositionData[index];
+ },
+
+ getSizeAndPositionOfLastMeasuredCell: function () {
+ return this._lastMeasuredIndex >= 0
+ ? this._cellSizeAndPositionData[this._lastMeasuredIndex]
+ : {
+ offset: 0,
+ size: 0
+ }
+ },
+
+ getTotalSize: function () {
+ var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell();
+ return lastMeasuredCellSizeAndPosition.offset + lastMeasuredCellSizeAndPosition.size + (this._cellCount - this._lastMeasuredIndex - 1) * this._estimatedCellSize
+ },
+
+ getUpdatedOffsetForIndex: function (align, containerSize, currentOffset, targetIndex) {
+ var datum = this.getSizeAndPositionOfCell(targetIndex);
+ var maxOffset = datum.offset;
+ var minOffset = maxOffset - containerSize + datum.size;
+
+ var idealOffset;
+
+ switch (align) {
+ case 'start':
+ idealOffset = maxOffset;
+ break;
+ case 'end':
+ idealOffset = minOffset;
+ break;
+ case 'center':
+ idealOffset = maxOffset - ((containerSize - datum.size) / 2);
+ break;
+ default:
+ idealOffset = Math.max(minOffset, Math.min(maxOffset, currentOffset));
+ break;
+ }
+
+ var totalSize = this.getTotalSize();
+
+ return Math.max(0, Math.min(totalSize - containerSize, idealOffset));
+ },
+
+ getVisibleCellRange: function (containerSize, offset) {
+ var totalSize = this.getTotalSize();
+
+ if (totalSize === 0) {
+ return {}
+ }
+
+ var maxOffset = offset + containerSize;
+ var start = this._findNearestCell(offset);
+
+ var datum = this.getSizeAndPositionOfCell(start);
+ offset = datum.offset + datum.size;
+
+ var stop = start;
+
+ while (offset < maxOffset && stop < this._cellCount - 1) {
+ stop++;
+ offset += this.getSizeAndPositionOfCell(stop).size;
+ }
+
+ return {
+ start: start,
+ stop: stop
+ }
+ },
+
+ resetCell: function (index) {
+ this._lastMeasuredIndex = Math.min(this._lastMeasuredIndex, index - 1)
+ },
+
+ _binarySearch: function (high, low, offset) {
+ var middle;
+ var currentOffset;
+
+ while (low <= high) {
+ middle = low + Math.floor((high - low) / 2);
+ currentOffset = this.getSizeAndPositionOfCell(middle).offset;
+
+ if (currentOffset === offset) {
+ return middle;
+ } else if (currentOffset < offset) {
+ low = middle + 1;
+ } else if (currentOffset > offset) {
+ high = middle - 1;
+ }
+ }
+
+ if (low > 0) {
+ return low - 1;
+ }
+ },
+
+ _exponentialSearch: function (index, offset) {
+ var interval = 1;
+
+ while (index < this._cellCount && this.getSizeAndPositionOfCell(index).offset < offset) {
+ index += interval;
+ interval *= 2;
+ }
+
+ return this._binarySearch(Math.min(index, this._cellCount - 1), Math.floor(index / 2), offset);
+ },
+
+ _findNearestCell: function (offset) {
+ if (isNaN(offset)) {
+ return;
+ }
+
+ offset = Math.max(0, offset);
+
+ var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell();
+ var lastMeasuredIndex = Math.max(0, this._lastMeasuredIndex);
+
+ if (lastMeasuredCellSizeAndPosition.offset >= offset) {
+ return this._binarySearch(lastMeasuredIndex, 0, offset);
+ } else {
+ return this._exponentialSearch(lastMeasuredIndex, offset);
+ }
+ }
+};
+
+BI.ScalingCellSizeAndPositionManager = function (cellCount, cellSizeGetter, estimatedCellSize, maxScrollSize) {
+ this._cellSizeAndPositionManager = new BI.CellSizeAndPositionManager(cellCount, cellSizeGetter, estimatedCellSize);
+ this._maxScrollSize = maxScrollSize || 10000000
+};
+
+BI.ScalingCellSizeAndPositionManager.prototype = {
+ constructor: BI.ScalingCellSizeAndPositionManager,
+
+ configure: function () {
+ this._cellSizeAndPositionManager.configure.apply(this._cellSizeAndPositionManager, arguments);
+ },
+
+ getCellCount: function () {
+ return this._cellSizeAndPositionManager.getCellCount()
+ },
+
+ getEstimatedCellSize: function () {
+ return this._cellSizeAndPositionManager.getEstimatedCellSize()
+ },
+
+ getLastMeasuredIndex: function () {
+ return this._cellSizeAndPositionManager.getLastMeasuredIndex()
+ },
+
+ getOffsetAdjustment: function (containerSize, offset) {
+ var totalSize = this._cellSizeAndPositionManager.getTotalSize();
+ var safeTotalSize = this.getTotalSize();
+ var offsetPercentage = this._getOffsetPercentage(containerSize, offset, safeTotalSize);
+
+ return Math.round(offsetPercentage * (safeTotalSize - totalSize));
+ },
+
+ getSizeAndPositionOfCell: function (index) {
+ return this._cellSizeAndPositionManager.getSizeAndPositionOfCell(index);
+ },
+
+ getSizeAndPositionOfLastMeasuredCell: function () {
+ return this._cellSizeAndPositionManager.getSizeAndPositionOfLastMeasuredCell();
+ },
+
+ getTotalSize: function () {
+ return Math.min(this._maxScrollSize, this._cellSizeAndPositionManager.getTotalSize());
+ },
+
+ getUpdatedOffsetForIndex: function (align, containerSize, currentOffset, targetIndex) {
+ currentOffset = this._safeOffsetToOffset(containerSize, currentOffset);
+
+ var offset = this._cellSizeAndPositionManager.getUpdatedOffsetForIndex(align, containerSize, currentOffset, targetIndex);
+
+ return this._offsetToSafeOffset(containerSize, offset);
+ },
+
+ getVisibleCellRange: function (containerSize, offset) {
+ offset = this._safeOffsetToOffset(containerSize, offset);
+
+ return this._cellSizeAndPositionManager.getVisibleCellRange(containerSize, offset);
+ },
+
+ resetCell: function (index) {
+ this._cellSizeAndPositionManager.resetCell(index)
+ },
+
+ _getOffsetPercentage: function (containerSize, offset, totalSize) {
+ return totalSize <= containerSize
+ ? 0
+ : offset / (totalSize - containerSize)
+ },
+
+ _offsetToSafeOffset: function (containerSize, offset) {
+ var totalSize = this._cellSizeAndPositionManager.getTotalSize();
+ var safeTotalSize = this.getTotalSize();
+
+ if (totalSize === safeTotalSize) {
+ return offset;
+ } else {
+ var offsetPercentage = this._getOffsetPercentage(containerSize, offset, totalSize);
+
+ return Math.round(offsetPercentage * (safeTotalSize - containerSize));
+ }
+ },
+
+ _safeOffsetToOffset: function (containerSize, offset) {
+ var totalSize = this._cellSizeAndPositionManager.getTotalSize();
+ var safeTotalSize = this.getTotalSize();
+
+ if (totalSize === safeTotalSize) {
+ return offset;
+ } else {
+ var offsetPercentage = this._getOffsetPercentage(containerSize, offset, safeTotalSize);
+
+ return Math.round(offsetPercentage * (totalSize - containerSize));
+ }
+ }
+};/**
+ * 汉字拼音索引
+ */
+;
+!(function () {
+ var _ChineseFirstPY = "YDYQSXMWZSSXJBYMGCCZQPSSQBYCDSCDQLDYLYBSSJGYZZJJFKCCLZDHWDWZJLJPFYYNWJJTMYHZWZHFLZPPQHGSCYYYNJQYXXGJHHSDSJNKKTMOMLCRXYPSNQSECCQZGGLLYJLMYZZSECYKYYHQWJSSGGYXYZYJWWKDJHYCHMYXJTLXJYQBYXZLDWRDJRWYSRLDZJPCBZJJBR"
+ + "CFTLECZSTZFXXZHTRQHYBDLYCZSSYMMRFMYQZPWWJJYFCRWFDFZQPYDDWYXKYJAWJFFXYPSFTZYHHYZYSWCJYXSCLCXXWZZXNBGNNXBXLZSZSBSGPYSYZDHMDZBQBZCWDZZYYTZHBTSYYBZGNTNXQYWQSKBPHHLXGYBFMJEBJHHGQTJCYSXSTKZHLYCKGLYSMZXYALMELDCCXGZ"
+ + "YRJXSDLTYZCQKCNNJWHJTZZCQLJSTSTBNXBTYXCEQXGKWJYFLZQLYHYXSPSFXLMPBYSXXXYDJCZYLLLSJXFHJXPJBTFFYABYXBHZZBJYZLWLCZGGBTSSMDTJZXPTHYQTGLJSCQFZKJZJQNLZWLSLHDZBWJNCJZYZSQQYCQYRZCJJWYBRTWPYFTWEXCSKDZCTBZHYZZYYJXZCFFZ"
+ + "ZMJYXXSDZZOTTBZLQWFCKSZSXFYRLNYJMBDTHJXSQQCCSBXYYTSYFBXDZTGBCNSLCYZZPSAZYZZSCJCSHZQYDXLBPJLLMQXTYDZXSQJTZPXLCGLQTZWJBHCTSYJSFXYEJJTLBGXSXJMYJQQPFZASYJNTYDJXKJCDJSZCBARTDCLYJQMWNQNCLLLKBYBZZSYHQQLTWLCCXTXLLZN"
+ + "TYLNEWYZYXCZXXGRKRMTCNDNJTSYYSSDQDGHSDBJGHRWRQLYBGLXHLGTGXBQJDZPYJSJYJCTMRNYMGRZJCZGJMZMGXMPRYXKJNYMSGMZJYMKMFXMLDTGFBHCJHKYLPFMDXLQJJSMTQGZSJLQDLDGJYCALCMZCSDJLLNXDJFFFFJCZFMZFFPFKHKGDPSXKTACJDHHZDDCRRCFQYJ"
+ + "KQCCWJDXHWJLYLLZGCFCQDSMLZPBJJPLSBCJGGDCKKDEZSQCCKJGCGKDJTJDLZYCXKLQSCGJCLTFPCQCZGWPJDQYZJJBYJHSJDZWGFSJGZKQCCZLLPSPKJGQJHZZLJPLGJGJJTHJJYJZCZMLZLYQBGJWMLJKXZDZNJQSYZMLJLLJKYWXMKJLHSKJGBMCLYYMKXJQLBMLLKMDXXK"
+ + "WYXYSLMLPSJQQJQXYXFJTJDXMXXLLCXQBSYJBGWYMBGGBCYXPJYGPEPFGDJGBHBNSQJYZJKJKHXQFGQZKFHYGKHDKLLSDJQXPQYKYBNQSXQNSZSWHBSXWHXWBZZXDMNSJBSBKBBZKLYLXGWXDRWYQZMYWSJQLCJXXJXKJEQXSCYETLZHLYYYSDZPAQYZCMTLSHTZCFYZYXYLJSD"
+ + "CJQAGYSLCQLYYYSHMRQQKLDXZSCSSSYDYCJYSFSJBFRSSZQSBXXPXJYSDRCKGJLGDKZJZBDKTCSYQPYHSTCLDJDHMXMCGXYZHJDDTMHLTXZXYLYMOHYJCLTYFBQQXPFBDFHHTKSQHZYYWCNXXCRWHOWGYJLEGWDQCWGFJYCSNTMYTOLBYGWQWESJPWNMLRYDZSZTXYQPZGCWXHN"
+ + "GPYXSHMYQJXZTDPPBFYHZHTJYFDZWKGKZBLDNTSXHQEEGZZYLZMMZYJZGXZXKHKSTXNXXWYLYAPSTHXDWHZYMPXAGKYDXBHNHXKDPJNMYHYLPMGOCSLNZHKXXLPZZLBMLSFBHHGYGYYGGBHSCYAQTYWLXTZQCEZYDQDQMMHTKLLSZHLSJZWFYHQSWSCWLQAZYNYTLSXTHAZNKZZ"
+ + "SZZLAXXZWWCTGQQTDDYZTCCHYQZFLXPSLZYGPZSZNGLNDQTBDLXGTCTAJDKYWNSYZLJHHZZCWNYYZYWMHYCHHYXHJKZWSXHZYXLYSKQYSPSLYZWMYPPKBYGLKZHTYXAXQSYSHXASMCHKDSCRSWJPWXSGZJLWWSCHSJHSQNHCSEGNDAQTBAALZZMSSTDQJCJKTSCJAXPLGGXHHGX"
+ + "XZCXPDMMHLDGTYBYSJMXHMRCPXXJZCKZXSHMLQXXTTHXWZFKHCCZDYTCJYXQHLXDHYPJQXYLSYYDZOZJNYXQEZYSQYAYXWYPDGXDDXSPPYZNDLTWRHXYDXZZJHTCXMCZLHPYYYYMHZLLHNXMYLLLMDCPPXHMXDKYCYRDLTXJCHHZZXZLCCLYLNZSHZJZZLNNRLWHYQSNJHXYNTT"
+ + "TKYJPYCHHYEGKCTTWLGQRLGGTGTYGYHPYHYLQYQGCWYQKPYYYTTTTLHYHLLTYTTSPLKYZXGZWGPYDSSZZDQXSKCQNMJJZZBXYQMJRTFFBTKHZKBXLJJKDXJTLBWFZPPTKQTZTGPDGNTPJYFALQMKGXBDCLZFHZCLLLLADPMXDJHLCCLGYHDZFGYDDGCYYFGYDXKSSEBDHYKDKDK"
+ + "HNAXXYBPBYYHXZQGAFFQYJXDMLJCSQZLLPCHBSXGJYNDYBYQSPZWJLZKSDDTACTBXZDYZYPJZQSJNKKTKNJDJGYYPGTLFYQKASDNTCYHBLWDZHBBYDWJRYGKZYHEYYFJMSDTYFZJJHGCXPLXHLDWXXJKYTCYKSSSMTWCTTQZLPBSZDZWZXGZAGYKTYWXLHLSPBCLLOQMMZSSLCM"
+ + "BJCSZZKYDCZJGQQDSMCYTZQQLWZQZXSSFPTTFQMDDZDSHDTDWFHTDYZJYQJQKYPBDJYYXTLJHDRQXXXHAYDHRJLKLYTWHLLRLLRCXYLBWSRSZZSYMKZZHHKYHXKSMDSYDYCJPBZBSQLFCXXXNXKXWYWSDZYQOGGQMMYHCDZTTFJYYBGSTTTYBYKJDHKYXBELHTYPJQNFXFDYKZH"
+ + "QKZBYJTZBXHFDXKDASWTAWAJLDYJSFHBLDNNTNQJTJNCHXFJSRFWHZFMDRYJYJWZPDJKZYJYMPCYZNYNXFBYTFYFWYGDBNZZZDNYTXZEMMQBSQEHXFZMBMFLZZSRXYMJGSXWZJSPRYDJSJGXHJJGLJJYNZZJXHGXKYMLPYYYCXYTWQZSWHWLYRJLPXSLSXMFSWWKLCTNXNYNPSJ"
+ + "SZHDZEPTXMYYWXYYSYWLXJQZQXZDCLEEELMCPJPCLWBXSQHFWWTFFJTNQJHJQDXHWLBYZNFJLALKYYJLDXHHYCSTYYWNRJYXYWTRMDRQHWQCMFJDYZMHMYYXJWMYZQZXTLMRSPWWCHAQBXYGZYPXYYRRCLMPYMGKSJSZYSRMYJSNXTPLNBAPPYPYLXYYZKYNLDZYJZCZNNLMZHH"
+ + "ARQMPGWQTZMXXMLLHGDZXYHXKYXYCJMFFYYHJFSBSSQLXXNDYCANNMTCJCYPRRNYTYQNYYMBMSXNDLYLYSLJRLXYSXQMLLYZLZJJJKYZZCSFBZXXMSTBJGNXYZHLXNMCWSCYZYFZLXBRNNNYLBNRTGZQYSATSWRYHYJZMZDHZGZDWYBSSCSKXSYHYTXXGCQGXZZSHYXJSCRHMKK"
+ + "BXCZJYJYMKQHZJFNBHMQHYSNJNZYBKNQMCLGQHWLZNZSWXKHLJHYYBQLBFCDSXDLDSPFZPSKJYZWZXZDDXJSMMEGJSCSSMGCLXXKYYYLNYPWWWGYDKZJGGGZGGSYCKNJWNJPCXBJJTQTJWDSSPJXZXNZXUMELPXFSXTLLXCLJXJJLJZXCTPSWXLYDHLYQRWHSYCSQYYBYAYWJJJ"
+ + "QFWQCQQCJQGXALDBZZYJGKGXPLTZYFXJLTPADKYQHPMATLCPDCKBMTXYBHKLENXDLEEGQDYMSAWHZMLJTWYGXLYQZLJEEYYBQQFFNLYXRDSCTGJGXYYNKLLYQKCCTLHJLQMKKZGCYYGLLLJDZGYDHZWXPYSJBZKDZGYZZHYWYFQYTYZSZYEZZLYMHJJHTSMQWYZLKYYWZCSRKQY"
+ + "TLTDXWCTYJKLWSQZWBDCQYNCJSRSZJLKCDCDTLZZZACQQZZDDXYPLXZBQJYLZLLLQDDZQJYJYJZYXNYYYNYJXKXDAZWYRDLJYYYRJLXLLDYXJCYWYWNQCCLDDNYYYNYCKCZHXXCCLGZQJGKWPPCQQJYSBZZXYJSQPXJPZBSBDSFNSFPZXHDWZTDWPPTFLZZBZDMYYPQJRSDZSQZ"
+ + "SQXBDGCPZSWDWCSQZGMDHZXMWWFYBPDGPHTMJTHZSMMBGZMBZJCFZWFZBBZMQCFMBDMCJXLGPNJBBXGYHYYJGPTZGZMQBQTCGYXJXLWZKYDPDYMGCFTPFXYZTZXDZXTGKMTYBBCLBJASKYTSSQYYMSZXFJEWLXLLSZBQJJJAKLYLXLYCCTSXMCWFKKKBSXLLLLJYXTYLTJYYTDP"
+ + "JHNHNNKBYQNFQYYZBYYESSESSGDYHFHWTCJBSDZZTFDMXHCNJZYMQWSRYJDZJQPDQBBSTJGGFBKJBXTGQHNGWJXJGDLLTHZHHYYYYYYSXWTYYYCCBDBPYPZYCCZYJPZYWCBDLFWZCWJDXXHYHLHWZZXJTCZLCDPXUJCZZZLYXJJTXPHFXWPYWXZPTDZZBDZCYHJHMLXBQXSBYLR"
+ + "DTGJRRCTTTHYTCZWMXFYTWWZCWJWXJYWCSKYBZSCCTZQNHXNWXXKHKFHTSWOCCJYBCMPZZYKBNNZPBZHHZDLSYDDYTYFJPXYNGFXBYQXCBHXCPSXTYZDMKYSNXSXLHKMZXLYHDHKWHXXSSKQYHHCJYXGLHZXCSNHEKDTGZXQYPKDHEXTYKCNYMYYYPKQYYYKXZLTHJQTBYQHXBM"
+ + "YHSQCKWWYLLHCYYLNNEQXQWMCFBDCCMLJGGXDQKTLXKGNQCDGZJWYJJLYHHQTTTNWCHMXCXWHWSZJYDJCCDBQCDGDNYXZTHCQRXCBHZTQCBXWGQWYYBXHMBYMYQTYEXMQKYAQYRGYZSLFYKKQHYSSQYSHJGJCNXKZYCXSBXYXHYYLSTYCXQTHYSMGSCPMMGCCCCCMTZTASMGQZJ"
+ + "HKLOSQYLSWTMXSYQKDZLJQQYPLSYCZTCQQPBBQJZCLPKHQZYYXXDTDDTSJCXFFLLCHQXMJLWCJCXTSPYCXNDTJSHJWXDQQJSKXYAMYLSJHMLALYKXCYYDMNMDQMXMCZNNCYBZKKYFLMCHCMLHXRCJJHSYLNMTJZGZGYWJXSRXCWJGJQHQZDQJDCJJZKJKGDZQGJJYJYLXZXXCDQ"
+ + "HHHEYTMHLFSBDJSYYSHFYSTCZQLPBDRFRZTZYKYWHSZYQKWDQZRKMSYNBCRXQBJYFAZPZZEDZCJYWBCJWHYJBQSZYWRYSZPTDKZPFPBNZTKLQYHBBZPNPPTYZZYBQNYDCPJMMCYCQMCYFZZDCMNLFPBPLNGQJTBTTNJZPZBBZNJKLJQYLNBZQHKSJZNGGQSZZKYXSHPZSNBCGZK"
+ + "DDZQANZHJKDRTLZLSWJLJZLYWTJNDJZJHXYAYNCBGTZCSSQMNJPJYTYSWXZFKWJQTKHTZPLBHSNJZSYZBWZZZZLSYLSBJHDWWQPSLMMFBJDWAQYZTCJTBNNWZXQXCDSLQGDSDPDZHJTQQPSWLYYJZLGYXYZLCTCBJTKTYCZJTQKBSJLGMGZDMCSGPYNJZYQYYKNXRPWSZXMTNCS"
+ + "ZZYXYBYHYZAXYWQCJTLLCKJJTJHGDXDXYQYZZBYWDLWQCGLZGJGQRQZCZSSBCRPCSKYDZNXJSQGXSSJMYDNSTZTPBDLTKZWXQWQTZEXNQCZGWEZKSSBYBRTSSSLCCGBPSZQSZLCCGLLLZXHZQTHCZMQGYZQZNMCOCSZJMMZSQPJYGQLJYJPPLDXRGZYXCCSXHSHGTZNLZWZKJCX"
+ + "TCFCJXLBMQBCZZWPQDNHXLJCTHYZLGYLNLSZZPCXDSCQQHJQKSXZPBAJYEMSMJTZDXLCJYRYYNWJBNGZZTMJXLTBSLYRZPYLSSCNXPHLLHYLLQQZQLXYMRSYCXZLMMCZLTZSDWTJJLLNZGGQXPFSKYGYGHBFZPDKMWGHCXMSGDXJMCJZDYCABXJDLNBCDQYGSKYDQTXDJJYXMSZ"
+ + "QAZDZFSLQXYJSJZYLBTXXWXQQZBJZUFBBLYLWDSLJHXJYZJWTDJCZFQZQZZDZSXZZQLZCDZFJHYSPYMPQZMLPPLFFXJJNZZYLSJEYQZFPFZKSYWJJJHRDJZZXTXXGLGHYDXCSKYSWMMZCWYBAZBJKSHFHJCXMHFQHYXXYZFTSJYZFXYXPZLCHMZMBXHZZSXYFYMNCWDABAZLXKT"
+ + "CSHHXKXJJZJSTHYGXSXYYHHHJWXKZXSSBZZWHHHCWTZZZPJXSNXQQJGZYZYWLLCWXZFXXYXYHXMKYYSWSQMNLNAYCYSPMJKHWCQHYLAJJMZXHMMCNZHBHXCLXTJPLTXYJHDYYLTTXFSZHYXXSJBJYAYRSMXYPLCKDUYHLXRLNLLSTYZYYQYGYHHSCCSMZCTZQXKYQFPYYRPFFLK"
+ + "QUNTSZLLZMWWTCQQYZWTLLMLMPWMBZSSTZRBPDDTLQJJBXZCSRZQQYGWCSXFWZLXCCRSZDZMCYGGDZQSGTJSWLJMYMMZYHFBJDGYXCCPSHXNZCSBSJYJGJMPPWAFFYFNXHYZXZYLREMZGZCYZSSZDLLJCSQFNXZKPTXZGXJJGFMYYYSNBTYLBNLHPFZDCYFBMGQRRSSSZXYSGTZ"
+ + "RNYDZZCDGPJAFJFZKNZBLCZSZPSGCYCJSZLMLRSZBZZLDLSLLYSXSQZQLYXZLSKKBRXBRBZCYCXZZZEEYFGKLZLYYHGZSGZLFJHGTGWKRAAJYZKZQTSSHJJXDCYZUYJLZYRZDQQHGJZXSSZBYKJPBFRTJXLLFQWJHYLQTYMBLPZDXTZYGBDHZZRBGXHWNJTJXLKSCFSMWLSDQYS"
+ + "JTXKZSCFWJLBXFTZLLJZLLQBLSQMQQCGCZFPBPHZCZJLPYYGGDTGWDCFCZQYYYQYSSCLXZSKLZZZGFFCQNWGLHQYZJJCZLQZZYJPJZZBPDCCMHJGXDQDGDLZQMFGPSYTSDYFWWDJZJYSXYYCZCYHZWPBYKXRYLYBHKJKSFXTZJMMCKHLLTNYYMSYXYZPYJQYCSYCWMTJJKQYRHL"
+ + "LQXPSGTLYYCLJSCPXJYZFNMLRGJJTYZBXYZMSJYJHHFZQMSYXRSZCWTLRTQZSSTKXGQKGSPTGCZNJSJCQCXHMXGGZTQYDJKZDLBZSXJLHYQGGGTHQSZPYHJHHGYYGKGGCWJZZYLCZLXQSFTGZSLLLMLJSKCTBLLZZSZMMNYTPZSXQHJCJYQXYZXZQZCPSHKZZYSXCDFGMWQRLLQ"
+ + "XRFZTLYSTCTMJCXJJXHJNXTNRZTZFQYHQGLLGCXSZSJDJLJCYDSJTLNYXHSZXCGJZYQPYLFHDJSBPCCZHJJJQZJQDYBSSLLCMYTTMQTBHJQNNYGKYRQYQMZGCJKPDCGMYZHQLLSLLCLMHOLZGDYYFZSLJCQZLYLZQJESHNYLLJXGJXLYSYYYXNBZLJSSZCQQCJYLLZLTJYLLZLL"
+ + "BNYLGQCHXYYXOXCXQKYJXXXYKLXSXXYQXCYKQXQCSGYXXYQXYGYTQOHXHXPYXXXULCYEYCHZZCBWQBBWJQZSCSZSSLZYLKDESJZWMYMCYTSDSXXSCJPQQSQYLYYZYCMDJDZYWCBTJSYDJKCYDDJLBDJJSODZYSYXQQYXDHHGQQYQHDYXWGMMMAJDYBBBPPBCMUUPLJZSMTXERXJ"
+ + "MHQNUTPJDCBSSMSSSTKJTSSMMTRCPLZSZMLQDSDMJMQPNQDXCFYNBFSDQXYXHYAYKQYDDLQYYYSSZBYDSLNTFQTZQPZMCHDHCZCWFDXTMYQSPHQYYXSRGJCWTJTZZQMGWJJTJHTQJBBHWZPXXHYQFXXQYWYYHYSCDYDHHQMNMTMWCPBSZPPZZGLMZFOLLCFWHMMSJZTTDHZZYFF"
+ + "YTZZGZYSKYJXQYJZQBHMBZZLYGHGFMSHPZFZSNCLPBQSNJXZSLXXFPMTYJYGBXLLDLXPZJYZJYHHZCYWHJYLSJEXFSZZYWXKZJLUYDTMLYMQJPWXYHXSKTQJEZRPXXZHHMHWQPWQLYJJQJJZSZCPHJLCHHNXJLQWZJHBMZYXBDHHYPZLHLHLGFWLCHYYTLHJXCJMSCPXSTKPNHQ"
+ + "XSRTYXXTESYJCTLSSLSTDLLLWWYHDHRJZSFGXTSYCZYNYHTDHWJSLHTZDQDJZXXQHGYLTZPHCSQFCLNJTCLZPFSTPDYNYLGMJLLYCQHYSSHCHYLHQYQTMZYPBYWRFQYKQSYSLZDQJMPXYYSSRHZJNYWTQDFZBWWTWWRXCWHGYHXMKMYYYQMSMZHNGCEPMLQQMTCWCTMMPXJPJJH"
+ + "FXYYZSXZHTYBMSTSYJTTQQQYYLHYNPYQZLCYZHZWSMYLKFJXLWGXYPJYTYSYXYMZCKTTWLKSMZSYLMPWLZWXWQZSSAQSYXYRHSSNTSRAPXCPWCMGDXHXZDZYFJHGZTTSBJHGYZSZYSMYCLLLXBTYXHBBZJKSSDMALXHYCFYGMQYPJYCQXJLLLJGSLZGQLYCJCCZOTYXMTMTTLLW"
+ + "TGPXYMZMKLPSZZZXHKQYSXCTYJZYHXSHYXZKXLZWPSQPYHJWPJPWXQQYLXSDHMRSLZZYZWTTCYXYSZZSHBSCCSTPLWSSCJCHNLCGCHSSPHYLHFHHXJSXYLLNYLSZDHZXYLSXLWZYKCLDYAXZCMDDYSPJTQJZLNWQPSSSWCTSTSZLBLNXSMNYYMJQBQHRZWTYYDCHQLXKPZWBGQY"
+ + "BKFCMZWPZLLYYLSZYDWHXPSBCMLJBSCGBHXLQHYRLJXYSWXWXZSLDFHLSLYNJLZYFLYJYCDRJLFSYZFSLLCQYQFGJYHYXZLYLMSTDJCYHBZLLNWLXXYGYYHSMGDHXXHHLZZJZXCZZZCYQZFNGWPYLCPKPYYPMCLQKDGXZGGWQBDXZZKZFBXXLZXJTPJPTTBYTSZZDWSLCHZHSLT"
+ + "YXHQLHYXXXYYZYSWTXZKHLXZXZPYHGCHKCFSYHUTJRLXFJXPTZTWHPLYXFCRHXSHXKYXXYHZQDXQWULHYHMJTBFLKHTXCWHJFWJCFPQRYQXCYYYQYGRPYWSGSUNGWCHKZDXYFLXXHJJBYZWTSXXNCYJJYMSWZJQRMHXZWFQSYLZJZGBHYNSLBGTTCSYBYXXWXYHXYYXNSQYXMQY"
+ + "WRGYQLXBBZLJSYLPSYTJZYHYZAWLRORJMKSCZJXXXYXCHDYXRYXXJDTSQFXLYLTSFFYXLMTYJMJUYYYXLTZCSXQZQHZXLYYXZHDNBRXXXJCTYHLBRLMBRLLAXKYLLLJLYXXLYCRYLCJTGJCMTLZLLCYZZPZPCYAWHJJFYBDYYZSMPCKZDQYQPBPCJPDCYZMDPBCYYDYCNNPLMTM"
+ + "LRMFMMGWYZBSJGYGSMZQQQZTXMKQWGXLLPJGZBQCDJJJFPKJKCXBLJMSWMDTQJXLDLPPBXCWRCQFBFQJCZAHZGMYKPHYYHZYKNDKZMBPJYXPXYHLFPNYYGXJDBKXNXHJMZJXSTRSTLDXSKZYSYBZXJLXYSLBZYSLHXJPFXPQNBYLLJQKYGZMCYZZYMCCSLCLHZFWFWYXZMWSXTY"
+ + "NXJHPYYMCYSPMHYSMYDYSHQYZCHMJJMZCAAGCFJBBHPLYZYLXXSDJGXDHKXXTXXNBHRMLYJSLTXMRHNLXQJXYZLLYSWQGDLBJHDCGJYQYCMHWFMJYBMBYJYJWYMDPWHXQLDYGPDFXXBCGJSPCKRSSYZJMSLBZZJFLJJJLGXZGYXYXLSZQYXBEXYXHGCXBPLDYHWETTWWCJMBTXC"
+ + "HXYQXLLXFLYXLLJLSSFWDPZSMYJCLMWYTCZPCHQEKCQBWLCQYDPLQPPQZQFJQDJHYMMCXTXDRMJWRHXCJZYLQXDYYNHYYHRSLSRSYWWZJYMTLTLLGTQCJZYABTCKZCJYCCQLJZQXALMZYHYWLWDXZXQDLLQSHGPJFJLJHJABCQZDJGTKHSSTCYJLPSWZLXZXRWGLDLZRLZXTGSL"
+ + "LLLZLYXXWGDZYGBDPHZPBRLWSXQBPFDWOFMWHLYPCBJCCLDMBZPBZZLCYQXLDOMZBLZWPDWYYGDSTTHCSQSCCRSSSYSLFYBFNTYJSZDFNDPDHDZZMBBLSLCMYFFGTJJQWFTMTPJWFNLBZCMMJTGBDZLQLPYFHYYMJYLSDCHDZJWJCCTLJCLDTLJJCPDDSQDSSZYBNDBJLGGJZXS"
+ + "XNLYCYBJXQYCBYLZCFZPPGKCXZDZFZTJJFJSJXZBNZYJQTTYJYHTYCZHYMDJXTTMPXSPLZCDWSLSHXYPZGTFMLCJTYCBPMGDKWYCYZCDSZZYHFLYCTYGWHKJYYLSJCXGYWJCBLLCSNDDBTZBSCLYZCZZSSQDLLMQYYHFSLQLLXFTYHABXGWNYWYYPLLSDLDLLBJCYXJZMLHLJDX"
+ + "YYQYTDLLLBUGBFDFBBQJZZMDPJHGCLGMJJPGAEHHBWCQXAXHHHZCHXYPHJAXHLPHJPGPZJQCQZGJJZZUZDMQYYBZZPHYHYBWHAZYJHYKFGDPFQSDLZMLJXKXGALXZDAGLMDGXMWZQYXXDXXPFDMMSSYMPFMDMMKXKSYZYSHDZKXSYSMMZZZMSYDNZZCZXFPLSTMZDNMXCKJMZTY"
+ + "YMZMZZMSXHHDCZJEMXXKLJSTLWLSQLYJZLLZJSSDPPMHNLZJCZYHMXXHGZCJMDHXTKGRMXFWMCGMWKDTKSXQMMMFZZYDKMSCLCMPCGMHSPXQPZDSSLCXKYXTWLWJYAHZJGZQMCSNXYYMMPMLKJXMHLMLQMXCTKZMJQYSZJSYSZHSYJZJCDAJZYBSDQJZGWZQQXFKDMSDJLFWEHK"
+ + "ZQKJPEYPZYSZCDWYJFFMZZYLTTDZZEFMZLBNPPLPLPEPSZALLTYLKCKQZKGENQLWAGYXYDPXLHSXQQWQCQXQCLHYXXMLYCCWLYMQYSKGCHLCJNSZKPYZKCQZQLJPDMDZHLASXLBYDWQLWDNBQCRYDDZTJYBKBWSZDXDTNPJDTCTQDFXQQMGNXECLTTBKPWSLCTYQLPWYZZKLPYG"
+ + "ZCQQPLLKCCYLPQMZCZQCLJSLQZDJXLDDHPZQDLJJXZQDXYZQKZLJCYQDYJPPYPQYKJYRMPCBYMCXKLLZLLFQPYLLLMBSGLCYSSLRSYSQTMXYXZQZFDZUYSYZTFFMZZSMZQHZSSCCMLYXWTPZGXZJGZGSJSGKDDHTQGGZLLBJDZLCBCHYXYZHZFYWXYZYMSDBZZYJGTSMTFXQYXQ"
+ + "STDGSLNXDLRYZZLRYYLXQHTXSRTZNGZXBNQQZFMYKMZJBZYMKBPNLYZPBLMCNQYZZZSJZHJCTZKHYZZJRDYZHNPXGLFZTLKGJTCTSSYLLGZRZBBQZZKLPKLCZYSSUYXBJFPNJZZXCDWXZYJXZZDJJKGGRSRJKMSMZJLSJYWQSKYHQJSXPJZZZLSNSHRNYPZTWCHKLPSRZLZXYJQ"
+ + "XQKYSJYCZTLQZYBBYBWZPQDWWYZCYTJCJXCKCWDKKZXSGKDZXWWYYJQYYTCYTDLLXWKCZKKLCCLZCQQDZLQLCSFQCHQHSFSMQZZLNBJJZBSJHTSZDYSJQJPDLZCDCWJKJZZLPYCGMZWDJJBSJQZSYZYHHXJPBJYDSSXDZNCGLQMBTSFSBPDZDLZNFGFJGFSMPXJQLMBLGQCYYXB"
+ + "QKDJJQYRFKZTJDHCZKLBSDZCFJTPLLJGXHYXZCSSZZXSTJYGKGCKGYOQXJPLZPBPGTGYJZGHZQZZLBJLSQFZGKQQJZGYCZBZQTLDXRJXBSXXPZXHYZYCLWDXJJHXMFDZPFZHQHQMQGKSLYHTYCGFRZGNQXCLPDLBZCSCZQLLJBLHBZCYPZZPPDYMZZSGYHCKCPZJGSLJLNSCDSL"
+ + "DLXBMSTLDDFJMKDJDHZLZXLSZQPQPGJLLYBDSZGQLBZLSLKYYHZTTNTJYQTZZPSZQZTLLJTYYLLQLLQYZQLBDZLSLYYZYMDFSZSNHLXZNCZQZPBWSKRFBSYZMTHBLGJPMCZZLSTLXSHTCSYZLZBLFEQHLXFLCJLYLJQCBZLZJHHSSTBRMHXZHJZCLXFNBGXGTQJCZTMSFZKJMSS"
+ + "NXLJKBHSJXNTNLZDNTLMSJXGZJYJCZXYJYJWRWWQNZTNFJSZPZSHZJFYRDJSFSZJZBJFZQZZHZLXFYSBZQLZSGYFTZDCSZXZJBQMSZKJRHYJZCKMJKHCHGTXKXQGLXPXFXTRTYLXJXHDTSJXHJZJXZWZLCQSBTXWXGXTXXHXFTSDKFJHZYJFJXRZSDLLLTQSQQZQWZXSYQTWGWB"
+ + "ZCGZLLYZBCLMQQTZHZXZXLJFRMYZFLXYSQXXJKXRMQDZDMMYYBSQBHGZMWFWXGMXLZPYYTGZYCCDXYZXYWGSYJYZNBHPZJSQSYXSXRTFYZGRHZTXSZZTHCBFCLSYXZLZQMZLMPLMXZJXSFLBYZMYQHXJSXRXSQZZZSSLYFRCZJRCRXHHZXQYDYHXSJJHZCXZBTYNSYSXJBQLPXZ"
+ + "QPYMLXZKYXLXCJLCYSXXZZLXDLLLJJYHZXGYJWKJRWYHCPSGNRZLFZWFZZNSXGXFLZSXZZZBFCSYJDBRJKRDHHGXJLJJTGXJXXSTJTJXLYXQFCSGSWMSBCTLQZZWLZZKXJMLTMJYHSDDBXGZHDLBMYJFRZFSGCLYJBPMLYSMSXLSZJQQHJZFXGFQFQBPXZGYYQXGZTCQWYLTLGW"
+ + "SGWHRLFSFGZJMGMGBGTJFSYZZGZYZAFLSSPMLPFLCWBJZCLJJMZLPJJLYMQDMYYYFBGYGYZMLYZDXQYXRQQQHSYYYQXYLJTYXFSFSLLGNQCYHYCWFHCCCFXPYLYPLLZYXXXXXKQHHXSHJZCFZSCZJXCPZWHHHHHAPYLQALPQAFYHXDYLUKMZQGGGDDESRNNZLTZGCHYPPYSQJJH"
+ + "CLLJTOLNJPZLJLHYMHEYDYDSQYCDDHGZUNDZCLZYZLLZNTNYZGSLHSLPJJBDGWXPCDUTJCKLKCLWKLLCASSTKZZDNQNTTLYYZSSYSSZZRYLJQKCQDHHCRXRZYDGRGCWCGZQFFFPPJFZYNAKRGYWYQPQXXFKJTSZZXSWZDDFBBXTBGTZKZNPZZPZXZPJSZBMQHKCYXYLDKLJNYPK"
+ + "YGHGDZJXXEAHPNZKZTZCMXCXMMJXNKSZQNMNLWBWWXJKYHCPSTMCSQTZJYXTPCTPDTNNPGLLLZSJLSPBLPLQHDTNJNLYYRSZFFJFQWDPHZDWMRZCCLODAXNSSNYZRESTYJWJYJDBCFXNMWTTBYLWSTSZGYBLJPXGLBOCLHPCBJLTMXZLJYLZXCLTPNCLCKXTPZJSWCYXSFYSZDK"
+ + "NTLBYJCYJLLSTGQCBXRYZXBXKLYLHZLQZLNZCXWJZLJZJNCJHXMNZZGJZZXTZJXYCYYCXXJYYXJJXSSSJSTSSTTPPGQTCSXWZDCSYFPTFBFHFBBLZJCLZZDBXGCXLQPXKFZFLSYLTUWBMQJHSZBMDDBCYSCCLDXYCDDQLYJJWMQLLCSGLJJSYFPYYCCYLTJANTJJPWYCMMGQYYS"
+ + "XDXQMZHSZXPFTWWZQSWQRFKJLZJQQYFBRXJHHFWJJZYQAZMYFRHCYYBYQWLPEXCCZSTYRLTTDMQLYKMBBGMYYJPRKZNPBSXYXBHYZDJDNGHPMFSGMWFZMFQMMBCMZZCJJLCNUXYQLMLRYGQZCYXZLWJGCJCGGMCJNFYZZJHYCPRRCMTZQZXHFQGTJXCCJEAQCRJYHPLQLSZDJRB"
+ + "CQHQDYRHYLYXJSYMHZYDWLDFRYHBPYDTSSCNWBXGLPZMLZZTQSSCPJMXXYCSJYTYCGHYCJWYRXXLFEMWJNMKLLSWTXHYYYNCMMCWJDQDJZGLLJWJRKHPZGGFLCCSCZMCBLTBHBQJXQDSPDJZZGKGLFQYWBZYZJLTSTDHQHCTCBCHFLQMPWDSHYYTQWCNZZJTLBYMBPDYYYXSQKX"
+ + "WYYFLXXNCWCXYPMAELYKKJMZZZBRXYYQJFLJPFHHHYTZZXSGQQMHSPGDZQWBWPJHZJDYSCQWZKTXXSQLZYYMYSDZGRXCKKUJLWPYSYSCSYZLRMLQSYLJXBCXTLWDQZPCYCYKPPPNSXFYZJJRCEMHSZMSXLXGLRWGCSTLRSXBZGBZGZTCPLUJLSLYLYMTXMTZPALZXPXJTJWTCYY"
+ + "ZLBLXBZLQMYLXPGHDSLSSDMXMBDZZSXWHAMLCZCPJMCNHJYSNSYGCHSKQMZZQDLLKABLWJXSFMOCDXJRRLYQZKJMYBYQLYHETFJZFRFKSRYXFJTWDSXXSYSQJYSLYXWJHSNLXYYXHBHAWHHJZXWMYLJCSSLKYDZTXBZSYFDXGXZJKHSXXYBSSXDPYNZWRPTQZCZENYGCXQFJYKJ"
+ + "BZMLJCMQQXUOXSLYXXLYLLJDZBTYMHPFSTTQQWLHOKYBLZZALZXQLHZWRRQHLSTMYPYXJJXMQSJFNBXYXYJXXYQYLTHYLQYFMLKLJTMLLHSZWKZHLJMLHLJKLJSTLQXYLMBHHLNLZXQJHXCFXXLHYHJJGBYZZKBXSCQDJQDSUJZYYHZHHMGSXCSYMXFEBCQWWRBPYYJQTYZCYQY"
+ + "QQZYHMWFFHGZFRJFCDPXNTQYZPDYKHJLFRZXPPXZDBBGZQSTLGDGYLCQMLCHHMFYWLZYXKJLYPQHSYWMQQGQZMLZJNSQXJQSYJYCBEHSXFSZPXZWFLLBCYYJDYTDTHWZSFJMQQYJLMQXXLLDTTKHHYBFPWTYYSQQWNQWLGWDEBZWCMYGCULKJXTMXMYJSXHYBRWFYMWFRXYQMXY"
+ + "SZTZZTFYKMLDHQDXWYYNLCRYJBLPSXCXYWLSPRRJWXHQYPHTYDNXHHMMYWYTZCSQMTSSCCDALWZTCPQPYJLLQZYJSWXMZZMMYLMXCLMXCZMXMZSQTZPPQQBLPGXQZHFLJJHYTJSRXWZXSCCDLXTYJDCQJXSLQYCLZXLZZXMXQRJMHRHZJBHMFLJLMLCLQNLDXZLLLPYPSYJYSXC"
+ + "QQDCMQJZZXHNPNXZMEKMXHYKYQLXSXTXJYYHWDCWDZHQYYBGYBCYSCFGPSJNZDYZZJZXRZRQJJYMCANYRJTLDPPYZBSTJKXXZYPFDWFGZZRPYMTNGXZQBYXNBUFNQKRJQZMJEGRZGYCLKXZDSKKNSXKCLJSPJYYZLQQJYBZSSQLLLKJXTBKTYLCCDDBLSPPFYLGYDTZJYQGGKQT"
+ + "TFZXBDKTYYHYBBFYTYYBCLPDYTGDHRYRNJSPTCSNYJQHKLLLZSLYDXXWBCJQSPXBPJZJCJDZFFXXBRMLAZHCSNDLBJDSZBLPRZTSWSBXBCLLXXLZDJZSJPYLYXXYFTFFFBHJJXGBYXJPMMMPSSJZJMTLYZJXSWXTYLEDQPJMYGQZJGDJLQJWJQLLSJGJGYGMSCLJJXDTYGJQJQJ"
+ + "CJZCJGDZZSXQGSJGGCXHQXSNQLZZBXHSGZXCXYLJXYXYYDFQQJHJFXDHCTXJYRXYSQTJXYEFYYSSYYJXNCYZXFXMSYSZXYYSCHSHXZZZGZZZGFJDLTYLNPZGYJYZYYQZPBXQBDZTZCZYXXYHHSQXSHDHGQHJHGYWSZTMZMLHYXGEBTYLZKQWYTJZRCLEKYSTDBCYKQQSAYXCJXW"
+ + "WGSBHJYZYDHCSJKQCXSWXFLTYNYZPZCCZJQTZWJQDZZZQZLJJXLSBHPYXXPSXSHHEZTXFPTLQYZZXHYTXNCFZYYHXGNXMYWXTZSJPTHHGYMXMXQZXTSBCZYJYXXTYYZYPCQLMMSZMJZZLLZXGXZAAJZYXJMZXWDXZSXZDZXLEYJJZQBHZWZZZQTZPSXZTDSXJJJZNYAZPHXYYSR"
+ + "NQDTHZHYYKYJHDZXZLSWCLYBZYECWCYCRYLCXNHZYDZYDYJDFRJJHTRSQTXYXJRJHOJYNXELXSFSFJZGHPZSXZSZDZCQZBYYKLSGSJHCZSHDGQGXYZGXCHXZJWYQWGYHKSSEQZZNDZFKWYSSTCLZSTSYMCDHJXXYWEYXCZAYDMPXMDSXYBSQMJMZJMTZQLPJYQZCGQHXJHHLXXH"
+ + "LHDLDJQCLDWBSXFZZYYSCHTYTYYBHECXHYKGJPXHHYZJFXHWHBDZFYZBCAPNPGNYDMSXHMMMMAMYNBYJTMPXYYMCTHJBZYFCGTYHWPHFTWZZEZSBZEGPFMTSKFTYCMHFLLHGPZJXZJGZJYXZSBBQSCZZLZCCSTPGXMJSFTCCZJZDJXCYBZLFCJSYZFGSZLYBCWZZBYZDZYPSWYJ"
+ + "ZXZBDSYUXLZZBZFYGCZXBZHZFTPBGZGEJBSTGKDMFHYZZJHZLLZZGJQZLSFDJSSCBZGPDLFZFZSZYZYZSYGCXSNXXCHCZXTZZLJFZGQSQYXZJQDCCZTQCDXZJYQJQCHXZTDLGSCXZSYQJQTZWLQDQZTQCHQQJZYEZZZPBWKDJFCJPZTYPQYQTTYNLMBDKTJZPQZQZZFPZSBNJLG"
+ + "YJDXJDZZKZGQKXDLPZJTCJDQBXDJQJSTCKNXBXZMSLYJCQMTJQWWCJQNJNLLLHJCWQTBZQYDZCZPZZDZYDDCYZZZCCJTTJFZDPRRTZTJDCQTQZDTJNPLZBCLLCTZSXKJZQZPZLBZRBTJDCXFCZDBCCJJLTQQPLDCGZDBBZJCQDCJWYNLLZYZCCDWLLXWZLXRXNTQQCZXKQLSGDF"
+ + "QTDDGLRLAJJTKUYMKQLLTZYTDYYCZGJWYXDXFRSKSTQTENQMRKQZHHQKDLDAZFKYPBGGPZREBZZYKZZSPEGJXGYKQZZZSLYSYYYZWFQZYLZZLZHWCHKYPQGNPGBLPLRRJYXCCSYYHSFZFYBZYYTGZXYLXCZWXXZJZBLFFLGSKHYJZEYJHLPLLLLCZGXDRZELRHGKLZZYHZLYQSZ"
+ + "ZJZQLJZFLNBHGWLCZCFJYSPYXZLZLXGCCPZBLLCYBBBBUBBCBPCRNNZCZYRBFSRLDCGQYYQXYGMQZWTZYTYJXYFWTEHZZJYWLCCNTZYJJZDEDPZDZTSYQJHDYMBJNYJZLXTSSTPHNDJXXBYXQTZQDDTJTDYYTGWSCSZQFLSHLGLBCZPHDLYZJYCKWTYTYLBNYTSDSYCCTYSZYYE"
+ + "BHEXHQDTWNYGYCLXTSZYSTQMYGZAZCCSZZDSLZCLZRQXYYELJSBYMXSXZTEMBBLLYYLLYTDQYSHYMRQWKFKBFXNXSBYCHXBWJYHTQBPBSBWDZYLKGZSKYHXQZJXHXJXGNLJKZLYYCDXLFYFGHLJGJYBXQLYBXQPQGZTZPLNCYPXDJYQYDYMRBESJYYHKXXSTMXRCZZYWXYQYBMC"
+ + "LLYZHQYZWQXDBXBZWZMSLPDMYSKFMZKLZCYQYCZLQXFZZYDQZPZYGYJYZMZXDZFYFYTTQTZHGSPCZMLCCYTZXJCYTJMKSLPZHYSNZLLYTPZCTZZCKTXDHXXTQCYFKSMQCCYYAZHTJPCYLZLYJBJXTPNYLJYYNRXSYLMMNXJSMYBCSYSYLZYLXJJQYLDZLPQBFZZBLFNDXQKCZFY"
+ + "WHGQMRDSXYCYTXNQQJZYYPFZXDYZFPRXEJDGYQBXRCNFYYQPGHYJDYZXGRHTKYLNWDZNTSMPKLBTHBPYSZBZTJZSZZJTYYXZPHSSZZBZCZPTQFZMYFLYPYBBJQXZMXXDJMTSYSKKBJZXHJCKLPSMKYJZCXTMLJYXRZZQSLXXQPYZXMKYXXXJCLJPRMYYGADYSKQLSNDHYZKQXZY"
+ + "ZTCGHZTLMLWZYBWSYCTBHJHJFCWZTXWYTKZLXQSHLYJZJXTMPLPYCGLTBZZTLZJCYJGDTCLKLPLLQPJMZPAPXYZLKKTKDZCZZBNZDYDYQZJYJGMCTXLTGXSZLMLHBGLKFWNWZHDXUHLFMKYSLGXDTWWFRJEJZTZHYDXYKSHWFZCQSHKTMQQHTZHYMJDJSKHXZJZBZZXYMPAGQMS"
+ + "TPXLSKLZYNWRTSQLSZBPSPSGZWYHTLKSSSWHZZLYYTNXJGMJSZSUFWNLSOZTXGXLSAMMLBWLDSZYLAKQCQCTMYCFJBSLXCLZZCLXXKSBZQCLHJPSQPLSXXCKSLNHPSFQQYTXYJZLQLDXZQJZDYYDJNZPTUZDSKJFSLJHYLZSQZLBTXYDGTQFDBYAZXDZHZJNHHQBYKNXJJQCZML"
+ + "LJZKSPLDYCLBBLXKLELXJLBQYCXJXGCNLCQPLZLZYJTZLJGYZDZPLTQCSXFDMNYCXGBTJDCZNBGBQYQJWGKFHTNPYQZQGBKPBBYZMTJDYTBLSQMPSXTBNPDXKLEMYYCJYNZCTLDYKZZXDDXHQSHDGMZSJYCCTAYRZLPYLTLKXSLZCGGEXCLFXLKJRTLQJAQZNCMBYDKKCXGLCZJ"
+ + "ZXJHPTDJJMZQYKQSECQZDSHHADMLZFMMZBGNTJNNLGBYJBRBTMLBYJDZXLCJLPLDLPCQDHLXZLYCBLCXZZJADJLNZMMSSSMYBHBSQKBHRSXXJMXSDZNZPXLGBRHWGGFCXGMSKLLTSJYYCQLTSKYWYYHYWXBXQYWPYWYKQLSQPTNTKHQCWDQKTWPXXHCPTHTWUMSSYHBWCRWXHJM"
+ + "KMZNGWTMLKFGHKJYLSYYCXWHYECLQHKQHTTQKHFZLDXQWYZYYDESBPKYRZPJFYYZJCEQDZZDLATZBBFJLLCXDLMJSSXEGYGSJQXCWBXSSZPDYZCXDNYXPPZYDLYJCZPLTXLSXYZYRXCYYYDYLWWNZSAHJSYQYHGYWWAXTJZDAXYSRLTDPSSYYFNEJDXYZHLXLLLZQZSJNYQYQQX"
+ + "YJGHZGZCYJCHZLYCDSHWSHJZYJXCLLNXZJJYYXNFXMWFPYLCYLLABWDDHWDXJMCXZTZPMLQZHSFHZYNZTLLDYWLSLXHYMMYLMBWWKYXYADTXYLLDJPYBPWUXJMWMLLSAFDLLYFLBHHHBQQLTZJCQJLDJTFFKMMMBYTHYGDCQRDDWRQJXNBYSNWZDBYYTBJHPYBYTTJXAAHGQDQT"
+ + "MYSTQXKBTZPKJLZRBEQQSSMJJBDJOTGTBXPGBKTLHQXJJJCTHXQDWJLWRFWQGWSHCKRYSWGFTGYGBXSDWDWRFHWYTJJXXXJYZYSLPYYYPAYXHYDQKXSHXYXGSKQHYWFDDDPPLCJLQQEEWXKSYYKDYPLTJTHKJLTCYYHHJTTPLTZZCDLTHQKZXQYSTEEYWYYZYXXYYSTTJKLLPZM"
+ + "CYHQGXYHSRMBXPLLNQYDQHXSXXWGDQBSHYLLPJJJTHYJKYPPTHYYKTYEZYENMDSHLCRPQFDGFXZPSFTLJXXJBSWYYSKSFLXLPPLBBBLBSFXFYZBSJSSYLPBBFFFFSSCJDSTZSXZRYYSYFFSYZYZBJTBCTSBSDHRTJJBYTCXYJEYLXCBNEBJDSYXYKGSJZBXBYTFZWGENYHHTHZH"
+ + "HXFWGCSTBGXKLSXYWMTMBYXJSTZSCDYQRCYTWXZFHMYMCXLZNSDJTTTXRYCFYJSBSDYERXJLJXBBDEYNJGHXGCKGSCYMBLXJMSZNSKGXFBNBPTHFJAAFXYXFPXMYPQDTZCXZZPXRSYWZDLYBBKTYQPQJPZYPZJZNJPZJLZZFYSBTTSLMPTZRTDXQSJEHBZYLZDHLJSQMLHTXTJE"
+ + "CXSLZZSPKTLZKQQYFSYGYWPCPQFHQHYTQXZKRSGTTSQCZLPTXCDYYZXSQZSLXLZMYCPCQBZYXHBSXLZDLTCDXTYLZJYYZPZYZLTXJSJXHLPMYTXCQRBLZSSFJZZTNJYTXMYJHLHPPLCYXQJQQKZZSCPZKSWALQSBLCCZJSXGWWWYGYKTJBBZTDKHXHKGTGPBKQYSLPXPJCKBMLL"
+ + "XDZSTBKLGGQKQLSBKKTFXRMDKBFTPZFRTBBRFERQGXYJPZSSTLBZTPSZQZSJDHLJQLZBPMSMMSXLQQNHKNBLRDDNXXDHDDJCYYGYLXGZLXSYGMQQGKHBPMXYXLYTQWLWGCPBMQXCYZYDRJBHTDJYHQSHTMJSBYPLWHLZFFNYPMHXXHPLTBQPFBJWQDBYGPNZTPFZJGSDDTQSHZE"
+ + "AWZZYLLTYYBWJKXXGHLFKXDJTMSZSQYNZGGSWQSPHTLSSKMCLZXYSZQZXNCJDQGZDLFNYKLJCJLLZLMZZNHYDSSHTHZZLZZBBHQZWWYCRZHLYQQJBEYFXXXWHSRXWQHWPSLMSSKZTTYGYQQWRSLALHMJTQJSMXQBJJZJXZYZKXBYQXBJXSHZTSFJLXMXZXFGHKZSZGGYLCLSARJ"
+ + "YHSLLLMZXELGLXYDJYTLFBHBPNLYZFBBHPTGJKWETZHKJJXZXXGLLJLSTGSHJJYQLQZFKCGNNDJSSZFDBCTWWSEQFHQJBSAQTGYPQLBXBMMYWXGSLZHGLZGQYFLZBYFZJFRYSFMBYZHQGFWZSYFYJJPHZBYYZFFWODGRLMFTWLBZGYCQXCDJYGZYYYYTYTYDWEGAZYHXJLZYYHL"
+ + "RMGRXXZCLHNELJJTJTPWJYBJJBXJJTJTEEKHWSLJPLPSFYZPQQBDLQJJTYYQLYZKDKSQJYYQZLDQTGJQYZJSUCMRYQTHTEJMFCTYHYPKMHYZWJDQFHYYXWSHCTXRLJHQXHCCYYYJLTKTTYTMXGTCJTZAYYOCZLYLBSZYWJYTSJYHBYSHFJLYGJXXTMZYYLTXXYPZLXYJZYZYYPN"
+ + "HMYMDYYLBLHLSYYQQLLNJJYMSOYQBZGDLYXYLCQYXTSZEGXHZGLHWBLJHEYXTWQMAKBPQCGYSHHEGQCMWYYWLJYJHYYZLLJJYLHZYHMGSLJLJXCJJYCLYCJPCPZJZJMMYLCQLNQLJQJSXYJMLSZLJQLYCMMHCFMMFPQQMFYLQMCFFQMMMMHMZNFHHJGTTHHKHSLNCHHYQDXTMMQ"
+ + "DCYZYXYQMYQYLTDCYYYZAZZCYMZYDLZFFFMMYCQZWZZMABTBYZTDMNZZGGDFTYPCGQYTTSSFFWFDTZQSSYSTWXJHXYTSXXYLBYQHWWKXHZXWZNNZZJZJJQJCCCHYYXBZXZCYZTLLCQXYNJYCYYCYNZZQYYYEWYCZDCJYCCHYJLBTZYYCQWMPWPYMLGKDLDLGKQQBGYCHJXY";
+
+ //此处收录了375个多音字,数据来自于http://www.51window.net/page/pinyin
+ var oMultiDiff = {
+ "19969": "DZ",
+ "19975": "WM",
+ "19988": "QJ",
+ "20048": "YL",
+ "20056": "SC",
+ "20060": "NM",
+ "20094": "QG",
+ "20127": "QJ",
+ "20167": "QC",
+ "20193": "YG",
+ "20250": "KH",
+ "20256": "ZC",
+ "20282": "SC",
+ "20285": "QJG",
+ "20291": "TD",
+ "20314": "YD",
+ "20340": "NE",
+ "20375": "TD",
+ "20389": "YJ",
+ "20391": "CZ",
+ "20415": "PB",
+ "20446": "YS",
+ "20447": "SQ",
+ "20504": "TC",
+ "20608": "KG",
+ "20854": "QJ",
+ "20857": "ZC",
+ "20911": "PF",
+ "20504": "TC",
+ "20608": "KG",
+ "20854": "QJ",
+ "20857": "ZC",
+ "20911": "PF",
+ "20985": "AW",
+ "21032": "PB",
+ "21048": "XQ",
+ "21049": "SC",
+ "21089": "YS",
+ "21119": "JC",
+ "21242": "SB",
+ "21273": "SC",
+ "21305": "YP",
+ "21306": "QO",
+ "21330": "ZC",
+ "21333": "SDC",
+ "21345": "QK",
+ "21378": "CA",
+ "21397": "SC",
+ "21414": "XS",
+ "21442": "SC",
+ "21477": "JG",
+ "21480": "TD",
+ "21484": "ZS",
+ "21494": "YX",
+ "21505": "YX",
+ "21512": "HG",
+ "21523": "XH",
+ "21537": "PB",
+ "21542": "PF",
+ "21549": "KH",
+ "21571": "E",
+ "21574": "DA",
+ "21588": "TD",
+ "21589": "O",
+ "21618": "ZC",
+ "21621": "KHA",
+ "21632": "ZJ",
+ "21654": "KG",
+ "21679": "LKG",
+ "21683": "KH",
+ "21710": "A",
+ "21719": "YH",
+ "21734": "WOE",
+ "21769": "A",
+ "21780": "WN",
+ "21804": "XH",
+ "21834": "A",
+ "21899": "ZD",
+ "21903": "RN",
+ "21908": "WO",
+ "21939": "ZC",
+ "21956": "SA",
+ "21964": "YA",
+ "21970": "TD",
+ "22003": "A",
+ "22031": "JG",
+ "22040": "XS",
+ "22060": "ZC",
+ "22066": "ZC",
+ "22079": "MH",
+ "22129": "XJ",
+ "22179": "XA",
+ "22237": "NJ",
+ "22244": "TD",
+ "22280": "JQ",
+ "22300": "YH",
+ "22313": "XW",
+ "22331": "YQ",
+ "22343": "YJ",
+ "22351": "PH",
+ "22395": "DC",
+ "22412": "TD",
+ "22484": "PB",
+ "22500": "PB",
+ "22534": "ZD",
+ "22549": "DH",
+ "22561": "PB",
+ "22612": "TD",
+ "22771": "KQ",
+ "22831": "HB",
+ "22841": "JG",
+ "22855": "QJ",
+ "22865": "XQ",
+ "23013": "ML",
+ "23081": "WM",
+ "23487": "SX",
+ "23558": "QJ",
+ "23561": "YW",
+ "23586": "YW",
+ "23614": "YW",
+ "23615": "SN",
+ "23631": "PB",
+ "23646": "ZS",
+ "23663": "ZT",
+ "23673": "YG",
+ "23762": "TD",
+ "23769": "ZS",
+ "23780": "QJ",
+ "23884": "QK",
+ "24055": "XH",
+ "24113": "DC",
+ "24162": "ZC",
+ "24191": "GA",
+ "24273": "QJ",
+ "24324": "NL",
+ "24377": "TD",
+ "24378": "QJ",
+ "24439": "PF",
+ "24554": "ZS",
+ "24683": "TD",
+ "24694": "WE",
+ "24733": "LK",
+ "24925": "TN",
+ "25094": "ZG",
+ "25100": "XQ",
+ "25103": "XH",
+ "25153": "PB",
+ "25170": "PB",
+ "25179": "KG",
+ "25203": "PB",
+ "25240": "ZS",
+ "25282": "FB",
+ "25303": "NA",
+ "25324": "KG",
+ "25341": "ZY",
+ "25373": "WZ",
+ "25375": "XJ",
+ "25384": "A",
+ "25457": "A",
+ "25528": "SD",
+ "25530": "SC",
+ "25552": "TD",
+ "25774": "ZC",
+ "25874": "ZC",
+ "26044": "YW",
+ "26080": "WM",
+ "26292": "PB",
+ "26333": "PB",
+ "26355": "ZY",
+ "26366": "CZ",
+ "26397": "ZC",
+ "26399": "QJ",
+ "26415": "ZS",
+ "26451": "SB",
+ "26526": "ZC",
+ "26552": "JG",
+ "26561": "TD",
+ "26588": "JG",
+ "26597": "CZ",
+ "26629": "ZS",
+ "26638": "YL",
+ "26646": "XQ",
+ "26653": "KG",
+ "26657": "XJ",
+ "26727": "HG",
+ "26894": "ZC",
+ "26937": "ZS",
+ "26946": "ZC",
+ "26999": "KJ",
+ "27099": "KJ",
+ "27449": "YQ",
+ "27481": "XS",
+ "27542": "ZS",
+ "27663": "ZS",
+ "27748": "TS",
+ "27784": "SC",
+ "27788": "ZD",
+ "27795": "TD",
+ "27812": "O",
+ "27850": "PB",
+ "27852": "MB",
+ "27895": "SL",
+ "27898": "PL",
+ "27973": "QJ",
+ "27981": "KH",
+ "27986": "HX",
+ "27994": "XJ",
+ "28044": "YC",
+ "28065": "WG",
+ "28177": "SM",
+ "28267": "QJ",
+ "28291": "KH",
+ "28337": "ZQ",
+ "28463": "TL",
+ "28548": "DC",
+ "28601": "TD",
+ "28689": "PB",
+ "28805": "JG",
+ "28820": "QG",
+ "28846": "PB",
+ "28952": "TD",
+ "28975": "ZC",
+ "29100": "A",
+ "29325": "QJ",
+ "29575": "SL",
+ "29602": "FB",
+ "30010": "TD",
+ "30044": "CX",
+ "30058": "PF",
+ "30091": "YSP",
+ "30111": "YN",
+ "30229": "XJ",
+ "30427": "SC",
+ "30465": "SX",
+ "30631": "YQ",
+ "30655": "QJ",
+ "30684": "QJG",
+ "30707": "SD",
+ "30729": "XH",
+ "30796": "LG",
+ "30917": "PB",
+ "31074": "NM",
+ "31085": "JZ",
+ "31109": "SC",
+ "31181": "ZC",
+ "31192": "MLB",
+ "31293": "JQ",
+ "31400": "YX",
+ "31584": "YJ",
+ "31896": "ZN",
+ "31909": "ZY",
+ "31995": "XJ",
+ "32321": "PF",
+ "32327": "ZY",
+ "32418": "HG",
+ "32420": "XQ",
+ "32421": "HG",
+ "32438": "LG",
+ "32473": "GJ",
+ "32488": "TD",
+ "32521": "QJ",
+ "32527": "PB",
+ "32562": "ZSQ",
+ "32564": "JZ",
+ "32735": "ZD",
+ "32793": "PB",
+ "33071": "PF",
+ "33098": "XL",
+ "33100": "YA",
+ "33152": "PB",
+ "33261": "CX",
+ "33324": "BP",
+ "33333": "TD",
+ "33406": "YA",
+ "33426": "WM",
+ "33432": "PB",
+ "33445": "JG",
+ "33486": "ZN",
+ "33493": "TS",
+ "33507": "QJ",
+ "33540": "QJ",
+ "33544": "ZC",
+ "33564": "XQ",
+ "33617": "YT",
+ "33632": "QJ",
+ "33636": "XH",
+ "33637": "YX",
+ "33694": "WG",
+ "33705": "PF",
+ "33728": "YW",
+ "33882": "SR",
+ "34067": "WM",
+ "34074": "YW",
+ "34121": "QJ",
+ "34255": "ZC",
+ "34259": "XL",
+ "34425": "JH",
+ "34430": "XH",
+ "34485": "KH",
+ "34503": "YS",
+ "34532": "HG",
+ "34552": "XS",
+ "34558": "YE",
+ "34593": "ZL",
+ "34660": "YQ",
+ "34892": "XH",
+ "34928": "SC",
+ "34999": "QJ",
+ "35048": "PB",
+ "35059": "SC",
+ "35098": "ZC",
+ "35203": "TQ",
+ "35265": "JX",
+ "35299": "JX",
+ "35782": "SZ",
+ "35828": "YS",
+ "35830": "E",
+ "35843": "TD",
+ "35895": "YG",
+ "35977": "MH",
+ "36158": "JG",
+ "36228": "QJ",
+ "36426": "XQ",
+ "36466": "DC",
+ "36710": "JC",
+ "36711": "ZYG",
+ "36767": "PB",
+ "36866": "SK",
+ "36951": "YW",
+ "37034": "YX",
+ "37063": "XH",
+ "37218": "ZC",
+ "37325": "ZC",
+ "38063": "PB",
+ "38079": "TD",
+ "38085": "QY",
+ "38107": "DC",
+ "38116": "TD",
+ "38123": "YD",
+ "38224": "HG",
+ "38241": "XTC",
+ "38271": "ZC",
+ "38415": "YE",
+ "38426": "KH",
+ "38461": "YD",
+ "38463": "AE",
+ "38466": "PB",
+ "38477": "XJ",
+ "38518": "YT",
+ "38551": "WK",
+ "38585": "ZC",
+ "38704": "XS",
+ "38739": "LJ",
+ "38761": "GJ",
+ "38808": "SQ",
+ "39048": "JG",
+ "39049": "XJ",
+ "39052": "HG",
+ "39076": "CZ",
+ "39271": "XT",
+ "39534": "TD",
+ "39552": "TD",
+ "39584": "PB",
+ "39647": "SB",
+ "39730": "LG",
+ "39748": "TPB",
+ "40109": "ZQ",
+ "40479": "ND",
+ "40516": "HG",
+ "40536": "HG",
+ "40583": "QJ",
+ "40765": "YQ",
+ "40784": "QJ",
+ "40840": "YK",
+ "40863": "QJG"
+ };
+
+ var _checkPYCh = function (ch) {
+ var uni = ch.charCodeAt(0);
+ // 如果不在汉字处理范围之内,返回原字符,也可以调用自己的处理函数
+ if (uni > 40869 || uni < 19968)
+ return ch; // dealWithOthers(ch);
+ return (oMultiDiff[uni] ? oMultiDiff[uni] : (_ChineseFirstPY.charAt(uni - 19968)));
+ };
+
+ var _mkPYRslt = function (arr) {
+ var arrRslt = [""], k;
+ for (var i = 0, len = arr.length; i < len; i++) {
+ var str = arr[i];
+ var strlen = str.length;
+ if (strlen == 1) {
+ for (k = 0; k < arrRslt.length; k++) {
+ arrRslt[k] += str;
+ }
+ } else {
+ var tmpArr = arrRslt.slice(0);
+ arrRslt = [];
+ for (k = 0; k < strlen; k++) {
+ // 复制一个相同的arrRslt
+ var tmp = tmpArr.slice(0);
+ // 把当前字符str[k]添加到每个元素末尾
+ for (var j = 0; j < tmp.length; j++) {
+ tmp[j] += str.charAt(k);
+ }
+ // 把复制并修改后的数组连接到arrRslt上
+ arrRslt = arrRslt.concat(tmp);
+ }
+ }
+ }
+ return arrRslt.join("").toLowerCase();
+ };
+
+ _.extend(BI, {
+ makeFirstPY: function (str) {
+ if (typeof (str) != "string")
+ return '' + str;
+ var arrResult = []; // 保存中间结果的数组
+ for (var i = 0, len = str.length; i < len; i++) {
+ // 获得unicode码
+ var ch = str.charAt(i);
+ // 检查该unicode码是否在处理范围之内,在则返回该码对映汉字的拼音首字母,不在则调用其它函数处理
+ arrResult.push(_checkPYCh(ch));
+ }
+ // 处理arrResult,返回所有可能的拼音首字母串数组
+ return _mkPYRslt(arrResult);
+ }
+ });
+})();/**
+ * Detect Element Resize.
+ * Forked in order to guard against unsafe 'window' and 'document' references.
+ *
+ * https://github.com/sdecima/javascript-detect-element-resize
+ * Sebastian Decima
+ *
+ * version: 0.5.3
+ **/
+!(function () {
+ // Check `document` and `window` in case of server-side rendering
+ var _window
+ if (typeof window !== 'undefined') {
+ _window = window
+ } else if (typeof self !== 'undefined') {
+ _window = self
+ } else {
+ _window = this
+ }
+
+ var addEventListener = typeof document !== 'undefined' && document.addEventListener;
+ var stylesCreated = false;
+
+ if (addEventListener) {
+ var requestFrame = (function () {
+ var raf = _window.requestAnimationFrame || _window.mozRequestAnimationFrame || _window.webkitRequestAnimationFrame ||
+ function (fn) {
+ return _window.setTimeout(fn, 20);
+ };
+ return function (fn) {
+ return raf(fn);
+ };
+ })();
+
+ var cancelFrame = (function () {
+ var cancel = _window.cancelAnimationFrame || _window.mozCancelAnimationFrame || _window.webkitCancelAnimationFrame ||
+ _window.clearTimeout;
+ return function (id) {
+ return cancel(id);
+ };
+ })();
+
+ var resetTriggers = function (element) {
+ var triggers = element.__resizeTriggers__,
+ expand = triggers.firstElementChild,
+ contract = triggers.lastElementChild,
+ expandChild = expand.firstElementChild;
+ contract.scrollLeft = contract.scrollWidth;
+ contract.scrollTop = contract.scrollHeight;
+ expandChild.style.width = expand.offsetWidth + 1 + 'px';
+ expandChild.style.height = expand.offsetHeight + 1 + 'px';
+ expand.scrollLeft = expand.scrollWidth;
+ expand.scrollTop = expand.scrollHeight;
+ };
+
+ var checkTriggers = function (element) {
+ return element.offsetWidth !== element.__resizeLast__.width ||
+ element.offsetHeight !== element.__resizeLast__.height;
+ }
+
+ var scrollListener = function (e) {
+ var element = this;
+ resetTriggers(this);
+ if (this.__resizeRAF__) cancelFrame(this.__resizeRAF__);
+ this.__resizeRAF__ = requestFrame(function () {
+ if (checkTriggers(element)) {
+ element.__resizeLast__.width = element.offsetWidth;
+ element.__resizeLast__.height = element.offsetHeight;
+ element.__resizeListeners__.forEach(function (fn) {
+ fn.call(element, e);
+ });
+ }
+ });
+ };
+
+ /* Detect CSS Animations support to detect element display/re-attach */
+ var animation = false,
+ animationstring = 'animation',
+ keyframeprefix = '',
+ animationstartevent = 'animationstart',
+ domPrefixes = 'Webkit Moz O ms'.split(' '),
+ startEvents = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' '),
+ pfx = '';
+ {
+ var elm = document.createElement('fakeelement');
+ if (elm.style.animationName !== undefined) {
+ animation = true;
+ }
+
+ if (animation === false) {
+ for (var i = 0; i < domPrefixes.length; i++) {
+ if (elm.style[domPrefixes[i] + 'AnimationName'] !== undefined) {
+ pfx = domPrefixes[i];
+ animationstring = pfx + 'Animation';
+ keyframeprefix = '-' + pfx.toLowerCase() + '-';
+ animationstartevent = startEvents[i];
+ animation = true;
+ break;
+ }
+ }
+ }
+ }
+
+ var animationName = 'resizeanim';
+ var animationKeyframes = '@' + keyframeprefix + 'keyframes ' + animationName + ' { from { opacity: 0; } to { opacity: 0; } } ';
+ var animationStyle = keyframeprefix + 'animation: 1ms ' + animationName + '; ';
+ }
+
+ var createStyles = function () {
+ if (!stylesCreated) {
+ //opacity:0 works around a chrome bug https://code.google.com/p/chromium/issues/detail?id=286360
+ var css = (animationKeyframes ? animationKeyframes : '') +
+ '.resize-triggers { ' + (animationStyle ? animationStyle : '') + 'visibility: hidden; opacity: 0; } ' +
+ '.resize-triggers, .resize-triggers > div, .contract-trigger:before { content: \" \"; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; } .resize-triggers > div { background: #eee; overflow: auto; } .contract-trigger:before { width: 200%; height: 200%; }',
+ head = document.head || document.getElementsByTagName('head')[0],
+ style = document.createElement('style');
+
+ style.type = 'text/css';
+ if (style.styleSheet) {
+ style.styleSheet.cssText = css;
+ } else {
+ style.appendChild(document.createTextNode(css));
+ }
+
+ head.appendChild(style);
+ stylesCreated = true;
+ }
+ }
+
+ var addResizeListener = function (element, fn) {
+ if (addEventListener){
+ if (!element.__resizeTriggers__) {
+ if (getComputedStyle(element).position === 'static') element.style.position = 'relative';
+ createStyles();
+ element.__resizeLast__ = {};
+ element.__resizeListeners__ = [];
+ (element.__resizeTriggers__ = document.createElement('div')).className = 'resize-triggers';
+ element.__resizeTriggers__.innerHTML = '
' +
+ '
';
+ element.appendChild(element.__resizeTriggers__);
+ resetTriggers(element);
+ element.addEventListener('scroll', scrollListener, true);
+
+ /* Listen for a css animation to detect element display/re-attach */
+ animationstartevent && element.__resizeTriggers__.addEventListener(animationstartevent, function (e) {
+ if (e.animationName === animationName)
+ resetTriggers(element);
+ });
+ }
+ element.__resizeListeners__.push(fn);
+
+ } else {
+ element.attachEvent('onresize', fn);
+ }
+ };
+
+ var removeResizeListener = function (element, fn) {
+ if (addEventListener) {
+ element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
+ if (!element.__resizeListeners__.length) {
+ element.removeEventListener('scroll', scrollListener, true);
+ element.__resizeTriggers__ = !element.removeChild(element.__resizeTriggers__);
+ }
+ } else {
+ element.detachEvent('onresize', fn);
+ }
+ };
+
+ BI.ResizeDetector = {
+ addResizeListener: function (widget, fn) {
+ addResizeListener(widget.element[0], fn);
+ return function () {
+ removeResizeListener(widget.element[0], fn);
+ }
+ },
+ removeResizeListener: function (widget, fn) {
+ removeResizeListener(widget.element[0], fn);
+ }
+ };
+}());
+;
+(function () {
+ function defaultComparator(a, b) {
+ return a < b;
+ }
+
+ BI.Heap = function (items, comparator) {
+ this._items = items || [];
+ this._size = this._items.length;
+ this._comparator = comparator || defaultComparator;
+ this._heapify();
+ };
+
+ BI.Heap.prototype = {
+ constructor: BI.Heap,
+ empty: function () {
+ return this._size === 0;
+ },
+
+ pop: function () {
+ if (this._size === 0) {
+ return;
+ }
+
+ var elt = this._items[0];
+
+ var lastElt = this._items.pop();
+ this._size--;
+
+ if (this._size > 0) {
+ this._items[0] = lastElt;
+ this._sinkDown(0);
+ }
+
+ return elt;
+ },
+
+ push: function (item) {
+ this._items[this._size++] = item;
+ this._bubbleUp(this._size - 1);
+ },
+
+ size: function () {
+ return this._size;
+ },
+
+ peek: function () {
+ if (this._size === 0) {
+ return;
+ }
+
+ return this._items[0];
+ },
+
+ _heapify: function () {
+ for (var index = Math.floor((this._size + 1) / 2); index >= 0; index--) {
+ this._sinkDown(index);
+ }
+ },
+
+ _bubbleUp: function (index) {
+ var elt = this._items[index];
+ while (index > 0) {
+ var parentIndex = Math.floor((index + 1) / 2) - 1;
+ var parentElt = this._items[parentIndex];
+
+ // if parentElt < elt, stop
+ if (this._comparator(parentElt, elt)) {
+ return;
+ }
+
+ // swap
+ this._items[parentIndex] = elt;
+ this._items[index] = parentElt;
+ index = parentIndex;
+ }
+ },
+
+ _sinkDown: function (index) {
+ var elt = this._items[index];
+
+ while (true) {
+ var leftChildIndex = 2 * (index + 1) - 1;
+ var rightChildIndex = 2 * (index + 1);
+ var swapIndex = -1;
+
+ if (leftChildIndex < this._size) {
+ var leftChild = this._items[leftChildIndex];
+ if (this._comparator(leftChild, elt)) {
+ swapIndex = leftChildIndex;
+ }
+ }
+
+ if (rightChildIndex < this._size) {
+ var rightChild = this._items[rightChildIndex];
+ if (this._comparator(rightChild, elt)) {
+ if (swapIndex === -1 ||
+ this._comparator(rightChild, this._items[swapIndex])) {
+ swapIndex = rightChildIndex;
+ }
+ }
+ }
+
+ // if we don't have a swap, stop
+ if (swapIndex === -1) {
+ return;
+ }
+
+ this._items[index] = this._items[swapIndex];
+ this._items[swapIndex] = elt;
+ index = swapIndex;
+ }
+ }
+ }
+})();
+;(function () {
+ var clamp = function (min, value, max) {
+ if (value < min) {
+ return min;
+ }
+ if (value > max) {
+ return max;
+ }
+ return value;
+ };
+
+ var BUFFER_ROWS = 5;
+ var NO_ROWS_SCROLL_RESULT = {
+ index: 0,
+ offset: 0,
+ position: 0,
+ contentHeight: 0
+ };
+
+ BI.TableScrollHelper = function (rowCount,
+ defaultRowHeight,
+ viewportHeight,
+ rowHeightGetter) {
+ this._rowOffsets = BI.PrefixIntervalTree.uniform(rowCount, defaultRowHeight);
+ this._storedHeights = new Array(rowCount);
+ for (var i = 0; i < rowCount; ++i) {
+ this._storedHeights[i] = defaultRowHeight;
+ }
+ this._rowCount = rowCount;
+ this._position = 0;
+ this._contentHeight = rowCount * defaultRowHeight;
+ this._defaultRowHeight = defaultRowHeight;
+ this._rowHeightGetter = rowHeightGetter ?
+ rowHeightGetter : function () {
+ return defaultRowHeight
+ };
+ this._viewportHeight = viewportHeight;
+
+ this._updateHeightsInViewport(0, 0);
+ };
+
+ BI.TableScrollHelper.prototype = {
+ constructor: BI.TableScrollHelper,
+ setRowHeightGetter: function (rowHeightGetter) {
+ this._rowHeightGetter = rowHeightGetter;
+ },
+
+ setViewportHeight: function (viewportHeight) {
+ this._viewportHeight = viewportHeight;
+ },
+
+ getContentHeight: function () {
+ return this._contentHeight;
+ },
+
+ _updateHeightsInViewport: function (firstRowIndex,
+ firstRowOffset) {
+ var top = firstRowOffset;
+ var index = firstRowIndex;
+ while (top <= this._viewportHeight && index < this._rowCount) {
+ this._updateRowHeight(index);
+ top += this._storedHeights[index];
+ index++;
+ }
+ },
+
+ _updateHeightsAboveViewport: function (firstRowIndex) {
+ var index = firstRowIndex - 1;
+ while (index >= 0 && index >= firstRowIndex - BUFFER_ROWS) {
+ var delta = this._updateRowHeight(index);
+ this._position += delta;
+ index--;
+ }
+ },
+
+ _updateRowHeight: function (rowIndex) {
+ if (rowIndex < 0 || rowIndex >= this._rowCount) {
+ return 0;
+ }
+ var newHeight = this._rowHeightGetter(rowIndex);
+ if (newHeight !== this._storedHeights[rowIndex]) {
+ var change = newHeight - this._storedHeights[rowIndex];
+ this._rowOffsets.set(rowIndex, newHeight);
+ this._storedHeights[rowIndex] = newHeight;
+ this._contentHeight += change;
+ return change;
+ }
+ return 0;
+ },
+
+ getRowPosition: function (rowIndex) {
+ this._updateRowHeight(rowIndex);
+ return this._rowOffsets.sumUntil(rowIndex);
+ },
+
+ scrollBy: function (delta) {
+ if (this._rowCount === 0) {
+ return NO_ROWS_SCROLL_RESULT;
+ }
+ var firstRow = this._rowOffsets.greatestLowerBound(this._position);
+ firstRow = clamp(firstRow, 0, Math.max(this._rowCount - 1, 0));
+ var firstRowPosition = this._rowOffsets.sumUntil(firstRow);
+ var rowIndex = firstRow;
+ var position = this._position;
+
+ var rowHeightChange = this._updateRowHeight(rowIndex);
+ if (firstRowPosition !== 0) {
+ position += rowHeightChange;
+ }
+ var visibleRowHeight = this._storedHeights[rowIndex] -
+ (position - firstRowPosition);
+
+ if (delta >= 0) {
+
+ while (delta > 0 && rowIndex < this._rowCount) {
+ if (delta < visibleRowHeight) {
+ position += delta;
+ delta = 0;
+ } else {
+ delta -= visibleRowHeight;
+ position += visibleRowHeight;
+ rowIndex++;
+ }
+ if (rowIndex < this._rowCount) {
+ this._updateRowHeight(rowIndex);
+ visibleRowHeight = this._storedHeights[rowIndex];
+ }
+ }
+ } else if (delta < 0) {
+ delta = -delta;
+ var invisibleRowHeight = this._storedHeights[rowIndex] - visibleRowHeight;
+
+ while (delta > 0 && rowIndex >= 0) {
+ if (delta < invisibleRowHeight) {
+ position -= delta;
+ delta = 0;
+ } else {
+ position -= invisibleRowHeight;
+ delta -= invisibleRowHeight;
+ rowIndex--;
+ }
+ if (rowIndex >= 0) {
+ var change = this._updateRowHeight(rowIndex);
+ invisibleRowHeight = this._storedHeights[rowIndex];
+ position += change;
+ }
+ }
+ }
+
+ var maxPosition = this._contentHeight - this._viewportHeight;
+ position = clamp(position, 0, maxPosition);
+ this._position = position;
+ var firstRowIndex = this._rowOffsets.greatestLowerBound(position);
+ firstRowIndex = clamp(firstRowIndex, 0, Math.max(this._rowCount - 1, 0));
+ firstRowPosition = this._rowOffsets.sumUntil(firstRowIndex);
+ var firstRowOffset = firstRowPosition - position;
+
+ this._updateHeightsInViewport(firstRowIndex, firstRowOffset);
+ this._updateHeightsAboveViewport(firstRowIndex);
+
+ return {
+ index: firstRowIndex,
+ offset: firstRowOffset,
+ position: this._position,
+ contentHeight: this._contentHeight
+ };
+ },
+
+ _getRowAtEndPosition: function (rowIndex) {
+ // We need to update enough rows above the selected one to be sure that when
+ // we scroll to selected position all rows between first shown and selected
+ // one have most recent heights computed and will not resize
+ this._updateRowHeight(rowIndex);
+ var currentRowIndex = rowIndex;
+ var top = this._storedHeights[currentRowIndex];
+ while (top < this._viewportHeight && currentRowIndex >= 0) {
+ currentRowIndex--;
+ if (currentRowIndex >= 0) {
+ this._updateRowHeight(currentRowIndex);
+ top += this._storedHeights[currentRowIndex];
+ }
+ }
+ var position = this._rowOffsets.sumTo(rowIndex) - this._viewportHeight;
+ if (position < 0) {
+ position = 0;
+ }
+ return position;
+ },
+
+ scrollTo: function (position) {
+ if (this._rowCount === 0) {
+ return NO_ROWS_SCROLL_RESULT;
+ }
+ if (position <= 0) {
+ // If position less than or equal to 0 first row should be fully visible
+ // on top
+ this._position = 0;
+ this._updateHeightsInViewport(0, 0);
+
+ return {
+ index: 0,
+ offset: 0,
+ position: this._position,
+ contentHeight: this._contentHeight
+ };
+ } else if (position >= this._contentHeight - this._viewportHeight) {
+ // If position is equal to or greater than max scroll value, we need
+ // to make sure to have bottom border of last row visible.
+ var rowIndex = this._rowCount - 1;
+ position = this._getRowAtEndPosition(rowIndex);
+ }
+ this._position = position;
+
+ var firstRowIndex = this._rowOffsets.greatestLowerBound(position);
+ firstRowIndex = clamp(firstRowIndex, 0, Math.max(this._rowCount - 1, 0));
+ var firstRowPosition = this._rowOffsets.sumUntil(firstRowIndex);
+ var firstRowOffset = firstRowPosition - position;
+
+ this._updateHeightsInViewport(firstRowIndex, firstRowOffset);
+ this._updateHeightsAboveViewport(firstRowIndex);
+
+ return {
+ index: firstRowIndex,
+ offset: firstRowOffset,
+ position: this._position,
+ contentHeight: this._contentHeight
+ };
+ },
+
+ /**
+ * Allows to scroll to selected row with specified offset. It always
+ * brings that row to top of viewport with that offset
+ */
+ scrollToRow: function (rowIndex, offset) {
+ rowIndex = clamp(rowIndex, 0, Math.max(this._rowCount - 1, 0));
+ offset = clamp(offset, -this._storedHeights[rowIndex], 0);
+ var firstRow = this._rowOffsets.sumUntil(rowIndex);
+ return this.scrollTo(firstRow - offset);
+ },
+
+ /**
+ * Allows to scroll to selected row by bringing it to viewport with minimal
+ * scrolling. This that if row is fully visible, scroll will not be changed.
+ * If top border of row is above top of viewport it will be scrolled to be
+ * fully visible on the top of viewport. If the bottom border of row is
+ * below end of viewport, it will be scrolled up to be fully visible on the
+ * bottom of viewport.
+ */
+ scrollRowIntoView: function (rowIndex) {
+ rowIndex = clamp(rowIndex, 0, Math.max(this._rowCount - 1, 0));
+ var rowBegin = this._rowOffsets.sumUntil(rowIndex);
+ var rowEnd = rowBegin + this._storedHeights[rowIndex];
+ if (rowBegin < this._position) {
+ return this.scrollTo(rowBegin);
+ } else if (this._position + this._viewportHeight < rowEnd) {
+ var position = this._getRowAtEndPosition(rowIndex);
+ return this.scrollTo(position);
+ }
+ return this.scrollTo(this._position);
+ }
+ };
+
+})();
+// Data structure that allows to store values and assign positions to them
+// in a way to minimize changing positions of stored values when new ones are
+// added or when some values are replaced. Stored elements are alwasy assigned
+// a consecutive set of positoins startin from 0 up to count of elements less 1
+// Following actions can be executed
+// * get position assigned to given value (null if value is not stored)
+// * create new entry for new value and get assigned position back
+// * replace value that is furthest from specified value range with new value
+// and get it's position back
+// All operations take amortized log(n) time where n is number of elements in
+// the set.
+BI.IntegerBufferSet = function () {
+ this._valueToPositionMap = {};
+ this._size = 0;
+ this._smallValues = new BI.Heap(
+ [], // Initial data in the heap
+ this._smallerComparator
+ );
+ this._largeValues = new BI.Heap(
+ [], // Initial data in the heap
+ this._greaterComparator
+ );
+
+};
+
+BI.IntegerBufferSet.prototype = {
+ constructor: BI.IntegerBufferSet,
+ getSize: function () /*number*/ {
+ return this._size;
+ },
+
+ getValuePosition: function (/*number*/ value) /*?number*/ {
+ if (this._valueToPositionMap[value] === undefined) {
+ return null;
+ }
+ return this._valueToPositionMap[value];
+ },
+
+ getNewPositionForValue: function (/*number*/ value) /*number*/ {
+ var newPosition = this._size;
+ this._size++;
+ this._pushToHeaps(newPosition, value);
+ this._valueToPositionMap[value] = newPosition;
+ return newPosition;
+ },
+
+ replaceFurthestValuePosition: function (/*number*/ lowValue,
+ /*number*/ highValue,
+ /*number*/ newValue) /*?number*/ {
+ this._cleanHeaps();
+ if (this._smallValues.empty() || this._largeValues.empty()) {
+ // Threre are currently no values stored. We will have to create new
+ // position for this value.
+ return null;
+ }
+
+ var minValue = this._smallValues.peek().value;
+ var maxValue = this._largeValues.peek().value;
+ if (minValue >= lowValue && maxValue <= highValue) {
+ // All values currently stored are necessary, we can't reuse any of them.
+ return null;
+ }
+
+ var valueToReplace;
+ if (lowValue - minValue > maxValue - highValue) {
+ // minValue is further from provided range. We will reuse it's position.
+ valueToReplace = minValue;
+ this._smallValues.pop();
+ } else {
+ valueToReplace = maxValue;
+ this._largeValues.pop();
+ }
+ var position = this._valueToPositionMap[valueToReplace];
+ delete this._valueToPositionMap[valueToReplace];
+ this._valueToPositionMap[newValue] = position;
+ this._pushToHeaps(position, newValue);
+
+ return position;
+ },
+
+ _pushToHeaps: function (/*number*/ position, /*number*/ value) {
+ var element = {
+ position: position,
+ value:value
+ };
+ // We can reuse the same object in both heaps, because we don't mutate them
+ this._smallValues.push(element);
+ this._largeValues.push(element);
+ },
+
+ _cleanHeaps: function () {
+ // We not usually only remove object from one heap while moving value.
+ // Here we make sure that there is no stale data on top of heaps.
+ this._cleanHeap(this._smallValues);
+ this._cleanHeap(this._largeValues);
+ var minHeapSize =
+ Math.min(this._smallValues.size(), this._largeValues.size());
+ var maxHeapSize =
+ Math.max(this._smallValues.size(), this._largeValues.size());
+ if (maxHeapSize > 10 * minHeapSize) {
+ // There are many old values in one of heaps. We nned to get rid of them
+ // to not use too avoid memory leaks
+ this._recreateHeaps();
+ }
+ },
+
+ _recreateHeaps: function () {
+ var sourceHeap = this._smallValues.size() < this._largeValues.size() ?
+ this._smallValues :
+ this._largeValues;
+ var newSmallValues = new Heap(
+ [], // Initial data in the heap
+ this._smallerComparator
+ );
+ var newLargeValues = new Heap(
+ [], // Initial datat in the heap
+ this._greaterComparator
+ );
+ while (!sourceHeap.empty()) {
+ var element = sourceHeap.pop();
+ // Push all stil valid elements to new heaps
+ if (this._valueToPositionMap[element.value] !== undefined) {
+ newSmallValues.push(element);
+ newLargeValues.push(element);
+ }
+ }
+ this._smallValues = newSmallValues;
+ this._largeValues = newLargeValues;
+ },
+
+ _cleanHeap: function (/*object*/ heap) {
+ while (!heap.empty() &&
+ this._valueToPositionMap[heap.peek().value] === undefined) {
+ heap.pop();
+ }
+ },
+
+ _smallerComparator: function (/*object*/ lhs, /*object*/ rhs) /*boolean*/ {
+ return lhs.value < rhs.value;
+ },
+
+ _greaterComparator: function (/*object*/ lhs, /*object*/ rhs) /*boolean*/ {
+ return lhs.value > rhs.value;
+ }
+};
+;
+!(function () {
+ BI.LinkHashMap = function () {
+ this.array = [];
+ this.map = {};
+ };
+ BI.LinkHashMap.prototype = {
+ constructor: BI.LinkHashMap,
+ has: function (key) {
+ if (key in this.map) {
+ return true;
+ }
+ return false;
+ },
+
+ add: function (key, value) {
+ if (typeof key == 'undefined') {
+ return;
+ }
+ if (key in this.map) {
+ this.map[key] = value;
+ } else {
+ this.array.push(key);
+ this.map[key] = value;
+ }
+ },
+
+ remove: function (key) {
+ if (key in this.map) {
+ delete this.map[key];
+ for (var i = 0; i < this.array.length; i++) {
+ if (this.array[i] == key) {
+ this.array.splice(i, 1);
+ break;
+ }
+ }
+ }
+ },
+
+ size: function () {
+ return this.array.length;
+ },
+
+ each: function (fn, scope) {
+ var scope = scope || window;
+ var fn = fn || null;
+ if (fn == null || typeof (fn) != "function") {
+ return;
+ }
+ for (var i = 0; i < this.array.length; i++) {
+ var key = this.array[i];
+ var value = this.map[key];
+ var re = fn.call(scope, key, value, i, this.array, this.map);
+ if (re == false) {
+ break;
+ }
+ }
+ },
+
+ get: function (key) {
+ return this.map[key];
+ },
+
+ toArray: function () {
+ var array = [];
+ this.each(function (key, value) {
+ array.push(value);
+ })
+ return array;
+ }
+ }
+})();window.BI = window.BI || {};
+
+$.extend(BI, {
+ $defaultImport: function (options) {
+ var config = $.extend({
+ op: 'resource',
+ path: null,
+ type: null,
+ must: false
+ }, options);
+ config.url = BI.servletURL + '?op=' + config.op + '&resource=' + config.path;
+ this.$import(config.url, config.type,config.must);
+ },
+ $import: function () {
+ var _LOADED = {}; // alex:保存加载过的
+ function loadReady(src, must) {
+ var $scripts = $("head script");
+ $.each($scripts, function (i, item) {
+ if (item.src.indexOf(src) != -1) {
+ _LOADED[src] = true;
+ }
+ });
+ var $links = $("head link");
+ $.each($links, function (i, item) {
+ if (item.href.indexOf(src) != -1 && must) {
+ _LOADED[src] = false;
+ $(item).remove();
+ }
+ });
+ }
+
+ // must=true 强行加载
+ return function (src, ext, must) {
+ loadReady(src, must);
+ // alex:如果已经加载过了的,直接return
+ if (_LOADED[src] === true) {
+ return;
+ }
+ if (ext === 'css') {
+ var link = document.createElement('link');
+ link.rel = 'stylesheet';
+ link.type = 'text/css';
+ link.href = src;
+ var head = document.getElementsByTagName('head')[0];
+ head.appendChild(link);
+ _LOADED[src] = true;
+ } else {
+ // alex:这里用同步调用的方式,必须等待ajax完成
+ $.ajax({
+ url: src,
+ dataType: "script", // alex:指定dataType为script,jquery会帮忙做globalEval的事情
+ async: false,
+ cache: true,
+ complete: function (res, status) {
+ /*
+ * alex:发现jquery会很智能地判断一下返回的数据类型是不是script,然后做一个globalEval
+ * 所以当status为success时就不需要再把其中的内容加到script里面去了
+ */
+ if (status == 'success') {
+ _LOADED[src] = true;
+ }
+ }
+ })
+ }
+ }
+ }()
+});;
+!(function () {
+ BI.LRU = function (limit) {
+ this.size = 0;
+ this.limit = limit;
+ this.head = this.tail = undefined;
+ this._keymap = {};
+ };
+
+ var p = BI.LRU.prototype;
+
+ p.put = function (key, value) {
+ var removed;
+ if (this.size === this.limit) {
+ removed = this.shift();
+ }
+
+ var entry = this.get(key, true);
+ if (!entry) {
+ entry = {
+ key: key
+ };
+ this._keymap[key] = entry;
+ if (this.tail) {
+ this.tail.newer = entry;
+ entry.older = this.tail
+ } else {
+ this.head = entry
+ }
+ this.tail = entry;
+ this.size++;
+ }
+ entry.value = value;
+
+ return removed;
+ };
+
+ p.shift = function () {
+ var entry = this.head;
+ if (entry) {
+ this.head = this.head.newer;
+ this.head.older = undefined;
+ entry.newer = entry.older = undefined;
+ this._keymap[entry.key] = undefined;
+ this.size--;
+ }
+ return entry;
+ };
+
+
+ p.get = function (key, returnEntry) {
+ var entry = this._keymap[key];
+ if (entry === undefined) return;
+ if (entry === this.tail) {
+ return returnEntry
+ ? entry
+ : entry.value
+ }
+ // HEAD--------------TAIL
+ // <.older .newer>
+ // <--- add direction --
+ // A B C
E
+ if (entry.newer) {
+ if (entry === this.head) {
+ this.head = entry.newer
+ }
+ entry.newer.older = entry.older; // C <-- E.
+ }
+ if (entry.older) {
+ entry.older.newer = entry.newer; // C. --> E
+ }
+ entry.newer = undefined; // D --x
+ entry.older = this.tail; // D. --> E
+ if (this.tail) {
+ this.tail.newer = entry; // E. <-- D
+ }
+ this.tail = entry;
+ return returnEntry
+ ? entry
+ : entry.value
+ };
+})();;
+!(function () {
+ var MD5 = function (hexcase) {
+ this.hexcase = !hexcase ? 0 : 1;
+ /* hex output format. 0 - lowercase; 1 - uppercase */
+ this.b64pad = "";
+ /* base-64 pad character. "=" for strict RFC compliance */
+ this.chrsz = 8;
+ /* bits per input character. 8 - ASCII; 16 - Unicode */
+ };
+
+ /*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+ MD5.prototype.hex_md5 = function (s) {
+ return this.binl2hex(this.core_md5(this.str2binl(s), s.length * this.chrsz));
+ };
+
+ MD5.prototype.hex_md5_salt = function (s) {
+ var md5ed = this.hex_md5(s);
+
+ var items1 = [];
+ var items2 = [];
+ for (var i = 0; i < md5ed.length; i++) {
+ if (i % 2 === 0) {
+ items1.push(md5ed.charAt(i));
+ } else {
+ items2.push(md5ed.charAt(i));
+ }
+ }
+ var result = ":" + items1.join("") + items2.join("");
+ return result;
+ };
+
+ MD5.prototype.b64_md5 = function (s) {
+ return this.binl2b64(this.core_md5(this.str2binl(s), s.length * this.chrsz));
+ };
+
+ MD5.prototype.hex_hmac_md5 = function (key, data) {
+ return this.binl2hex(this.core_hmac_md5(key, data));
+ };
+
+ MD5.prototype.b64_hmac_md5 = function (key, data) {
+ return this.binl2b64(this.core_hmac_md5(key, data));
+ };
+
+ /* Backwards compatibility - same as hex_md5() */
+ MD5.prototype.calcMD5 = function (s) {
+ return this.binl2hex(this.core_md5(this.str2binl(s), s.length * this.chrsz));
+ };
+
+ MD5.prototype.core_md5 = function (x, len) {
+ /* append padding */
+ x[len >> 5] |= 0x80 << ((len) % 32);
+ x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+ var a = 1732584193;
+ var b = -271733879;
+ var c = -1732584194;
+ var d = 271733878;
+
+ for (var i = 0; i < x.length; i += 16) {
+ var olda = a;
+ var oldb = b;
+ var oldc = c;
+ var oldd = d;
+
+ a = this.md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
+ d = this.md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
+ c = this.md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
+ b = this.md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
+ a = this.md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
+ d = this.md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
+ c = this.md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
+ b = this.md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
+ a = this.md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
+ d = this.md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
+ c = this.md5_ff(c, d, a, b, x[i + 10], 17, -42063);
+ b = this.md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
+ a = this.md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
+ d = this.md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
+ c = this.md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
+ b = this.md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
+
+ a = this.md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
+ d = this.md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
+ c = this.md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
+ b = this.md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
+ a = this.md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
+ d = this.md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
+ c = this.md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
+ b = this.md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
+ a = this.md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
+ d = this.md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
+ c = this.md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
+ b = this.md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
+ a = this.md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
+ d = this.md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
+ c = this.md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
+ b = this.md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
+
+ a = this.md5_hh(a, b, c, d, x[i + 5], 4, -378558);
+ d = this.md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
+ c = this.md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
+ b = this.md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
+ a = this.md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
+ d = this.md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
+ c = this.md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
+ b = this.md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
+ a = this.md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
+ d = this.md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
+ c = this.md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
+ b = this.md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
+ a = this.md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
+ d = this.md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
+ c = this.md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
+ b = this.md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
+
+ a = this.md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
+ d = this.md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
+ c = this.md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
+ b = this.md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
+ a = this.md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
+ d = this.md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
+ c = this.md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
+ b = this.md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
+ a = this.md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
+ d = this.md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
+ c = this.md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
+ b = this.md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
+ a = this.md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
+ d = this.md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
+ c = this.md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
+ b = this.md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
+
+ a = this.safe_add(a, olda);
+ b = this.safe_add(b, oldb);
+ c = this.safe_add(c, oldc);
+ d = this.safe_add(d, oldd);
+ }
+ return Array(a, b, c, d);
+
+ };
+
+ /*
+ * These functions implement the four basic operations the algorithm uses.
+ */
+ MD5.prototype.md5_cmn = function (q, a, b, x, s, t) {
+ return this.safe_add(this.bit_rol(this.safe_add(this.safe_add(a, q), this.safe_add(x, t)), s), b);
+ };
+ MD5.prototype.md5_ff = function (a, b, c, d, x, s, t) {
+ return this.md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+ };
+ MD5.prototype.md5_gg = function (a, b, c, d, x, s, t) {
+ return this.md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+ };
+ MD5.prototype.md5_hh = function (a, b, c, d, x, s, t) {
+ return this.md5_cmn(b ^ c ^ d, a, b, x, s, t);
+ };
+ MD5.prototype.md5_ii = function (a, b, c, d, x, s, t) {
+ return this.md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+ };
+
+ /*
+ * Calculate the HMAC-MD5, of a key and some data
+ */
+ MD5.prototype.core_hmac_md5 = function (key, data) {
+ var bkey = this.str2binl(key);
+ if (bkey.length > 16)
+ bkey = this.core_md5(bkey, key.length * this.chrsz);
+
+ var ipad = Array(16), opad = Array(16);
+ for (var i = 0; i < 16; i++) {
+ ipad[i] = bkey[i] ^ 0x36363636;
+ opad[i] = bkey[i] ^ 0x5C5C5C5C;
+ }
+
+ var hash = this.core_md5(ipad.concat(this.str2binl(data)), 512 + data.length * this.chrsz);
+ return this.core_md5(opad.concat(hash), 512 + 128);
+ };
+
+ /*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+ MD5.prototype.safe_add = function (x, y) {
+ var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+ var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+ return (msw << 16) | (lsw & 0xFFFF);
+ };
+
+ /*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+ MD5.prototype.bit_rol = function (num, cnt) {
+ return (num << cnt) | (num >>> (32 - cnt));
+ };
+
+ /*
+ * Convert a string to an array of little-endian words
+ * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
+ */
+ MD5.prototype.str2binl = function (str) {
+ var bin = Array();
+ var mask = (1 << this.chrsz) - 1;
+ for (var i = 0; i < str.length * this.chrsz; i += this.chrsz)
+ bin[i >> 5] |= (str.charCodeAt(i / this.chrsz) & mask) << (i % 32);
+ return bin;
+ };
+
+ /*
+ * Convert an array of little-endian words to a hex string.
+ */
+ MD5.prototype.binl2hex = function (binarray) {
+ var hex_tab = this.hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+ var str = "";
+ for (var i = 0; i < binarray.length * 4; i++) {
+ str += hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8 + 4)) & 0xF)
+ + hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8)) & 0xF);
+ }
+ return str;
+ };
+
+ /*
+ * Convert an array of little-endian words to a base-64 string
+ */
+ MD5.prototype.binl2b64 = function (binarray) {
+ var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ var str = "";
+ for (var i = 0; i < binarray.length * 4; i += 3) {
+ var triplet = (((binarray[i >> 2] >> 8 * (i % 4)) & 0xFF) << 16)
+ | (((binarray[i + 1 >> 2] >> 8 * ((i + 1) % 4)) & 0xFF) << 8)
+ | ((binarray[i + 2 >> 2] >> 8 * ((i + 2) % 4)) & 0xFF);
+ for (var j = 0; j < 4; j++) {
+ if (i * 8 + j * 6 > binarray.length * 32)
+ str += this.b64pad;
+ else
+ str += tab.charAt((triplet >> 6 * (3 - j)) & 0x3F);
+ }
+ }
+ return str;
+ };
+ BI.MD5 = new MD5();
+})();//线段树
+;(function () {
+ var parent = function (node) {
+ return Math.floor(node / 2);
+ };
+
+ var Int32Array = window.Int32Array || function (size) {
+ var xs = [];
+ for (var i = size - 1; i >= 0; --i) {
+ xs[i] = 0;
+ }
+ return xs;
+ };
+
+ var ceilLog2 = function (x) {
+ var y = 1;
+ while (y < x) {
+ y *= 2;
+ }
+ return y;
+ };
+
+ BI.PrefixIntervalTree = function (xs) {
+ this._size = xs.length;
+ this._half = ceilLog2(this._size);
+ this._heap = new Int32Array(2 * this._half);
+
+ var i;
+ for (i = 0; i < this._size; ++i) {
+ this._heap[this._half + i] = xs[i];
+ }
+
+ for (i = this._half - 1; i > 0; --i) {
+ this._heap[i] = this._heap[2 * i] + this._heap[2 * i + 1];
+ }
+ };
+
+ BI.PrefixIntervalTree.prototype = {
+ constructor: BI.PrefixIntervalTree,
+ set: function (index, value) {
+ var node = this._half + index;
+ this._heap[node] = value;
+
+ node = parent(node);
+ for (; node !== 0; node = parent(node)) {
+ this._heap[node] =
+ this._heap[2 * node] + this._heap[2 * node + 1];
+ }
+ },
+
+ get: function (index) {
+ var node = this._half + index;
+ return this._heap[node];
+ },
+
+ getSize: function () {
+ return this._size;
+ },
+
+ /**
+ * get(0) + get(1) + ... + get(end - 1).
+ */
+ sumUntil: function (end) {
+ if (end === 0) {
+ return 0;
+ }
+
+ var node = this._half + end - 1;
+ var sum = this._heap[node];
+ for (; node !== 1; node = parent(node)) {
+ if (node % 2 === 1) {
+ sum += this._heap[node - 1];
+ }
+ }
+
+ return sum;
+ },
+
+ /**
+ * get(0) + get(1) + ... + get(inclusiveEnd).
+ */
+ sumTo: function (inclusiveEnd) {
+ return this.sumUntil(inclusiveEnd + 1);
+ },
+
+ /**
+ * sum get(begin) + get(begin + 1) + ... + get(end - 1).
+ */
+ sum: function (begin, end) {
+ return this.sumUntil(end) - this.sumUntil(begin);
+ },
+
+ /**
+ * Returns the smallest i such that 0 <= i <= size and sumUntil(i) <= t, or
+ * -1 if no such i exists.
+ */
+ greatestLowerBound: function (t) {
+ if (t < 0) {
+ return -1;
+ }
+
+ var node = 1;
+ if (this._heap[node] <= t) {
+ return this._size;
+ }
+
+ while (node < this._half) {
+ var leftSum = this._heap[2 * node];
+ if (t < leftSum) {
+ node = 2 * node;
+ } else {
+ node = 2 * node + 1;
+ t -= leftSum;
+ }
+ }
+
+ return node - this._half;
+ },
+
+ /**
+ * Returns the smallest i such that 0 <= i <= size and sumUntil(i) < t, or
+ * -1 if no such i exists.
+ */
+ greatestStrictLowerBound: function (t) {
+ if (t <= 0) {
+ return -1;
+ }
+
+ var node = 1;
+ if (this._heap[node] < t) {
+ return this._size;
+ }
+
+ while (node < this._half) {
+ var leftSum = this._heap[2 * node];
+ if (t <= leftSum) {
+ node = 2 * node;
+ } else {
+ node = 2 * node + 1;
+ t -= leftSum;
+ }
+ }
+
+ return node - this._half;
+ },
+
+ /**
+ * Returns the smallest i such that 0 <= i <= size and t <= sumUntil(i), or
+ * size + 1 if no such i exists.
+ */
+ leastUpperBound: function (t) {
+ return this.greatestStrictLowerBound(t) + 1;
+ },
+
+ /**
+ * Returns the smallest i such that 0 <= i <= size and t < sumUntil(i), or
+ * size + 1 if no such i exists.
+ */
+ leastStrictUpperBound: function (t) {
+ return this.greatestLowerBound(t) + 1;
+ }
+ };
+
+ BI.PrefixIntervalTree.uniform = function (size, initialValue) {
+ var xs = [];
+ for (var i = size - 1; i >= 0; --i) {
+ xs[i] = initialValue;
+ }
+
+ return new BI.PrefixIntervalTree(xs);
+ };
+
+ BI.PrefixIntervalTree.empty = function (size) {
+ return BI.PrefixIntervalTree.uniform(size, 0);
+ };
+
+})();
+;
+!(function () {
+ BI.Queue = function (capacity) {
+ this.capacity = capacity;
+ this.array = [];
+ };
+ BI.Queue.prototype = {
+ constructor: BI.Queue,
+
+ contains: function (v) {
+ return this.array.contains(v);
+ },
+
+ indexOf: function (v) {
+ return this.array.contains(v);
+ },
+
+ getElementByIndex: function(index) {
+ return this.array[index];
+ },
+
+ push: function (v) {
+ this.array.push(v);
+ if (this.capacity && this.array.length > this.capacity) {
+ this.array.shift();
+ }
+ },
+
+ pop: function () {
+ this.array.pop();
+ },
+
+ shift: function () {
+ this.array.shift();
+ },
+
+ unshift: function (v) {
+ this.array.unshift(v);
+ if (this.capacity && this.array.length > this.capacity) {
+ this.array.pop();
+ }
+ },
+
+ remove: function (v) {
+ this.array.remove(v);
+ },
+
+ splice: function() {
+ this.array.splice.apply(this.array, arguments);
+ },
+
+ slice: function() {
+ this.array.slice.apply(this.array, arguments);
+ },
+
+ size: function () {
+ return this.array.length;
+ },
+
+ each: function (fn, scope) {
+ var scope = scope || window;
+ var fn = fn || null;
+ if (fn == null || typeof (fn) != "function") {
+ return;
+ }
+ for (var i = 0; i < this.array.length; i++) {
+ var re = fn.call(scope, i, this.array[i], this.array);
+ if (re == false) {
+ break;
+ }
+ }
+ },
+
+ toArray: function () {
+ return this.array;
+ },
+
+ fromArray: function (array) {
+ var self = this;
+ BI.each(array, function (i, v) {
+ self.push(v);
+ })
+ },
+
+ clear: function () {
+ this.array.clear();
+ }
+ }
+})();!(function () {
+ var Section = function (height, width, x, y) {
+ this.height = height;
+ this.width = width;
+ this.x = x;
+ this.y = y;
+
+ this._indexMap = {};
+ this._indices = [];
+ };
+
+ Section.prototype = {
+ constructor: Section,
+ addCellIndex: function (index) {
+ if (!this._indexMap[index]) {
+ this._indexMap[index] = true;
+ this._indices.push(index);
+ }
+ },
+
+ getCellIndices: function () {
+ return this._indices
+ }
+ };
+
+ var SECTION_SIZE = 100;
+ BI.SectionManager = function (sectionSize) {
+ this._sectionSize = sectionSize || SECTION_SIZE;
+ this._cellMetadata = [];
+ this._sections = {};
+ };
+
+ BI.SectionManager.prototype = {
+ constructor: BI.SectionManager,
+ getCellIndices: function (height, width, x, y) {
+ var indices = {};
+
+ BI.each(this.getSections(height, width, x, y), function (i, section) {
+ BI.each(section.getCellIndices(), function (j, index) {
+ indices[index] = index
+ })
+ });
+
+ return BI.map(BI.keys(indices), function (i, index) {
+ return indices[index]
+ });
+ },
+
+ getCellMetadata: function (index) {
+ return this._cellMetadata[index];
+ },
+
+ getSections: function (height, width, x, y) {
+ var sectionXStart = Math.floor(x / this._sectionSize);
+ var sectionXStop = Math.floor((x + width - 1) / this._sectionSize);
+ var sectionYStart = Math.floor(y / this._sectionSize);
+ var sectionYStop = Math.floor((y + height - 1) / this._sectionSize);
+
+ var sections = [];
+
+ for (var sectionX = sectionXStart; sectionX <= sectionXStop; sectionX++) {
+ for (var sectionY = sectionYStart; sectionY <= sectionYStop; sectionY++) {
+ var key = sectionX + "." + sectionY;
+
+ if (!this._sections[key]) {
+ this._sections[key] = new Section(this._sectionSize, this._sectionSize, sectionX * this._sectionSize, sectionY * this._sectionSize)
+ }
+
+ sections.push(this._sections[key])
+ }
+ }
+
+ return sections
+ },
+
+ getTotalSectionCount: function () {
+ return BI.size(this._sections);
+ },
+
+ registerCell: function (cellMetadatum, index) {
+ this._cellMetadata[index] = cellMetadatum;
+
+ BI.each(this.getSections(cellMetadatum.height, cellMetadatum.width, cellMetadatum.x, cellMetadatum.y), function (i, section) {
+ section.addCellIndex(index);
+ });
+ }
+ }
+})();if (typeof Set !== 'undefined' && Set.toString().match(/native code/)) {
+
+} else {
+ Set = function () {
+ this.set = {}
+ };
+ Set.prototype.has = function (key) {
+ return this.set[key] !== undefined;
+ };
+ Set.prototype.add = function (key) {
+ this.set[key] = 1
+ };
+ Set.prototype.clear = function () {
+ this.set = {}
+ };
+};
+(function () {
+ var clamp = function (value, min, max) {
+ if (value < min) {
+ return min;
+ }
+ if (value > max) {
+ return max;
+ }
+ return value;
+ };
+ var MIN_BUFFER_ROWS = 6;
+ var MAX_BUFFER_ROWS = 10;
+
+ BI.TableRowBuffer = function (rowsCount,
+ defaultRowHeight,
+ viewportHeight,
+ rowHeightGetter) {
+ this._bufferSet = new BI.IntegerBufferSet();
+ this._defaultRowHeight = defaultRowHeight;
+ this._viewportRowsBegin = 0;
+ this._viewportRowsEnd = 0;
+ this._maxVisibleRowCount = Math.ceil(viewportHeight / defaultRowHeight) + 1;
+ // this._bufferRowsCount = Math.floor(this._maxVisibleRowCount / 2);
+ this._bufferRowsCount = clamp(
+ Math.floor(this._maxVisibleRowCount / 2),
+ MIN_BUFFER_ROWS,
+ MAX_BUFFER_ROWS
+ );
+ this._rowsCount = rowsCount;
+ this._rowHeightGetter = rowHeightGetter;
+ this._rows = [];
+ this._viewportHeight = viewportHeight;
+
+ };
+ BI.TableRowBuffer.prototype = {
+ constructor: BI.TableRowBuffer,
+
+ getRowsWithUpdatedBuffer: function () {
+ var remainingBufferRows = 2 * this._bufferRowsCount;
+ var bufferRowIndex =
+ Math.max(this._viewportRowsBegin - this._bufferRowsCount, 0);
+ while (bufferRowIndex < this._viewportRowsBegin) {
+ this._addRowToBuffer(
+ bufferRowIndex,
+ this._viewportRowsBegin,
+ this._viewportRowsEnd - 1
+ );
+ bufferRowIndex++;
+ remainingBufferRows--;
+ }
+ bufferRowIndex = this._viewportRowsEnd;
+ while (bufferRowIndex < this._rowsCount && remainingBufferRows > 0) {
+ this._addRowToBuffer(
+ bufferRowIndex,
+ this._viewportRowsBegin,
+ this._viewportRowsEnd - 1
+ );
+ bufferRowIndex++;
+ remainingBufferRows--;
+ }
+ return this._rows;
+ },
+
+ getRows: function (firstRowIndex,
+ firstRowOffset) {
+ var top = firstRowOffset;
+ var totalHeight = top;
+ var rowIndex = firstRowIndex;
+ var endIndex =
+ Math.min(firstRowIndex + this._maxVisibleRowCount, this._rowsCount);
+
+ this._viewportRowsBegin = firstRowIndex;
+ while (rowIndex < endIndex ||
+ (totalHeight < this._viewportHeight && rowIndex < this._rowsCount)) {
+ this._addRowToBuffer(
+ rowIndex,
+ firstRowIndex,
+ endIndex - 1
+ );
+ totalHeight += this._rowHeightGetter(rowIndex);
+ ++rowIndex;
+ // Store index after the last viewport row as end, to be able to
+ // distinguish when there are no rows rendered in viewport
+ this._viewportRowsEnd = rowIndex;
+ }
+
+ return this._rows;
+ },
+
+ _addRowToBuffer: function (rowIndex,
+ firstViewportRowIndex,
+ lastViewportRowIndex) {
+ var rowPosition = this._bufferSet.getValuePosition(rowIndex);
+ var viewportRowsCount = lastViewportRowIndex - firstViewportRowIndex + 1;
+ var allowedRowsCount = viewportRowsCount + this._bufferRowsCount * 2;
+ if (rowPosition === null &&
+ this._bufferSet.getSize() >= allowedRowsCount) {
+ rowPosition =
+ this._bufferSet.replaceFurthestValuePosition(
+ firstViewportRowIndex,
+ lastViewportRowIndex,
+ rowIndex
+ );
+ }
+ if (rowPosition === null) {
+ // We can't reuse any of existing positions for this row. We have to
+ // create new position
+ rowPosition = this._bufferSet.getNewPositionForValue(rowIndex);
+ this._rows[rowPosition] = rowIndex;
+ } else {
+ // This row already is in the table with rowPosition position or it
+ // can replace row that is in that position
+ this._rows[rowPosition] = rowIndex;
+ }
+ }
+ }
+
+})();
+;
+(function () {
+ BI.Tree = function () {
+ this.root = new BI.Node(BI.UUID());
+ };
+
+ BI.Tree.prototype = {
+ constructor: BI.Tree,
+ addNode: function (node, newNode, index) {
+ if (BI.isNull(newNode)) {
+ this.root.addChild(node, index);
+ } else if (BI.isNull(node)) {
+ this.root.addChild(newNode, index);
+ } else {
+ node.addChild(newNode, index);
+ }
+ },
+
+ isRoot: function (node) {
+ return node === this.root;
+ },
+
+ getRoot: function () {
+ return this.root;
+ },
+
+ clear: function () {
+ this.root.clear();
+ },
+
+ initTree: function (nodes) {
+ var self = this;
+ this.clear();
+ var queue = [];
+ BI.each(nodes, function (i, node) {
+ var n = new BI.Node(node);
+ n.set("data", node);
+ self.addNode(n);
+ queue.push(n);
+ });
+ while (!BI.isEmpty(queue)) {
+ var parent = queue.shift();
+ var node = parent.get("data");
+ BI.each(node.children, function (i, child) {
+ var n = new BI.Node(child);
+ n.set("data", child);
+ queue.push(n);
+ self.addNode(parent, n);
+ })
+ }
+ },
+
+ _toJSON: function (node) {
+ var self = this;
+ var children = [];
+ BI.each(node.getChildren(), function (i, child) {
+ children.push(self._toJSON(child));
+ });
+ return BI.extend({
+ id: node.id
+ }, BI.deepClone(node.get("data")), (children.length > 0 ? {
+ children: children
+ } : {}));
+ },
+
+ toJSON: function (node) {
+ var self = this, result = [];
+ BI.each((node || this.root).getChildren(), function (i, child) {
+ result.push(self._toJSON(child));
+ });
+ return result;
+ },
+
+ _toJSONWithNode: function (node) {
+ var self = this;
+ var children = [];
+ BI.each(node.getChildren(), function (i, child) {
+ children.push(self._toJSONWithNode(child));
+ });
+ return BI.extend({
+ id: node.id
+ }, BI.deepClone(node.get("data")), {
+ node: node
+ }, (children.length > 0 ? {
+ children: children
+ } : {}));
+ },
+
+ toJSONWithNode: function (node) {
+ var self = this, result = [];
+ BI.each((node || this.root).getChildren(), function (i, child) {
+ result.push(self._toJSONWithNode(child));
+ });
+ return result;
+ },
+
+ search: function (root, target, param) {
+ if (!(root instanceof BI.Node)) {
+ return arguments.callee.apply(this, [this.root, root, target]);
+ }
+ var self = this, next = null;
+
+ if (BI.isNull(target)) {
+ return null;
+ }
+ if (BI.isEqual(root[param || "id"], target)) {
+ return root;
+ }
+ BI.any(root.getChildren(), function (i, child) {
+ next = self.search(child, target, param);
+ if (null !== next) {
+ return true;
+ }
+ });
+ return next;
+ },
+
+ _traverse: function (node, callback) {
+ var queue = [];
+ queue.push(node);
+ while (!BI.isEmpty(queue)) {
+ var temp = queue.shift();
+ var b = callback && callback(temp);
+ if (b === false) {
+ break;
+ }
+ if (b === true) {
+ continue;
+ }
+ if (temp != null) {
+ queue = queue.concat(temp.getChildren());
+ }
+ }
+ },
+
+ traverse: function (callback) {
+ this._traverse(this.root, callback);
+ },
+
+ _recursion: function (node, route, callback) {
+ var self = this;
+ return BI.every(node.getChildren(), function (i, child) {
+ var next = BI.clone(route);
+ next.push(child.id);
+ var b = callback && callback(child, next);
+ if (b === false) {
+ return false;
+ }
+ if (b === true) {
+ return true;
+ }
+ return self._recursion(child, next, callback);
+ });
+ },
+
+ recursion: function (callback) {
+ this._recursion(this.root, [], callback);
+ },
+
+ inOrderTraverse: function (callback) {
+ this._inOrderTraverse(this.root, callback);
+ },
+
+ //中序遍历(递归)
+ _inOrderTraverse: function (node, callback) {
+ if (node != null) {
+ this._inOrderTraverse(node.getLeft());
+ callback && callback(node);
+ this._inOrderTraverse(node.getRight());
+ }
+ },
+
+ //中序遍历(非递归)
+ nrInOrderTraverse: function (callback) {
+
+ var stack = [];
+ var node = this.root;
+ while (node != null || !BI.isEmpty(stack)) {
+ while (node != null) {
+ stack.push(node);
+ node = node.getLeft();
+ }
+ node = stack.pop();
+ callback && callback(node);
+ node = node.getRight();
+ }
+ },
+
+ preOrderTraverse: function (callback) {
+ this._preOrderTraverse(this.root, callback);
+ },
+
+ //先序遍历(递归)
+ _preOrderTraverse: function (node, callback) {
+ if (node != null) {
+ callback && callback(node);
+ this._preOrderTraverse(node.getLeft());
+ this._preOrderTraverse(node.getRight());
+ }
+ },
+
+ //先序遍历(非递归)
+ nrPreOrderTraverse: function (callback) {
+
+ var stack = [];
+ var node = this.root;
+
+ while (node != null || !BI.isEmpty(stack)) {
+
+ while (node != null) {
+ callback && callback(node);
+ stack.push(node);
+ node = node.getLeft();
+ }
+ node = stack.pop();
+ node = node.getRight();
+ }
+ },
+
+ postOrderTraverse: function (callback) {
+ this._postOrderTraverse(this.root, callback);
+ },
+
+ //后序遍历(递归)
+ _postOrderTraverse: function (node, callback) {
+ if (node != null) {
+ this._postOrderTraverse(node.getLeft());
+ this._postOrderTraverse(node.getRight());
+ callback && callback(node);
+ }
+ },
+
+ //后续遍历(非递归)
+ nrPostOrderTraverse: function (callback) {
+
+ var stack = [];
+ var node = this.root;
+ var preNode = null;//表示最近一次访问的节点
+
+ while (node != null || !BI.isEmpty(stack)) {
+
+ while (node != null) {
+ stack.push(node);
+ node = node.getLeft();
+ }
+
+ node = BI.last(stack);
+
+ if (node.getRight() == null || node.getRight() == preNode) {
+ callback && callback(node);
+ node = stack.pop();
+ preNode = node;
+ node = null;
+ } else {
+ node = node.getRight();
+ }
+ }
+ }
+ };
+
+ BI.Node = function (id) {
+ if (BI.isObject(id)) {
+ BI.extend(this, id);
+ } else {
+ this.id = id;
+ }
+ this.clear.apply(this, arguments);
+ };
+
+ BI.Node.prototype = {
+ constructor: BI.Node,
+
+ set: function (key, value) {
+ if (BI.isObject(key)) {
+ BI.extend(this, key);
+ return;
+ }
+ this[key] = value;
+ },
+
+ get: function (key) {
+ return this[key];
+ },
+
+ isLeaf: function () {
+ return BI.isEmpty(this.children);
+ },
+
+ getChildren: function () {
+ return this.children;
+ },
+
+ getChildrenLength: function () {
+ return this.children.length;
+ },
+
+ getFirstChild: function () {
+ return BI.first(this.children);
+ },
+
+ getLastChild: function () {
+ return BI.last(this.children);
+ },
+
+ setLeft: function (left) {
+ this.left = left;
+ },
+
+ getLeft: function () {
+ return this.left;
+ },
+
+ setRight: function (right) {
+ this.right = right;
+ },
+
+ getRight: function () {
+ return this.right;
+ },
+
+ setParent: function (parent) {
+ this.parent = parent;
+ },
+
+ getParent: function () {
+ return this.parent;
+ },
+
+ getChild: function (index) {
+ return this.children[index];
+ },
+
+ getChildIndex: function (id) {
+ return BI.findIndex(this.children, function (i, ch) {
+ return ch.get("id") === id;
+ });
+ },
+
+ removeChild: function (id) {
+ this.removeChildByIndex(this.getChildIndex(id));
+ },
+
+ removeChildByIndex: function (index) {
+ var before = this.getChild(index - 1);
+ var behind = this.getChild(index + 1);
+ if (before != null) {
+ before.setRight(behind || null);
+ }
+ if (behind != null) {
+ behind.setLeft(before || null);
+ }
+ this.children.splice(index, 1);
+ },
+
+ removeAllChilds: function () {
+ this.children = [];
+ },
+
+ addChild: function (child, index) {
+ var cur = null;
+ if (BI.isUndefined(index)) {
+ cur = this.children.length - 1;
+ } else {
+ cur = index - 1;
+ }
+ child.setParent(this);
+ if (cur >= 0) {
+ this.getChild(cur).setRight(child);
+ child.setLeft(this.getChild(cur));
+ }
+ if (BI.isUndefined(index)) {
+ this.children.push(child);
+ } else {
+ this.children.splice(index, 0, child);
+ }
+ },
+
+ equals: function (obj) {
+ return this === obj || this.id === obj.id;
+ },
+
+ clear: function () {
+ this.parent = null;
+ this.left = null;
+ this.right = null;
+ this.children = [];
+ }
+ };
+
+ BI.extend(BI.Tree, {
+ transformToArrayFormat: function (nodes, pId) {
+ if (!nodes) return [];
+ var r = [];
+ if (BI.isArray(nodes)) {
+ for (var i = 0, l = nodes.length; i < l; i++) {
+ var node = BI.clone(nodes[i]);
+ node.pId = node.pId == null ? pId : node.pId;
+ delete node.children;
+ r.push(node);
+ if (nodes[i]["children"]) {
+ r = r.concat(BI.Tree.transformToArrayFormat(nodes[i]["children"], node.id));
+ }
+ }
+ } else {
+ var newNodes = BI.clone(nodes);
+ newNodes.pId = newNodes.pId == null ? pId : newNodes.pId;
+ delete newNodes.children;
+ r.push(newNodes);
+ if (nodes["children"]) {
+ r = r.concat(BI.Tree.transformToArrayFormat(nodes["children"], newNodes.id));
+ }
+ }
+ return r;
+ },
+
+ arrayFormat: function (nodes, pId) {
+ if (!nodes) {
+ return [];
+ }
+ var r = [];
+ if (BI.isArray(nodes)) {
+ for (var i = 0, l = nodes.length; i < l; i++) {
+ var node = nodes[i];
+ node.pId = node.pId == null ? pId : node.pId;
+ r.push(node);
+ if (nodes[i]["children"]) {
+ r = r.concat(BI.Tree.arrayFormat(nodes[i]["children"], node.id));
+ }
+ }
+ } else {
+ var newNodes = nodes;
+ newNodes.pId = newNodes.pId == null ? pId : newNodes.pId;
+ r.push(newNodes);
+ if (nodes["children"]) {
+ r = r.concat(BI.Tree.arrayFormat(nodes["children"], newNodes.id));
+ }
+ }
+ return r;
+ },
+
+ transformToTreeFormat: function (sNodes) {
+ var i, l;
+ if (!sNodes) {
+ return [];
+ }
+
+ if (BI.isArray(sNodes)) {
+ var r = [];
+ var tmpMap = [];
+ for (i = 0, l = sNodes.length; i < l; i++) {
+ if (BI.isNull(sNodes[i].id)) {
+ return sNodes;
+ }
+ tmpMap[sNodes[i].id] = BI.clone(sNodes[i]);
+ }
+ for (i = 0, l = sNodes.length; i < l; i++) {
+ if (tmpMap[sNodes[i].pId] && sNodes[i].id !== sNodes[i].pId) {
+ if (!tmpMap[sNodes[i].pId].children) {
+ tmpMap[sNodes[i].pId].children = [];
+ }
+ tmpMap[sNodes[i].pId].children.push(tmpMap[sNodes[i].id]);
+ } else {
+ r.push(tmpMap[sNodes[i].id]);
+ }
+ delete tmpMap[sNodes[i].id].pId;
+ }
+ return r;
+ } else {
+ return [sNodes];
+ }
+ },
+
+ treeFormat: function (sNodes) {
+ var i, l;
+ if (!sNodes) {
+ return [];
+ }
+
+ if (BI.isArray(sNodes)) {
+ var r = [];
+ var tmpMap = [];
+ for (i = 0, l = sNodes.length; i < l; i++) {
+ if (BI.isNull(sNodes[i].id)) {
+ return sNodes;
+ }
+ tmpMap[sNodes[i].id] = sNodes[i];
+ }
+ for (i = 0, l = sNodes.length; i < l; i++) {
+ if (tmpMap[sNodes[i].pId] && sNodes[i].id !== sNodes[i].pId) {
+ if (!tmpMap[sNodes[i].pId].children) {
+ tmpMap[sNodes[i].pId].children = [];
+ }
+ tmpMap[sNodes[i].pId].children.push(tmpMap[sNodes[i].id]);
+ } else {
+ r.push(tmpMap[sNodes[i].id]);
+ }
+ }
+ return r;
+ } else {
+ return [sNodes];
+ }
+ },
+
+ traversal: function (array, callback) {
+ if (BI.isNull(array)) {
+ return;
+ }
+ var self = this;
+ BI.any(array, function (i, item) {
+ if (callback(i, item) === false) {
+ return true;
+ }
+ self.traversal(item.children, callback);
+ })
+ }
+ })
+})();//向量操作
+BI.Vector = function (x, y) {
+ this.x = x;
+ this.y = y;
+};
+BI.Vector.prototype = {
+ constructor: BI.Vector,
+ cross: function (v) {
+ return (this.x * v.y - this.y * v.x);
+ },
+ length: function (v) {
+ return (Math.sqrt(this.x * v.x + this.y * v.y));
+ }
+};
+BI.Region = function (x, y, w, h) {
+ this.x = x;
+ this.y = y;
+ this.w = w;
+ this.h = h;
+};
+BI.Region.prototype = {
+ constructor: BI.Region,
+ //判断两个区域是否相交,若相交,则要么顶点互相包含,要么矩形边界(或对角线)相交
+ isIntersects: function (obj) {
+ if (this.isPointInside(obj.x, obj.y) ||
+ this.isPointInside(obj.x + obj.w, obj.y) ||
+ this.isPointInside(obj.x, obj.y + obj.h) ||
+ this.isPointInside(obj.x + obj.w, obj.y + obj.h)) {
+ return true;
+ } else if (obj.isPointInside(this.x, this.y) ||
+ obj.isPointInside(this.x + this.w, this.y) ||
+ obj.isPointInside(this.x, this.y + this.h) ||
+ obj.isPointInside(this.x + this.w, this.y + this.h)) {
+ return true;
+ } else if (obj.x != null && obj.y != null)//判断矩形对角线相交 |v1 X v2||v1 X v3| < 0
+ {
+ var vector1 = new BI.Vector(this.w, this.h);//矩形对角线向量
+ var vector2 = new BI.Vector(obj.x - this.x, obj.y - this.y);
+ var vector3 = new BI.Vector(vector2.x + obj.w, vector2.y + obj.h);
+ if ((vector1.cross(vector2) * vector1.cross(vector3)) < 0) {
+ return true;
+ }
+ }
+ return false;
+ },
+ //判断一个点是否在这个区域内部
+ isPointInside: function (x, y) {
+ if (this.x == null || this.y == null) {
+ return false;
+ }
+ if (x >= this.x && x <= this.x + this.w && y >= this.y && y <= this.y + this.h) {
+ return true;
+ }
+ return false;
+ },
+ //返回区域的重心,因为是矩形所以返回中点
+ getPosition: function () {
+ var pos = [];
+ pos.push(this.x + this.w / 2);
+ pos.push(this.y + this.h / 2);
+ return pos;
+ }
+};;
+!(function (BI) {
+
+ if (BI.isIE()) {
+ XMLSerializer = null;
+ DOMParser = null;
+ }
+
+
+ var XML = {
+ Document: {
+ NodeType: {
+ ELEMENT: 1,
+ ATTRIBUTE: 2,
+ TEXT: 3,
+ CDATA_SECTION: 4,
+ ENTITY_REFERENCE: 5,
+ ENTITY: 6,
+ PROCESSING_INSTRUCTION: 7,
+ COMMENT: 8,
+ DOCUMENT: 9,
+ DOCUMENT_TYPE: 10,
+ DOCUMENT_FRAGMENT: 11,
+ NOTATION: 12
+ }
+ }
+ };
+
+ XML.ResultType = {
+ single: 'single',
+ array: 'array'
+ };
+
+ XML.fromString = function (xmlStr) {
+ try {
+ var parser = new DOMParser();
+ return parser.parseFromString(xmlStr, "text/xml");
+ } catch (e) {
+ var arrMSXML = ["MSXML2.DOMDocument.6.0", "MSXML2.DOMDocument.3.0"];
+ for (var i = 0; i < arrMSXML.length; i++) {
+ try {
+ var xmlDoc = new ActiveXObject(arrMSXML[i]);
+ xmlDoc.setProperty("SelectionLanguage", "XPath");
+ xmlDoc.async = false;
+ xmlDoc.loadXML(xmlStr);
+ return xmlDoc;
+ } catch (xmlError) {
+ }
+ }
+ }
+ };
+
+ XML.toString = function (xmlNode) {
+ if (!BI.isIE()) {
+ var xmlSerializer = new XMLSerializer();
+ return xmlSerializer.serializeToString(xmlNode);
+ } else
+ return xmlNode.xml;
+ };
+
+ XML.getNSResolver = function (str) {
+ if (!str) {
+ return null;
+ }
+ var list = str.split(' ');
+ var namespaces = {};
+ for (var i = 0; i < list.length; i++) {
+ var pair = list[i].split('=');
+ var fix = BI.trim(pair[0]).replace("xmlns:", "");
+ namespaces[fix] = BI.trim(pair[1]).replace(/"/g, "").replace(/'/g, "");
+ }
+ return function (prefix) {
+ return namespaces[prefix];
+ };
+ };
+
+ XML.eval = function (context, xpathExp, resultType, namespaces) {
+ if ((BI.isIE() && ('undefined' === typeof(context.selectSingleNode) || 'undefined' === typeof(context.selectNodes)))) {
+ return XML.eval2(context, xpathExp, resultType, namespaces);
+ } else {
+ if (BI.isIE()) {
+ namespaces = namespaces ? namespaces : "";
+ var doc = (context.nodeType == XML.Document.NodeType.DOCUMENT) ? context : context.ownerDocument;
+ doc.setProperty("SelectionNamespaces", namespaces);
+ var result;
+ if (resultType == this.ResultType.single) {
+ result = context.selectSingleNode(xpathExp);
+ } else {
+ result = context.selectNodes(xpathExp) || [];
+ }
+ doc.setProperty("SelectionNamespaces", "");
+ return result;
+ } else {
+ var node = context;
+ var xmlDoc = (context.nodeName.indexOf("document") == -1) ? context.ownerDocument : context;
+ var retType = (resultType == this.ResultType.single) ? XPathResult.FIRST_ORDERED_NODE_TYPE : XPathResult.ANY_TYPE;
+ var col = xmlDoc.evaluate(xpathExp, node, XML.getNSResolver(namespaces), retType, null);
+
+ if (retType == XPathResult.FIRST_ORDERED_NODE_TYPE) {
+ return col.singleNodeValue;
+ } else {
+ var thisColMemb = col.iterateNext();
+ var rowsCol = [];
+ while (thisColMemb) {
+ rowsCol[rowsCol.length] = thisColMemb;
+ thisColMemb = col.iterateNext();
+ }
+ return rowsCol;
+ }
+ }
+ }
+ };
+
+ XML.eval2 = function (context, xpathExp, resultType, namespaces) {
+ if (resultType !== "single" && resultType !== undefined && resultType !== null) {
+ throw new Error("justep.SimpleXML.eval only be resultType='single', not" + resultType);
+ }
+
+ if (context === null || context === undefined || xpathExp === null || xpathExp === undefined) {
+ return context;
+ }
+
+ if (context.nodeType == XML.Document.NodeType.DOCUMENT) {
+ context = context.documentElement;
+ }
+
+ var childs, i;
+ if (xpathExp.indexOf("/") != -1) {
+ var items = xpathExp.split("/");
+ var isAbs = xpathExp.substring(0, 1) == "/";
+ for (i = 0; i < items.length; i++) {
+ var item = items[i];
+ if (item === "") {
+ continue;
+ } else {
+ var next = null;
+ var ii = i + 1;
+ for (; ii < items.length; ii++) {
+ if (next === null) {
+ next = items[ii];
+ } else {
+ next = next + "/" + items[ii];
+ }
+ }
+
+ if (item == ".") {
+ return this.eval(context, next, resultType);
+
+ } else if (item == "..") {
+ return this.eval2(context.parentNode, next, resultType);
+
+ } else if (item == "*") {
+ if (isAbs) {
+ return this.eval2(context, next, resultType);
+
+ } else {
+ childs = context.childNodes;
+ for (var j = 0; j < childs.length; j++) {
+ var tmp = this.eval2(childs[j], next, resultType);
+ if (tmp !== null) {
+ return tmp;
+ }
+ }
+ return null;
+ }
+
+ } else {
+ if (isAbs) {
+ if (context.nodeName == item) {
+ return this.eval2(context, next, resultType);
+ } else {
+ return null;
+ }
+ } else {
+ var child = this.getChildByName(context, item);
+ if (child !== null) {
+ return this.eval2(child, next, resultType);
+ } else {
+ return null;
+ }
+
+ }
+ }
+
+ }
+ }
+
+ return null;
+
+ } else {
+ if ("text()" == xpathExp) {
+ childs = context.childNodes;
+ for (i = 0; i < childs.length; i++) {
+ if (childs[i].nodeType == XML.Document.NodeType.TEXT) {
+ return childs[i];
+ }
+ }
+ return null;
+ } else {
+ return this.getChildByName(context, xpathExp);
+ }
+ }
+ };
+
+ XML.getChildByName = function (context, name) {
+ if (context === null || context === undefined || name === null || name === undefined) {
+ return null;
+ }
+
+ if (context.nodeType == XML.Document.NodeType.DOCUMENT) {
+ context = context.documentElement;
+ }
+
+ var childs = context.childNodes;
+ for (var i = 0; i < childs.length; i++) {
+ if (childs[i].nodeType == XML.Document.NodeType.ELEMENT && (childs[i].nodeName == name || name == "*")) {
+ return childs[i];
+ }
+ }
+
+ return null;
+ };
+
+ XML.appendChildren = function (context, xpathExp, nodes, isBefore) {
+ nodes = (typeof nodes.length != "undefined") ? nodes : [nodes];
+ var finded = this.eval(context, xpathExp);
+ var count = finded.length;
+ for (var i = 0; i < count; i++) {
+ if (isBefore && finded[i].firstNode) {
+ this._insertBefore(finded[i], nodes, finded[i].firstNode);
+ } else {
+ for (var j = 0; j < nodes.length; j++) {
+ finded[i].appendChild(nodes[j]);
+ }
+ }
+ }
+ return count;
+ };
+
+ XML.removeNodes = function (context, xpathExp) {
+ var nodes = this.eval(context, xpathExp);
+ for (var i = 0; i < nodes.length; i++) {
+ nodes[i].parentNode.removeChild(nodes[i]);
+ }
+ };
+
+ XML._insertBefore = function (parent, newchildren, refchild) {
+ for (var i = 0; i < newchildren.length; i++) {
+ parent.insertBefore(newchildren[i], refchild);
+ }
+ };
+
+ XML.insertNodes = function (context, xpathExp, nodes, isBefore) {
+ nodes = (typeof nodes.length != "undefined") ? nodes : [nodes];
+ var finded = this.eval(context, xpathExp);
+ var count = finded.length;
+ for (var i = 0; i < count; i++) {
+ var refnode = (isBefore) ? finded[i] : finded[i].nextSibling;
+ this._insertBefore(finded[i].parentNode, nodes, refnode);
+ }
+ return count;
+ };
+
+ XML.replaceNodes = function (context, xpathExp, nodes) {
+ nodes = (typeof nodes.length != "undefined") ? nodes : [nodes];
+ var finded = this.eval(context, xpathExp);
+ var count = finded.length;
+ for (var i = 0; i < count; i++) {
+ var refnode = finded[i];
+ var parent = refnode.parentNode;
+ this._insertBefore(parent, nodes, refnode);
+ parent.removeChild(refnode);
+ }
+ return count;
+ };
+
+ XML.setNodeText = function (context, xpathExp, text) {
+ var finded = this.eval(context, xpathExp, this.ResultType.single);
+ if (finded === null) {
+ return;
+ }
+ if (finded.nodeType == XML.Document.NodeType.ELEMENT) {
+ var textNode = this.eval(finded, "./text()", this.ResultType.single);
+ if (!textNode) {
+ textNode = finded.ownerDocument.createTextNode("");
+ finded.appendChild(textNode);
+ }
+ textNode.nodeValue = text;
+ } else {
+ finded.nodeValue = text;
+ }
+ return;
+ };
+
+ XML.getNodeText = function (context, xpathExp, defaultValue) {
+ var finded = xpathExp ? this.eval(context, xpathExp, this.ResultType.single) : context;
+ if (finded && (finded.nodeType == XML.Document.NodeType.ELEMENT)) {
+ finded = this.eval(finded, "./text()", this.ResultType.single);
+ }
+ return (finded && finded.nodeValue) ? "" + finded.nodeValue : (defaultValue !== undefined) ? defaultValue : null;
+ };
+
+ XML.Namespaces = {
+ XMLSCHEMA: "http://www.w3.org/2001/XMLSchema#",
+ XMLSCHEMA_STRING: "http://www.w3.org/2001/XMLSchema#String",
+ XMLSCHEMA_LONG: "http://www.w3.org/2001/XMLSchema#Long",
+ XMLSCHEMA_INTEGER: 'http://www.w3.org/2001/XMLSchema#Integer',
+ XMLSCHEMA_FLOAT: 'http://www.w3.org/2001/XMLSchema#Float',
+ XMLSCHEMA_DOUBLE: 'http://www.w3.org/2001/XMLSchema#Double',
+ XMLSCHEMA_DECIMAL: 'http://www.w3.org/2001/XMLSchema#Decimal',
+ XMLSCHEMA_DATE: 'http://www.w3.org/2001/XMLSchema#Date',
+ XMLSCHEMA_TIME: 'http://www.w3.org/2001/XMLSchema#Time',
+ XMLSCHEMA_DATETIME: 'http://www.w3.org/2001/XMLSchema#DateTime',
+ XMLSCHEMA_BOOLEAN: 'http://www.w3.org/2001/XMLSchema#Boolean',
+ XMLSCHEMA_SYMBOL: 'http://www.w3.org/2001/XMLSchema#Symbol',
+ JUSTEPSCHEMA: "http://www.justep.com/xbiz#",
+ RDF: "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
+ JUSTEP: "http://www.justep.com/x5#",
+ 'get': function (type) {
+ type = type ? type.toLowerCase() : "string";
+ if ("string" == type) {
+ return XML.Namespaces.XMLSCHEMA_STRING;
+ }
+ else if ("integer" == type) {
+ return XML.Namespaces.XMLSCHEMA_INTEGER;
+ }
+ else if ("long" == type) {
+ return XML.Namespaces.XMLSCHEMA_LONG;
+ }
+ else if ("float" == type) {
+ return XML.Namespaces.XMLSCHEMA_FLOAT;
+ }
+ else if ("double" == type) {
+ return XML.Namespaces.XMLSCHEMA_DOUBLE;
+ }
+ else if ("decimal" == type) {
+ return XML.Namespaces.XMLSCHEMA_DECIMAL;
+ }
+ else if ("date" == type) {
+ return XML.Namespaces.XMLSCHEMA_DATE;
+ }
+ else if ("time" == type) {
+ return XML.Namespaces.XMLSCHEMA_TIME;
+ }
+ else if ("datetime" == type) {
+ return XML.Namespaces.XMLSCHEMA_DATETIME;
+ }
+ else if ("boolean" == type) {
+ return XML.Namespaces.XMLSCHEMA_BOOLEAN;
+ }
+ }
+ };
+})(BI);BI.BehaviorFactory = {
+ createBehavior: function(key, options){
+ var behavior;
+ switch (key){
+ case "highlight":
+ behavior = BI.HighlightBehavior;
+ break;
+ case "redmark":
+ behavior = BI.RedMarkBehavior;
+ break;
+ }
+ return new behavior(options);
+ }
+}
+
+/**
+ * guy
+ * 行为控件
+ * @class BI.Behavior
+ * @extends BI.OB
+ */
+BI.Behavior = BI.inherit(BI.OB, {
+ _defaultConfig: function() {
+ return BI.extend(BI.Behavior.superclass._defaultConfig.apply(this, arguments), {
+ rule: function(){return true;}
+ });
+ },
+
+ _init : function() {
+ BI.Behavior.superclass._init.apply(this, arguments);
+
+ },
+
+ doBehavior: function(){
+
+ }
+});/**
+ * 布局容器类
+ * @class BI.Layout
+ * @extends BI.Widget
+ *
+ * @cfg {JSON} options 配置属性
+ * @cfg {Boolean} [options.scrollable=false] 子组件超出容器边界之后是否会出现滚动条
+ * @cfg {Boolean} [options.scrollx=false] 子组件超出容器边界之后是否会出现横向滚动条
+ * @cfg {Boolean} [options.scrolly=false] 子组件超出容器边界之后是否会出现纵向滚动条
+ */
+BI.Layout = BI.inherit(BI.Widget, {
+ props: function () {
+ return {
+ scrollable: null, //true, false, null
+ scrollx: false, //true, false
+ scrolly: false, //true, false
+ items: []
+ };
+ },
+
+ render: function () {
+ this._init4Margin();
+ this._init4Scroll();
+ },
+
+ _init4Margin: function () {
+ if (this.options.top) {
+ this.element.css('top', this.options.top);
+ }
+ if (this.options.left) {
+ this.element.css('left', this.options.left);
+ }
+ if (this.options.bottom) {
+ this.element.css('bottom', this.options.bottom);
+ }
+ if (this.options.right) {
+ this.element.css('right', this.options.right);
+ }
+ },
+
+ _init4Scroll: function () {
+ switch (this.options.scrollable) {
+ case true:
+ this.element.css("overflow", "auto");
+ break;
+ case false:
+ this.element.css("overflow", "hidden");
+ break;
+ default :
+ break;
+ }
+ if (this.options.scrollx) {
+ this.element.css({
+ "overflow-x": "auto",
+ "overflow-y": "hidden"
+ });
+ }
+ if (this.options.scrolly) {
+ this.element.css({
+ "overflow-x": "hidden",
+ "overflow-y": "auto"
+ });
+ }
+ },
+
+ _mountChildren: function () {
+ var self = this;
+ var frag = document.createDocumentFragment();
+ var hasChild = false;
+ BI.each(this._children, function (i, widget) {
+ if (widget.element !== self.element) {
+ frag.appendChild(widget.element[0]);
+ hasChild = true;
+ }
+ });
+ if (hasChild === true) {
+ this.element.append(frag);
+ }
+ },
+
+ _getChildName: function (index) {
+ return index + "";
+ },
+
+ _addElement: function (i, item) {
+ var self = this, w;
+ if (!this.hasWidget(this._getChildName(i))) {
+ w = BI.createWidget(item);
+ 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);
+ }
+ });
+ });
+ this.addWidget(this._getChildName(i), w);
+ } else {
+ w = this.getWidgetByName(this._getChildName(i));
+ }
+ return w;
+ },
+
+ _getOptions: function (item) {
+ if (item instanceof BI.Widget) {
+ item = item.options;
+ }
+ item = BI.stripEL(item);
+ if (item instanceof BI.Widget) {
+ item = item.options;
+ }
+ return item;
+ },
+
+ _compare: function (item1, item2) {
+ var self = this;
+ return eq(item1, item2);
+
+ //不比较函数
+ function eq(a, b, aStack, bStack) {
+ if (a === b) {
+ return a !== 0 || 1 / a === 1 / b;
+ }
+ if (a == null || b == null) {
+ return a === b;
+ }
+ var className = Object.prototype.toString.call(a);
+ switch (className) {
+ case '[object RegExp]':
+ case '[object String]':
+ return '' + a === '' + b;
+ case '[object Number]':
+ if (+a !== +a) {
+ return +b !== +b;
+ }
+ return +a === 0 ? 1 / +a === 1 / b : +a === +b;
+ case '[object Date]':
+ case '[object Boolean]':
+ return +a === +b;
+ }
+
+ var areArrays = className === '[object Array]';
+ if (!areArrays) {
+ if (BI.isFunction(a) && BI.isFunction(b)) {
+ return true;
+ }
+ a = self._getOptions(a);
+ b = self._getOptions(b);
+ }
+
+ aStack = aStack || [];
+ bStack = bStack || [];
+ var length = aStack.length;
+ while (length--) {
+ if (aStack[length] === a) {
+ return bStack[length] === b;
+ }
+ }
+
+ aStack.push(a);
+ bStack.push(b);
+
+ if (areArrays) {
+ length = a.length;
+ if (length !== b.length) {
+ return false;
+ }
+ while (length--) {
+ if (!eq(a[length], b[length], aStack, bStack)) {
+ return false;
+ }
+ }
+ } else {
+ var keys = _.keys(a), key;
+ length = keys.length;
+ if (_.keys(b).length !== length) {
+ return false;
+ }
+ while (length--) {
+ key = keys[length];
+ if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) {
+ return false;
+ }
+ }
+ }
+ aStack.pop();
+ bStack.pop();
+ return true;
+ }
+ },
+
+ _getWrapper: function () {
+ return this.element;
+ },
+
+ _addItemAt: function (index, item) {
+ for (var i = this.options.items.length; i > index; i--) {
+ this._children[this._getChildName(i)] = this._children[this._getChildName(i - 1)];
+ }
+ delete this._children[this._getChildName(index)];
+ this.options.items.splice(index, 0, item);
+ },
+
+ _removeItemAt: function (index) {
+ for (var i = index; i < this.options.items.length - 1; i++) {
+ this._children[this._getChildName(i)] = this._children[this._getChildName(i + 1)];
+ }
+ delete this._children[this._getChildName(this.options.items.length - 1)];
+ this.options.items.splice(index, 1);
+ },
+
+ /**
+ * 添加一个子组件到容器中
+ * @param {JSON/BI.Widget} item 子组件
+ */
+ addItem: function (item) {
+ return this.addItemAt(this.options.items.length, item);
+ },
+
+ prependItem: function (item) {
+ return this.addItemAt(0, item);
+ },
+
+ addItemAt: function (index, item) {
+ if (index < 0 || index > this.options.items.length) {
+ return;
+ }
+ this._addItemAt(index, item);
+ var w = this._addElement(index, item);
+ if (index > 0) {
+ this._children[this._getChildName(index - 1)].element.after(w.element);
+ } else {
+ w.element.prependTo(this._getWrapper());
+ }
+ w._mount();
+ return w;
+ },
+
+ 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)) {
+ child && deleted.push(child);
+ } else {
+ newChildren[this._getChildName(newItems.length)] = child;
+ newItems.push(this.options.items[i]);
+ }
+ }
+ this.options.items = newItems;
+ this._children = newChildren;
+ BI.each(deleted, function (i, c) {
+ c._destroy();
+ });
+ },
+
+ updateItemAt: function (index, item) {
+ if (index < 0 || index > this.options.items.length - 1) {
+ return;
+ }
+
+ var child = this._children[this._getChildName(index)];
+ var updated;
+ if (updated = child.update(this._getOptions(item))) {
+ return updated;
+ }
+ var del = this._children[this._getChildName(index)];
+ delete this._children[this._getChildName(index)];
+ this.options.items.splice(index, 1);
+ var w = this._addElement(index, item);
+ this.options.items.splice(index, 0, item);
+ this._children[this._getChildName(index)] = w;
+ if (index > 0) {
+ this._children[this._getChildName(index - 1)].element.after(w.element);
+ } else {
+ w.element.prependTo(this._getWrapper());
+ }
+ del._destroy();
+ w._mount();
+ },
+
+ addItems: function (items) {
+ var self = this, o = this.options;
+ var fragment = document.createDocumentFragment();
+ var added = [];
+ BI.each(items, function (i, item) {
+ var w = self._addElement(o.items.length, item);
+ self._children[self._getChildName(o.items.length)] = w;
+ o.items.push(item);
+ added.push(w);
+ fragment.appendChild(w.element[0]);
+ });
+ this._getWrapper().append(fragment);
+ BI.each(added, function (i, w) {
+ w._mount();
+ })
+ },
+
+ prependItems: function (items) {
+ var self = this;
+ items = items || [];
+ var fragment = document.createDocumentFragment();
+ var added = [];
+ for (var i = items.length - 1; i >= 0; i--) {
+ this._addItemAt(0, items[i]);
+ var w = this._addElement(0, items[i]);
+ self._children[self._getChildName(0)] = w;
+ this.options.items.unshift(items[i]);
+ added.push(w);
+ fragment.appendChild(w.element[0]);
+ }
+ this._getWrapper().prepend(fragment);
+ BI.each(added, function (i, w) {
+ w._mount();
+ })
+ },
+
+ getValue: function () {
+ var self = this, value = [], child;
+ BI.each(this.options.items, function (i) {
+ 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, child;
+ BI.each(this.options.items, function (i) {
+ if (child = self._children[self._getChildName(i)]) {
+ child.setValue(v);
+ }
+ })
+ },
+
+ setText: function (v) {
+ var self = this, child;
+ BI.each(this.options.items, function (i) {
+ if (child = self._children[self._getChildName(i)]) {
+ child.setText(v);
+ }
+ })
+ },
+
+ update: function (item) {
+ var o = this.options;
+ 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;
+ }
+ }
+ if (o.items.length > items.length) {
+ 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) {
+ w._destroy();
+ })
+ } else if (items.length > o.items.length) {
+ for (i = o.items.length; i < items.length; i++) {
+ this.addItemAt(i, items[i]);
+ }
+ }
+ return updated;
+ },
+
+ stroke: function (items) {
+ var self = this;
+ BI.each(items, function (i, item) {
+ if (!!item) {
+ self._addElement(i, item);
+ }
+ });
+ },
+
+ removeWidget: function (nameOrWidget) {
+ var removeIndex;
+ if (BI.isWidget(nameOrWidget)) {
+ BI.each(this._children, function (name, child) {
+ if (child === nameOrWidget) {
+ removeIndex = name;
+ }
+ })
+ } else {
+ removeIndex = nameOrWidget;
+ }
+ if (removeIndex) {
+ this._removeItemAt(removeIndex | 0);
+ }
+ },
+
+ empty: function () {
+ BI.Layout.superclass.empty.apply(this, arguments);
+ 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 || [];
+ if (this._isMounted) {
+ this.update({items: items});
+ return;
+ }
+ this.options.items = items;
+ this.stroke(items);
+ },
+
+ resize: function () {
+
+ }
+});
+BI.shortcut('bi.layout', BI.Layout);/**
+ * guy
+ * 由一个元素切换到另一个元素的行为
+ * @class BI.Action
+ * @extends BI.OB
+ * @abstract
+ */
+BI.Action = BI.inherit(BI.OB, {
+ _defaultConfig: function() {
+ return BI.extend(BI.Action.superclass._defaultConfig.apply(this, arguments), {
+ src: null,
+ tar: null
+ });
+ },
+
+ _init : function() {
+ BI.Action.superclass._init.apply(this, arguments);
+ },
+
+ actionPerformed: function(src, tar, callback){
+
+ },
+
+ actionBack: function(tar, src, callback){
+
+ }
+});
+
+BI.ActionFactory = {
+ createAction: function(key, options){
+ var action;
+ switch (key){
+ case "show":
+ action = BI.ShowAction;
+ break;
+ }
+ return new action(options);
+ }
+}/**
+ * guy
+ * 由一个元素切换到另一个元素的行为
+ * @class BI.ShowAction
+ * @extends BI.Action
+ */
+BI.ShowAction = BI.inherit(BI.Action, {
+ _defaultConfig: function () {
+ return BI.extend(BI.ShowAction.superclass._defaultConfig.apply(this, arguments), {});
+ },
+
+ _init: function () {
+ BI.ShowAction.superclass._init.apply(this, arguments);
+ },
+
+ actionPerformed: function (src, tar, callback) {
+ tar = tar || this.options.tar;
+ tar.setVisible(true);
+ callback && callback();
+ },
+
+ actionBack: function (tar, src, callback) {
+ tar = tar || this.options.tar;
+ tar.setVisible(false);
+ callback && callback();
+ }
+});/**
+ * @class BI.FloatSection
+ * @extends BI.View
+ * @abstract
+ */
+BI.FloatSection = BI.inherit(BI.View, {
+ _init : function() {
+ BI.FloatSection.superclass._init.apply(this, arguments);
+ var self = this;
+ var flatten = ["_init", "_defaultConfig", "_vessel", "_render", "getName", "listenEnd", "local", "refresh", "load", "change"];
+ flatten = BI.makeObject(flatten, true);
+ BI.each(this.constructor.caller.caller.caller.prototype, function (key) {
+ if (flatten[key]) {
+ return;
+ }
+ var f = self[key];
+ if (BI.isFunction(f)) {
+ self[key] = BI.bind(function () {
+ if (this.model._start === true) {
+ this._F.push({f: f, arg: arguments});
+ return;
+ }
+ return f.apply(this, arguments);
+ }, self);
+ }
+ })
+ },
+
+ rebuildNorth : function(north) {
+ return true;
+ },
+ rebuildCenter : function(center) {},
+ rebuildSouth : function(south) {
+ return false;
+ },
+ close: function(){
+ this.notifyParentEnd();
+ this.trigger(BI.PopoverSection.EVENT_CLOSE);
+ },
+ end: function(){
+
+ }
+});
+
+/**
+ * 弹出层
+ * @class BI.PopoverSection
+ * @extends BI.Widget
+ * @abstract
+ */
+BI.PopoverSection = BI.inherit(BI.Widget, {
+ _init : function() {
+ BI.PopoverSection.superclass._init.apply(this, arguments);
+ },
+
+ rebuildNorth : function(north) {
+ return true;
+ },
+ rebuildCenter : function(center) {},
+ rebuildSouth : function(south) {
+ return false;
+ },
+ close: function(){
+ this.fireEvent(BI.PopoverSection.EVENT_CLOSE);
+ },
+ end: function(){
+
+ }
+});
+BI.PopoverSection.EVENT_CLOSE = "EVENT_CLOSE";;(function () {
+ if (!window.BI) {
+ window.BI = {};
+ }
+ function isEmpty(value) {
+ // 判断是否为空值
+ var result = value === "" || value === null || value === undefined;
+ return result;
+ }
+
+ // 判断是否是无效的日期
+ function isInvalidDate(date) {
+ return date == "Invalid Date" || date == "NaN";
+ }
+
+ /**
+ * 科学计数格式
+ */
+ 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 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;
+ }
+
+ /**
+ * 数字格式
+ */
+ function _numberFormat(text, format) {
+ var text = text + '';
+ //数字格式,区分正负数
+ var numMod = format.indexOf(';');
+ if (numMod > -1) {
+ if (text >= 0) {
+ return _numberFormat(text + "", format.substring(0, numMod));
+ } else {
+ return _numberFormat((-text) + "", format.substr(numMod + 1));
+ }
+ }
+ var tp = text.split('.'), fp = format.split('.'),
+ tleft = tp[0] || '', fleft = fp[0] || '',
+ tright = tp[1] || '', fright = fp[1] || '';
+ //百分比,千分比的小数点移位处理
+ if (/[%‰]$/.test(format)) {
+ var paddingZero = /[%]$/.test(format) ? '00' : '000';
+ tright += paddingZero;
+ tleft += tright.substr(0, paddingZero.length);
+ tleft = tleft.replace(/^0+/gi, '');
+ tright = tright.substr(paddingZero.length).replace(/0+$/gi, '');
+ }
+ var right = _dealWithRight(tright, fright);
+ if (right.leftPlus) {
+ //小数点后有进位
+ tleft = parseInt(tleft) + 1 + '';
+
+ tleft = isNaN(tleft) ? '1' : tleft;
+ }
+ right = right.num;
+ var left = _dealWithLeft(tleft, fleft);
+ if (!(/[0-9]/.test(left))) {
+ left = left + '0';
+ }
+ if (!(/[0-9]/.test(right))) {
+ return left + right;
+ } else {
+ return left + '.' + right;
+ }
+ }
+
+ /**
+ * 处理小数点右边小数部分
+ * @param tright 右边内容
+ * @param fright 右边格式
+ * @returns {JSON} 返回处理结果和整数部分是否需要进位
+ * @private
+ */
+ function _dealWithRight(tright, fright) {
+ var right = '', j = 0, i = 0;
+ for (var len = fright.length; i < len; i++) {
+ var ch = fright.charAt(i);
+ var c = tright.charAt(j);
+ switch (ch) {
+ case '0':
+ if (isEmpty(c)) {
+ c = '0';
+ }
+ right += c;
+ j++;
+ break;
+ case '#':
+ right += c;
+ j++;
+ break;
+ default :
+ right += ch;
+ break;
+ }
+ }
+ var rll = tright.substr(j);
+ var result = {};
+ if (!isEmpty(rll) && rll.charAt(0) > 4) {
+ //有多余字符,需要四舍五入
+ result.leftPlus = true;
+ var numReg = right.match(/^[0-9]+/);
+ if (numReg) {
+ var num = numReg[0];
+ var orilen = num.length;
+ var newnum = parseInt(num) + 1 + '';
+ //进位到整数部分
+ if (newnum.length > orilen) {
+ newnum = newnum.substr(1);
+ } else {
+ newnum = String.leftPad(newnum, orilen, '0');
+ result.leftPlus = false;
+ }
+ right = right.replace(/^[0-9]+/, newnum);
+ }
+ }
+ result.num = right;
+ return result;
+ }
+
+ /**
+ * 处理小数点左边整数部分
+ * @param tleft 左边内容
+ * @param fleft 左边格式
+ * @returns {string} 返回处理结果
+ * @private
+ */
+ function _dealWithLeft(tleft, fleft) {
+ var left = '';
+ var j = tleft.length - 1;
+ var combo = -1, last = -1;
+ var i = fleft.length - 1;
+ for (; i >= 0; i--) {
+ var ch = fleft.charAt(i);
+ var c = tleft.charAt(j);
+ switch (ch) {
+ case '0':
+ if (isEmpty(c)) {
+ c = '0';
+ }
+ last = -1;
+ left = c + left;
+ j--;
+ break;
+ case '#':
+ last = i;
+ left = c + left;
+ j--;
+ break;
+ case ',':
+ if (!isEmpty(c)) {
+ //计算一个,分隔区间的长度
+ var com = fleft.match(/,[#0]+/);
+ if (com) {
+ combo = com[0].length - 1;
+ }
+ left = ',' + left;
+ }
+ break;
+ default :
+ left = ch + left;
+ break;
+ }
+ }
+ if (last > -1) {
+ //处理剩余字符
+ var tll = tleft.substr(0, j + 1);
+ left = left.substr(0, last) + tll + left.substr(last);
+ }
+ if (combo > 0) {
+ //处理,分隔区间
+ var res = left.match(/[0-9]+,/);
+ if (res) {
+ res = res[0];
+ var newstr = '', n = res.length - 1 - combo;
+ for (; n >= 0; n = n - combo) {
+ newstr = res.substr(n, combo) + ',' + newstr;
+ }
+ var lres = res.substr(0, n + combo);
+ if (!isEmpty(lres)) {
+ newstr = lres + ',' + newstr;
+ }
+ }
+ 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;
+ };
+
+ /**
+ * 把日期对象按照指定格式转化成字符串
+ *
+ * @example
+ * var date = new Date('Thu Dec 12 2013 00:00:00 GMT+0800');
+ * var result = BI.date2Str(date, 'yyyy-MM-dd');//2013-12-12
+ *
+ * @class BI.date2Str
+ * @param date 日期
+ * @param format 日期格式
+ * @returns {String}
+ */
+ BI.date2Str = function (date, format) {
+ if (!date) {
+ return '';
+ }
+ // O(len(format))
+ var len = format.length, result = '';
+ if (len > 0) {
+ var flagch = format.charAt(0), start = 0, str = flagch;
+ for (var i = 1; i < len; i++) {
+ var ch = format.charAt(i);
+ if (flagch !== ch) {
+ result += compileJFmt({
+ 'char': flagch,
+ 'str': str,
+ 'len': i - start
+ }, date);
+ flagch = ch;
+ start = i;
+ str = flagch;
+ } else {
+ str += ch;
+ }
+ }
+ result += compileJFmt({
+ 'char': flagch,
+ 'str': str,
+ 'len': len - start
+ }, date);
+ }
+ return result;
+
+ function compileJFmt(jfmt, date) {
+ var str = jfmt.str, len = jfmt.len, ch = jfmt['char'];
+ switch (ch) {
+ case 'E': //星期
+ str = Date._DN[date.getDay()];
+ break;
+ case 'y': //年
+ if (len <= 3) {
+ str = (date.getFullYear() + '').slice(2, 4);
+ } else {
+ str = date.getFullYear();
+ }
+ break;
+ case 'M': //月
+ if (len > 2) {
+ str = Date._MN[date.getMonth()];
+ } else if (len < 2) {
+ str = date.getMonth() + 1;
+ } else {
+ str = String.leftPad(date.getMonth() + 1 + '', 2, '0');
+ }
+ break;
+ case 'd': //日
+ if (len > 1) {
+ str = String.leftPad(date.getDate() + '', 2, '0');
+ } else {
+ str = date.getDate();
+ }
+ break;
+ case 'h': //时(12)
+ var hour = date.getHours() % 12;
+ if (hour === 0) {
+ hour = 12;
+ }
+ if (len > 1) {
+ str = String.leftPad(hour + '', 2, '0');
+ } else {
+ str = hour;
+ }
+ break;
+ case 'H': //时(24)
+ if (len > 1) {
+ str = String.leftPad(date.getHours() + '', 2, '0');
+ } else {
+ str = date.getHours();
+ }
+ break;
+ case 'm':
+ if (len > 1) {
+ str = String.leftPad(date.getMinutes() + '', 2, '0');
+ } else {
+ str = date.getMinutes();
+ }
+ break;
+ case 's':
+ if (len > 1) {
+ str = String.leftPad(date.getSeconds() + '', 2, '0');
+ } else {
+ str = date.getSeconds();
+ }
+ break;
+ case 'a':
+ str = date.getHours() < 12 ? 'am' : 'pm';
+ break;
+ case 'z':
+ str = date.getTimezone();
+ break;
+ default:
+ str = jfmt.str;
+ break;
+ }
+ return str;
+ }
+ };
+
+ BI.object2Number = function (value) {
+ if (value == null) {
+ return 0;
+ }
+ if (typeof value == 'number') {
+ return value;
+ } else {
+ var str = value + "";
+ if (str.indexOf(".") === -1) {
+ return parseInt(str);
+ } else {
+ return parseFloat(str);
+ }
+ }
+ };
+
+ BI.object2Date = function (obj) {
+ if (obj == null) {
+ return new Date();
+ }
+ if (obj instanceof Date) {
+ return obj;
+ } else if (typeof obj == 'number') {
+ return new Date(obj);
+ } else {
+ var str = obj + "";
+ str = str.replace(/-/g, '/');
+ var dt = new Date(str);
+ if (!isInvalidDate(dt)) {
+ return dt;
+ }
+
+ return new Date();
+ }
+ };
+
+ BI.object2Time = function (obj) {
+ if (obj == null) {
+ return new Date();
+ }
+ if (obj instanceof Date) {
+ return obj;
+ } else {
+ var str = obj + "";
+ str = str.replace(/-/g, '/');
+ var dt = new Date(str);
+ if (!isInvalidDate(dt)) {
+ return dt;
+ }
+ if (str.indexOf('/') === -1 && str.indexOf(':') !== -1) {
+ dt = new Date("1970/01/01 " + str);
+ if (!isInvalidDate(dt)) {
+ return dt;
+ }
+ }
+ dt = BI.str2Date(str, "HH:mm:ss");
+ if (!isInvalidDate(dt)) {
+ return dt;
+ }
+ return new Date();
+ }
+ };
+})();
+/**
+ * guy
+ *
+ * @class BI.HighlightBehavior
+ * @extends BI.Behavior
+ */
+BI.HighlightBehavior = BI.inherit(BI.Behavior, {
+ _defaultConfig: function () {
+ return BI.extend(BI.HighlightBehavior.superclass._defaultConfig.apply(this, arguments), {});
+ },
+
+ _init: function () {
+ BI.HighlightBehavior.superclass._init.apply(this, arguments);
+
+ },
+
+ doBehavior: function (items) {
+ var args = Array.prototype.slice.call(arguments, 1),
+ o = this.options;
+ BI.each(items, function (i, item) {
+ if (item instanceof BI.Single) {
+ var rule = o.rule(item.getValue(), item);
+
+ function doBe(run) {
+ if (run === true) {
+ item.doHighLight.apply(item, args);
+ } else {
+ item.unHighLight.apply(item, args);
+ }
+ }
+
+ if (BI.isFunction(rule)) {
+ rule(doBe);
+ } else {
+ doBe(rule);
+ }
+ } else {
+ item.doBehavior.apply(item, args);
+ }
+ })
+ }
+});/**
+ * guy
+ * 标红行为
+ * @class BI.RedMarkBehavior
+ * @extends BI.Behavior
+ */
+BI.RedMarkBehavior = BI.inherit(BI.Behavior, {
+ _defaultConfig: function() {
+ return BI.extend(BI.RedMarkBehavior.superclass._defaultConfig.apply(this, arguments), {
+
+ });
+ },
+
+ _init : function() {
+ BI.RedMarkBehavior.superclass._init.apply(this, arguments);
+
+ },
+
+ doBehavior: function(items){
+ var args = Array.prototype.slice.call(arguments, 1),
+ o = this.options;
+ BI.each(items, function(i, item){
+ if(item instanceof BI.Single) {
+ if (o.rule(item.getValue(), item)) {
+ item.doRedMark.apply(item, args);
+ } else {
+ item.unRedMark.apply(item, args);
+ }
+ } else {
+ item.doBehavior.apply(item, args);
+ }
+ })
+ }
+});/**
+ * guy
+ * 控制器
+ * Controller层超类
+ * @class BI.Controller
+ * @extends BI.OB
+ * @abstract
+ */
+BI.Controller = BI.inherit(BI.OB, {
+ _defaultConfig: function() {
+ return BI.extend(BI.Controller.superclass._defaultConfig.apply(this, arguments), {
+
+ })
+ },
+ _init : function() {
+ BI.Controller.superclass._init.apply(this, arguments);
+ },
+
+ destroy: function(){
+
+ }
+});
+BI.Controller.EVENT_CHANGE = "__EVENT_CHANGE__";/**
+ * 广播
+ *
+ * Created by GUY on 2015/12/23.
+ * @class
+ */
+BI.BroadcastController = BI.inherit(BI.Controller, {
+ _defaultConfig: function () {
+ return BI.extend(BI.BroadcastController.superclass._defaultConfig.apply(this, arguments), {});
+ },
+
+ _init: function () {
+ BI.BroadcastController.superclass._init.apply(this, arguments);
+ this._broadcasts = {};
+ },
+
+ on: function (name, fn) {
+ var self = this;
+ if (!this._broadcasts[name]) {
+ this._broadcasts[name] = [];
+ }
+ this._broadcasts[name].push(fn);
+ return function () {
+ self.remove(name, fn);
+ }
+ },
+
+ send: function (name) {
+ var args = [].slice.call(arguments, 1);
+ BI.each(this._broadcasts[name], function (i, fn) {
+ fn.apply(null, args);
+ });
+ },
+
+ 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];
+ }
+ return this;
+ }
+});/**
+ * 气泡图控制器
+ * 控制气泡图的显示方向
+ *
+ * Created by GUY on 2015/8/21.
+ * @class
+ */
+BI.BubblesController = BI.inherit(BI.Controller, {
+ _defaultConfig: function () {
+ return BI.extend(BI.BubblesController.superclass._defaultConfig.apply(this, arguments), {});
+ },
+
+ _const: {
+ bubbleHeight: 35
+ },
+
+ _init: function () {
+ BI.BubblesController.superclass._init.apply(this, arguments);
+ this.bubblesManager = {};
+ this.storeBubbles = {};
+ },
+
+ _createBubble: function (direct, text, height) {
+ return BI.createWidget({
+ type: "bi.bubble",
+ text: text,
+ height: height || 35,
+ direction: direct
+ });
+ },
+
+ _getOffsetLeft: function (name, context, offsetStyle) {
+ var left = 0;
+ if ("center" === offsetStyle) {
+ left = context.element.offset().left + (context.element.bounds().width - this.get(name).element.bounds().width) / 2;
+ if (left < 0) {
+ left = 0;
+ }
+ return left;
+ }
+ if ("right" === offsetStyle) {
+ left = context.element.offset().left + context.element.bounds().width - this.get(name).element.bounds().width;
+ if (left < 0) {
+ left = 0;
+ }
+ return left;
+ }
+ return context.element.offset().left;
+ },
+
+ _getOffsetTop: function (name, context, offsetStyle) {
+ var top = 0;
+ if ("center" === offsetStyle) {
+ top = context.element.offset().top + (context.element.bounds().height - this.get(name).element.bounds().height) / 2;
+ if (top < 0) {
+ top = 0;
+ }
+ return top;
+ } else if ("right" === offsetStyle) {
+ top = context.element.offset().top + context.element.bounds().height - this.get(name).element.bounds().height;
+ if (top < 0) {
+ top = 0;
+ }
+ return top;
+ }
+ return context.element.offset().top;
+ },
+
+ _getLeftPosition: function (name, context, offsetStyle) {
+ var position = $.getLeftPosition(context, this.get(name));
+ position.top = this._getOffsetTop(name, context, offsetStyle);
+ return position;
+ },
+
+ _getBottomPosition: function (name, context, offsetStyle) {
+ var position = $.getBottomPosition(context, this.get(name));
+ position.left = this._getOffsetLeft(name, context, offsetStyle);
+ return position;
+ },
+
+ _getTopPosition: function (name, context, offsetStyle) {
+ var position = $.getTopPosition(context, this.get(name));
+ position.left = this._getOffsetLeft(name, context, offsetStyle);
+ return position;
+ },
+
+ _getRightPosition: function (name, context, offsetStyle) {
+ var position = $.getRightPosition(context, this.get(name));
+ position.top = this._getOffsetTop(name, context, offsetStyle);
+ return position;
+ },
+
+ /**
+ *
+ * @param name
+ * @param text
+ * @param context
+ * @param offsetStyle center, left, right三种类型, 默认left
+ * @returns {BI.BubblesController}
+ */
+ show: function (name, text, context, opt) {
+ opt || (opt = {});
+ var container = opt.container || context;
+ var offsetStyle = opt.offsetStyle || {};
+ if (!this.storeBubbles[name]) {
+ this.storeBubbles[name] = {};
+ }
+ if (!this.storeBubbles[name]["top"]) {
+ this.storeBubbles[name]["top"] = this._createBubble("top", text);
+ }
+ BI.createWidget({
+ type: "bi.absolute",
+ element: container,
+ items: [{
+ el: this.storeBubbles[name]["top"]
+ }]
+ });
+ this.set(name, this.storeBubbles[name]["top"]);
+ var position = this._getTopPosition(name, context, offsetStyle);
+ this.get(name).element.css({left: position.left, top: position.top});
+ this.get(name).invisible();
+ if (!$.isTopSpaceEnough(context, this.get(name))) {
+ if (!this.storeBubbles[name]["left"]) {
+ this.storeBubbles[name]["left"] = this._createBubble("left", text, 30);
+ }
+ BI.createWidget({
+ type: "bi.absolute",
+ element: container,
+ items: [{
+ el: this.storeBubbles[name]["left"]
+ }]
+ });
+ this.set(name, this.storeBubbles[name]["left"]);
+ var position = this._getLeftPosition(name, context, offsetStyle);
+ this.get(name).element.css({left: position.left, top: position.top});
+ this.get(name).invisible();
+ if (!$.isLeftSpaceEnough(context, this.get(name))) {
+ if (!this.storeBubbles[name]["right"]) {
+ this.storeBubbles[name]["right"] = this._createBubble("right", text, 30);
+ }
+ BI.createWidget({
+ type: "bi.absolute",
+ element: container,
+ items: [{
+ el: this.storeBubbles[name]["right"]
+ }]
+ });
+ this.set(name, this.storeBubbles[name]["right"]);
+ var position = this._getRightPosition(name, context, offsetStyle);
+ this.get(name).element.css({left: position.left, top: position.top});
+ this.get(name).invisible();
+ if (!$.isRightSpaceEnough(context, this.get(name))) {
+ if (!this.storeBubbles[name]["bottom"]) {
+ this.storeBubbles[name]["bottom"] = this._createBubble("bottom", text);
+ }
+ BI.createWidget({
+ type: "bi.absolute",
+ element: container,
+ items: [{
+ el: this.storeBubbles[name]["bottom"]
+ }]
+ });
+ this.set(name, this.storeBubbles[name]["bottom"]);
+ var position = this._getBottomPosition(name, context, offsetStyle);
+ this.get(name).element.css({left: position.left, top: position.top});
+ this.get(name).invisible();
+ }
+ }
+ }
+ this.get(name).setText(text);
+ this.get(name).visible();
+ return this;
+ },
+
+ hide: function (name) {
+ if (!this.has(name)) {
+ return this;
+ }
+ this.get(name).invisible();
+ return this;
+ },
+
+ add: function (name, bubble) {
+ if (this.has(name)) {
+ return this;
+ }
+ this.set(name, bubble);
+ return this;
+ },
+
+ get: function (name) {
+ return this.bubblesManager[name];
+ },
+
+ set: function (name, bubble) {
+ this.bubblesManager[name] = bubble;
+ },
+
+ has: function (name) {
+ return this.bubblesManager[name] != null;
+ },
+
+ remove: function (name) {
+ if (!this.has(name)) {
+ return this;
+ }
+ BI.each(this.storeBubbles[name], function (dir, bubble) {
+ bubble.destroy();
+ });
+ delete this.storeBubbles[name];
+ delete this.bubblesManager[name];
+ return this;
+ }
+});/**
+ * guy
+ * FloatBox弹出层控制器, z-index在100w层级
+ * @class BI.FloatBoxController
+ * @extends BI.Controller
+ */
+BI.FloatBoxController = BI.inherit(BI.Controller, {
+ _defaultConfig: function () {
+ return BI.extend(BI.FloatBoxController.superclass._defaultConfig.apply(this, arguments), {
+ modal: true, // 模态窗口
+ render: "body"
+ });
+ },
+
+ _init: function () {
+ BI.FloatBoxController.superclass._init.apply(this, arguments);
+ this.modal = this.options.modal;
+ this.floatManager = {};
+ this.floatLayer = {};
+ this.floatContainer = {};
+ this.floatOpened = {};
+ this.zindex = BI.zIndex_floatbox;
+ this.zindexMap = {};
+ },
+
+ _check: function (name) {
+ return BI.isNotNull(this.floatManager[name]);
+ },
+
+ create: function (name, section, options) {
+ if (this._check(name)) {
+ return this;
+ }
+ var floatbox = BI.createWidget({
+ type: "bi.float_box"
+ }, options);
+ floatbox.populate(section);
+ this.add(name, floatbox, options);
+ return this;
+ },
+
+ add: function (name, floatbox, options) {
+ var self = this;
+ options || (options = {});
+ if (this._check(name)) {
+ return this;
+ }
+ this.floatContainer[name] = BI.createWidget({
+ type: "bi.absolute",
+ cls: "bi-popup-view",
+ items: [{
+ el: (this.floatLayer[name] = BI.createWidget({
+ type: 'bi.absolute',
+ items: [floatbox]
+ })),
+ left: 0,
+ right: 0,
+ top: 0,
+ bottom: 0
+ }]
+ });
+ this.floatManager[name] = floatbox;
+ (function (key) {
+ floatbox.on(BI.FloatBox.EVENT_FLOAT_BOX_CLOSED, function () {
+ self.close(key);
+ })
+ })(name);
+ BI.createWidget({
+ type: "bi.absolute",
+ element: options.container || this.options.render,
+ items: [{
+ el: this.floatContainer[name],
+ left: 0,
+ right: 0,
+ top: 0,
+ bottom: 0
+ }]
+ });
+ return this;
+ },
+
+ open: function (name) {
+ if (!this._check(name)) {
+ return this;
+ }
+ if (!this.floatOpened[name]) {
+ this.floatOpened[name] = true;
+ 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"
+ });
+ }
+ return this;
+ },
+
+ close: function (name) {
+ if (!this._check(name)) {
+ return this;
+ }
+ if (this.floatOpened[name]) {
+ delete this.floatOpened[name];
+ this.floatContainer[name].invisible();
+ this.modal && this.floatContainer[name].element.__releaseZIndexMask__(this.zindexMap[name]);
+ }
+ return this;
+ },
+
+ get: function (name) {
+ return this.floatManager[name];
+ },
+
+ remove: function (name) {
+ if (!this._check(name)) {
+ return this;
+ }
+ this.floatContainer[name].destroy();
+ this.modal && this.floatContainer[name].element.__releaseZIndexMask__(this.zindexMap[name]);
+ delete this.floatManager[name];
+ delete this.floatLayer[name];
+ delete this.zindexMap[name];
+ delete this.floatContainer[name];
+ delete this.floatOpened[name];
+ return this;
+ }
+});/**
+ * 弹出层面板控制器, z-index在10w层级
+ *
+ * Created by GUY on 2015/6/24.
+ * @class
+ */
+BI.LayerController = BI.inherit(BI.Controller, {
+ _defaultConfig: function () {
+ return BI.extend(BI.LayerController.superclass._defaultConfig.apply(this, arguments), {
+ render: "body"
+ });
+ },
+
+ _init: function () {
+ BI.LayerController.superclass._init.apply(this, arguments);
+ this.layerManager = {};
+ this.layouts = {};
+ this.zindex = BI.zIndex_layer;
+ BI.Resizers.add("layerController" + BI.uniqueId(), BI.bind(this._resize, this));
+ },
+
+ _resize: function () {
+ BI.each(this.layouts, function (i, layer) {
+ if (layer.element.is(":visible")) {
+ layer.element.trigger("__resize__");
+ }
+ })
+ },
+
+ make: function (name, container, op) {
+ if (this.has(name)) {
+ return this.get(name);
+ }
+ op || (op = {});
+ var widget = BI.createWidget((op.render || {}), {
+ type: "bi.layout"
+ });
+ BI.createWidget({
+ type: "bi.absolute",
+ element: container || this.options.render,
+ items: [BI.extend({
+ el: widget
+ }, {
+ top: 0,
+ left: 0,
+ right: 0,
+ bottom: 0
+ }, op.offset)]
+ });
+ this.add(name, widget, widget);
+ return widget;
+ },
+
+ create: function (name, from, op) {
+ if (this.has(name)) {
+ return this.get(name);
+ }
+ op || (op = {});
+ var offset = op.offset || {};
+ var w = from;
+ if (BI.isWidget(from)) {
+ w = from.element;
+ }
+ if (BI.isNotEmptyString(w)) {
+ w = $(w);
+ }
+ if (this.has(name)) {
+ return this.get(name);
+ }
+ var widget = BI.createWidget((op.render || {}), {
+ type: "bi.layout",
+ cls: op.cls
+ });
+ var layout = BI.createWidget({
+ type: "bi.absolute",
+ items: [{
+ el: widget,
+ left: 0,
+ right: 0,
+ top: 0,
+ bottom: 0
+ }]
+ });
+ BI.createWidget({
+ type: "bi.absolute",
+ element: op.container || this.options.render,
+ items: [{
+ el: layout,
+ left: offset.left || 0,
+ right: offset.right || 0,
+ top: offset.top || 0,
+ bottom: offset.bottom || 0
+ }]
+ });
+ if (w) {
+ layout.element.addClass("bi-popup-view");
+ layout.element.css({
+ left: w.offset().left + (offset.left || 0),
+ top: w.offset().top + (offset.top || 0),
+ width: offset.width || (w.outerWidth() - (offset.right || 0)) || "",
+ height: offset.height || (w.outerHeight() - (offset.bottom || 0)) || ""
+ });
+ layout.element.on("__resize__", function () {
+ w.is(":visible") &&
+ layout.element.css({
+ left: w.offset().left + (offset.left || 0),
+ top: w.offset().top + (offset.top || 0),
+ width: offset.width || (w.outerWidth() - (offset.right || 0)) || "",
+ height: offset.height || (w.outerHeight() - (offset.bottom || 0)) || ""
+ });
+ });
+ }
+ this.add(name, widget, layout);
+ return widget;
+ },
+
+ hide: function (name, callback) {
+ if (!this.has(name)) {
+ return this;
+ }
+ this._getLayout(name).invisible();
+ this._getLayout(name).element.hide(0, callback);
+ return this;
+ },
+
+ show: function (name, callback) {
+ if (!this.has(name)) {
+ return this;
+ }
+ this._getLayout(name).visible();
+ this._getLayout(name).element.css("z-index", this.zindex++).show(0, callback).trigger("__resize__");
+ return this;
+ },
+
+ isVisible: function (name) {
+ return this.has(name) && this._getLayout(name).isVisible();
+ },
+
+ add: function (name, layer, layout) {
+ if (this.has(name)) {
+ throw new Error("name is already exist");
+ }
+ layout.setVisible(false);
+ this.layerManager[name] = layer;
+ this.layouts[name] = layout;
+ layout.element.css("z-index", this.zindex++);
+ return this;
+ },
+
+ _getLayout: function (name) {
+ return this.layouts[name];
+ },
+
+ get: function (name) {
+ return this.layerManager[name];
+ },
+
+ has: function (name) {
+ return this.layerManager[name] != null;
+ },
+
+ remove: function (name) {
+ if (!this.has(name)) {
+ return this;
+ }
+ this.layerManager[name].destroy();
+ this.layouts[name].destroy();
+ delete this.layerManager[name];
+ delete this.layouts[name];
+ return this;
+ }
+});/**
+ * 遮罩面板, z-index在1亿层级
+ *
+ * Created by GUY on 2015/6/24.
+ * @class
+ */
+BI.MaskersController = BI.inherit(BI.LayerController, {
+ _defaultConfig: function () {
+ return BI.extend(BI.MaskersController.superclass._defaultConfig.apply(this, arguments), {});
+ },
+
+ _init: function () {
+ BI.MaskersController.superclass._init.apply(this, arguments);
+ this.zindex = BI.zIndex_masker;
+ }
+});/**
+ * window.resize 控制器
+ *
+ * Created by GUY on 2015/6/24.
+ * @class
+ */
+BI.ResizeController = BI.inherit(BI.Controller, {
+ _defaultConfig: function () {
+ return BI.extend(BI.ResizeController.superclass._defaultConfig.apply(this, arguments), {});
+ },
+
+ _init: function () {
+ BI.ResizeController.superclass._init.apply(this, arguments);
+ var self = this;
+ this.resizerManger = {};
+ var fn = BI.debounce(function (ev) {
+ //if (BI.isWindow(ev.target)) {
+ self._resize(ev);
+ //}
+ }, 30);
+ $(window).resize(fn);
+ },
+
+ _resize: function (ev) {
+ BI.each(this.resizerManger, function (key, resizer) {
+ if (resizer instanceof $) {
+ if (resizer.is(":visible")) {
+ resizer.trigger("__resize__");
+ }
+ return;
+ }
+ if (resizer instanceof BI.Layout) {
+ resizer.resize();
+ return;
+ }
+ if (BI.isFunction(resizer)) {
+ resizer(ev);
+ return;
+ }
+ })
+ },
+
+ add: function (name, resizer) {
+ var self = this;
+ if (this.has(name)) {
+ return this;
+ }
+ this.resizerManger[name] = resizer;
+ return function () {
+ self.remove(name);
+ };
+ },
+
+ get: function (name) {
+ return this.resizerManger[name];
+ },
+
+ has: function (name) {
+ return this.resizerManger[name] != null;
+ },
+
+ remove: function (name) {
+ if (!this.has(name)) {
+ return this;
+ }
+ delete this.resizerManger[name];
+ return this;
+ }
+});/**
+ * tooltip控制器
+ * 控制tooltip的显示, 且页面中只有一个tooltip显示
+ *
+ * Created by GUY on 2015/9/8.
+ * @class BI.TooltipsController
+ * @extends BI.Controller
+ */
+BI.TooltipsController = BI.inherit(BI.Controller, {
+ _defaultConfig: function () {
+ return BI.extend(BI.TooltipsController.superclass._defaultConfig.apply(this, arguments), {});
+ },
+
+ _const: {
+ height: 20
+ },
+
+ _init: function () {
+ BI.TooltipsController.superclass._init.apply(this, arguments);
+ this.tooltipsManager = {};
+ this.showingTips = {};//存储正在显示的tooltip
+ },
+
+ _createTooltip: function (text, level) {
+ return BI.createWidget({
+ type: "bi.tooltip",
+ text: text,
+ level: level,
+ stopEvent: true,
+ height: this._const.height
+ });
+ },
+
+ hide: function (name, callback) {
+ if (!this.has(name)) {
+ return this;
+ }
+ delete this.showingTips[name];
+ this.get(name).element.hide(0, callback);
+ this.get(name).invisible();
+ return this;
+ },
+
+ create: function (name, text, level, context) {
+ if (!this.has(name)) {
+ var tooltip = this._createTooltip(text, level);
+ this.add(name, tooltip);
+ BI.createWidget({
+ type: "bi.absolute",
+ element: context || "body",
+ items: [{
+ el: tooltip
+ }]
+ });
+ tooltip.invisible();
+ }
+ return this.get(name);
+ },
+
+ //opt: {container: '', belowMouse: false}
+ show: function (e, name, text, level, context, opt) {
+ opt || (opt = {});
+ var self = this;
+ BI.each(this.showingTips, function (i, tip) {
+ self.hide(i);
+ });
+ this.showingTips = {};
+ if (!this.has(name)) {
+ this.create(name, text, level, opt.container || context);
+ }
+
+ var offset = context.element.offset();
+ var bounds = context.element.bounds();
+
+ var top = offset.top + bounds.height + 5;
+ var tooltip = this.get(name);
+ tooltip.setText(text);
+ tooltip.element.css({
+ left: "0px",
+ top: "0px"
+ });
+ tooltip.visible();
+ tooltip.element.height(tooltip.element[0].scrollHeight);
+ this.showingTips[name] = true;
+ var x = e.pageX || e.clientX, y = (e.pageY || e.clientY) + 15;
+ if (x + tooltip.element.outerWidth() > $("body").outerWidth()) {
+ x -= tooltip.element.outerWidth();
+ }
+ if (y + tooltip.element.outerHeight() > $("body").outerHeight()) {
+ y -= tooltip.element.outerHeight() + 15;
+ top = offset.top - tooltip.element.outerHeight() - 5;
+ !opt.belowMouse && (y = Math.min(y, top));
+ } else {
+ !opt.belowMouse && (y = Math.max(y, top));
+ }
+ tooltip.element.css({
+ left: x < 0 ? 0 : x + "px",
+ top: y < 0 ? 0 : y + "px"
+ });
+ tooltip.element.hover(function () {
+ self.remove(name);
+ context.element.trigger("mouseleave.title" + context.getName());
+ });
+ return this;
+ },
+
+ add: function (name, bubble) {
+ if (this.has(name)) {
+ return this;
+ }
+ this.set(name, bubble);
+ return this;
+ },
+
+ get: function (name) {
+ return this.tooltipsManager[name];
+ },
+
+ set: function (name, bubble) {
+ this.tooltipsManager[name] = bubble;
+ },
+
+ has: function (name) {
+ return this.tooltipsManager[name] != null;
+ },
+
+ remove: function (name) {
+ if (!this.has(name)) {
+ return this;
+ }
+ this.tooltipsManager[name].destroy();
+ delete this.tooltipsManager[name];
+ return this;
+ }
+});/**
+ *
+ * @class BI.FloatBoxRouter
+ * @extends BI.WRouter
+ */
+BI.FloatBoxRouter = BI.inherit(BI.WRouter, {
+ routes: {},
+
+ _init: function () {
+ this.store = {};
+ this.views = {};
+ },
+
+ createView: function (url, modelData, viewData, context) {
+ return BI.Factory.createView(url, this.get(url), modelData || {}, viewData || {}, context)
+ },
+
+ open: function (url, modelData, viewData, context, options) {
+ var self = this, isValid = BI.isKey(modelData);
+ options || (options = {});
+ url = context.rootURL + "/" + url;
+ var data = void 0;
+ if (isValid) {
+ modelData = modelData + "";//避免modelData是数字
+ var keys = modelData.split('.');
+ BI.each(keys, function (i, k) {
+ if (i === 0) {
+ data = context.model.get(k) || {};
+ } else {
+ data = data[k] || {};
+ }
+ });
+ data.id = options.id || keys[keys.length - 1];
+ } else {
+ data = modelData;
+ }
+ BI.extend(data, options.data);
+ if (!this.controller) {
+ this.controller = new BI.FloatBoxController();
+ }
+ if (!this.store[url]) {
+ this.store[url] = BI.createWidget({
+ type: "bi.float_box"
+ }, options);
+ var view = this.createView(url, data, viewData, context);
+ isValid && context.model.addChild(modelData, view.model);
+ view.listenTo(view.model, "destroy", function () {
+ self.remove(url, context);
+ });
+ context.on(BI.Events.UNMOUNT, function () {
+ self.remove(url, context);
+ });
+ this.store[url].populate(view);
+ this.views[url] = view;
+ this.controller.add(url, this.store[url]);
+ context && context.on("end:" + view.cid, function () {
+ BI.nextTick(function () {
+ self.close(url);
+// view.end();
+ (context.listenEnd.apply(context, isValid ? modelData.split('.') : [modelData]) !== false) && context.populate();
+ }, 30)
+ }).on("change:" + view.cid, _.bind(context.notifyParent, context))
+ }
+ this.controller.open(url);
+ this.views[url].populate(data, options.force || true);
+ return this;
+ },
+
+ close: function (url) {
+ if (this.controller) {
+ this.controller.close(url);
+ }
+ return this;
+ },
+
+ remove: function (url, context) {
+ url = context.rootURL + "/" + url;
+ if (this.controller) {
+ this.controller.remove(url);
+ delete this.store[url];
+ this.views[url] && this.views[url].model.destroy();
+ delete this.views[url];
+ }
+ return this;
+ }
+});/**
+ * 统一绑定事件
+ * @type {*|void|Object}
+ */
+BI.EventList = BI.inherit(BI.OB, {
+ _defaultConfig: function() {
+ return BI.extend(BI.EventList.superclass._defaultConfig.apply(this, arguments), {
+ event: "click",
+ callback: BI.emptyFn,
+ handle: "",
+ items:[]
+ });
+ },
+
+ _init : function() {
+ BI.EventList.superclass._init.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ _getHandle: function(item){
+ var handle = this.options.handle ? _.result(item, this.options.handle) : item;
+ return handle.element || handle;
+ },
+
+ populate: function(items){
+ var self = this,
+ event = this.options.event,
+ callback = this.options.callback;
+ BI.nextTick(function(){
+ BI.each(items, function(i, item){
+ var fn = callback(item);
+ BI.isFunction(fn) && (fn = BI.debounce(fn, BI.EVENT_RESPONSE_TIME, true));
+ self._getHandle(item)[event](fn);
+ })
+ })
+
+ }
+});/**
+ * 统一监听jquery事件
+ * @type {*|void|Object}
+ */
+BI.ListenerList = BI.inherit(BI.OB, {
+ _defaultConfig: function() {
+ return BI.extend(BI.ListenerList.superclass._defaultConfig.apply(this, arguments), {
+ event: "click",
+ callback: BI.emptyFn,
+ items:[]
+ });
+ },
+
+ _init : function() {
+ BI.ListenerList.superclass._init.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ _getHandle: function(item){
+ var handle = this.options.handle ? _.result(item, this.options.handle) : item;
+ return handle.element || handle;
+ },
+
+ populate: function(items){
+ var self = this,
+ event = this.options.event,
+ callback = this.options.callback;
+ BI.nextTick(function(){
+ BI.each(items, function(i, item){
+ var fn = callback(item);
+ BI.isFunction(fn) && (fn = BI.debounce(fn, BI.EVENT_RESPONSE_TIME, true));
+ self._getHandle(item).on(event, fn);
+ })
+ })
+ }
+});/**
+ * Created by GUY on 2015/6/25.
+ */
+/**
+ * 统一监听jquery事件
+ * @type {*|void|Object}
+ */
+BI.OffList = BI.inherit(BI.OB, {
+ _defaultConfig: function() {
+ return BI.extend(BI.OffList.superclass._defaultConfig.apply(this, arguments), {
+ event: "click",
+ items:[]
+ });
+ },
+
+ _init : function() {
+ BI.OffList.superclass._init.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ _getHandle: function(item){
+ var handle = this.options.handle ? _.result(item, this.options.handle) : item;
+ return handle.element || handle;
+ },
+
+ populate: function(items){
+ var self = this,
+ event = this.options.event;
+ BI.each(items, function(i, item){
+ self._getHandle(item).off(event);
+ })
+ }
+});/**
+ * 事件集合
+ * @class BI.Events
+ */
+_.extend(BI, {
+ Events: {
+
+ /**
+ * @static
+ * @property keydown事件
+ */
+ KEYDOWN: "_KEYDOWN",
+
+ /**
+ * @static
+ * @property 回撤事件
+ */
+ BACKSPACE: "_BACKSPACE",
+
+ /**
+ * @static
+ * @property 空格事件
+ */
+ SPACE: "_SPACE",
+
+ /**
+ * @static
+ * @property 回车事件
+ */
+ ENTER: "_ENTER",
+
+ /**
+ * @static
+ * @property 确定事件
+ */
+ CONFIRM: '_CONFIRM',
+
+ /**
+ * @static
+ * @property 错误事件
+ */
+ ERROR: '_ERROR',
+
+ /**
+ * @static
+ * @property 暂停事件
+ */
+ PAUSE: '_PAUSE',
+
+ /**
+ * @static
+ * @property destroy事件
+ */
+ DESTROY: '_DESTROY',
+
+ /**
+ * @static
+ * @property 取消挂载事件
+ */
+ UNMOUNT: '_UNMOUNT',
+
+ /**
+ * @static
+ * @property 清除选择
+ */
+ CLEAR: '_CLEAR',
+
+ /**
+ * @static
+ * @property 添加数据
+ */
+ ADD: '_ADD',
+
+ /**
+ * @static
+ * @property 正在编辑状态事件
+ */
+ EDITING: '_EDITING',
+
+ /**
+ * @static
+ * @property 空状态事件
+ */
+ EMPTY: '_EMPTY',
+
+ /**
+ * @static
+ * @property 显示隐藏事件
+ */
+ VIEW: '_VIEW',
+
+ /**
+ * @static
+ * @property 窗体改变大小
+ */
+ RESIZE: "_RESIZE",
+
+ /**
+ * @static
+ * @property 编辑前事件
+ */
+ BEFOREEDIT: '_BEFOREEDIT',
+
+ /**
+ * @static
+ * @property 编辑后事件
+ */
+ AFTEREDIT: '_AFTEREDIT',
+
+ /**
+ * @static
+ * @property 开始编辑事件
+ */
+ STARTEDIT: '_STARTEDIT',
+
+ /**
+ * @static
+ * @property 停止编辑事件
+ */
+ STOPEDIT: '_STOPEDIT',
+
+ /**
+ * @static
+ * @property 值改变事件
+ */
+ CHANGE: '_CHANGE',
+
+ /**
+ * @static
+ * @property 下拉弹出菜单事件
+ */
+ EXPAND: '_EXPAND',
+
+ /**
+ * @static
+ * @property 关闭下拉菜单事件
+ */
+ COLLAPSE: '_COLLAPSE',
+
+ /**
+ * @static
+ * @property 回调事件
+ */
+ CALLBACK: '_CALLBACK',
+
+ /**
+ * @static
+ * @property 点击事件
+ */
+ CLICK: '_CLICK',
+
+ /**
+ * @static
+ * @property 状态改变事件,一般是用在复选按钮和单选按钮
+ */
+ STATECHANGE: '_STATECHANGE',
+
+ /**
+ * @static
+ * @property 状态改变前事件
+ */
+ BEFORESTATECHANGE: '_BEFORESTATECHANGE',
+
+
+ /**
+ * @static
+ * @property 初始化事件
+ */
+ INIT: '_INIT',
+
+ /**
+ * @static
+ * @property 初始化后事件
+ */
+ AFTERINIT: '_AFTERINIT',
+
+ /**
+ * @static
+ * @property 滚动条滚动事件
+ */
+ SCROLL: '_SCROLL',
+
+
+ /**
+ * @static
+ * @property 开始加载事件
+ */
+ STARTLOAD: '_STARTLOAD',
+
+ /**
+ * @static
+ * @property 加载后事件
+ */
+ AFTERLOAD: '_AFTERLOAD',
+
+
+ /**
+ * @static
+ * @property 提交前事件
+ */
+ BS: 'beforesubmit',
+
+ /**
+ * @static
+ * @property 提交后事件
+ */
+ AS: 'aftersubmit',
+
+ /**
+ * @static
+ * @property 提交完成事件
+ */
+ SC: 'submitcomplete',
+
+ /**
+ * @static
+ * @property 提交失败事件
+ */
+ SF: 'submitfailure',
+
+ /**
+ * @static
+ * @property 提交成功事件
+ */
+ SS: 'submitsuccess',
+
+ /**
+ * @static
+ * @property 校验提交前事件
+ */
+ BVW: 'beforeverifywrite',
+
+ /**
+ * @static
+ * @property 校验提交后事件
+ */
+ AVW: 'afterverifywrite',
+
+ /**
+ * @static
+ * @property 校验后事件
+ */
+ AV: 'afterverify',
+
+ /**
+ * @static
+ * @property 填报前事件
+ */
+ BW: 'beforewrite',
+
+ /**
+ * @static
+ * @property 填报后事件
+ */
+ AW: 'afterwrite',
+
+ /**
+ * @static
+ * @property 填报成功事件
+ */
+ WS: 'writesuccess',
+
+ /**
+ * @static
+ * @property 填报失败事件
+ */
+ WF: 'writefailure',
+
+ /**
+ * @static
+ * @property 添加行前事件
+ */
+ BA: 'beforeappend',
+
+ /**
+ * @static
+ * @property 添加行后事件
+ */
+ AA: 'afterappend',
+
+ /**
+ * @static
+ * @property 删除行前事件
+ */
+ BD: 'beforedelete',
+
+ /**
+ * @static
+ * @property 删除行后事件
+ */
+ AD: 'beforedelete',
+
+ /**
+ * @static
+ * @property 未提交离开事件
+ */
+ UC: 'unloadcheck',
+
+
+ /**
+ * @static
+ * @property PDF导出前事件
+ */
+ BTOPDF: 'beforetopdf',
+
+ /**
+ * @static
+ * @property PDF导出后事件
+ */
+ ATOPDF: 'aftertopdf',
+
+ /**
+ * @static
+ * @property Excel导出前事件
+ */
+ BTOEXCEL: 'beforetoexcel',
+
+ /**
+ * @static
+ * @property Excel导出后事件
+ */
+ ATOEXCEL: 'aftertoexcel',
+
+ /**
+ * @static
+ * @property Word导出前事件
+ */
+ BTOWORD: 'beforetoword',
+
+ /**
+ * @static
+ * @property Word导出后事件
+ */
+ ATOWORD: 'aftertoword',
+
+ /**
+ * @static
+ * @property 图片导出前事件
+ */
+ BTOIMAGE: 'beforetoimage',
+
+ /**
+ * @static
+ * @property 图片导出后事件
+ */
+ ATOIMAGE: 'aftertoimage',
+
+ /**
+ * @static
+ * @property HTML导出前事件
+ */
+ BTOHTML: 'beforetohtml',
+
+ /**
+ * @static
+ * @property HTML导出后事件
+ */
+ ATOHTML: 'aftertohtml',
+
+ /**
+ * @static
+ * @property Excel导入前事件
+ */
+ BIMEXCEL: 'beforeimportexcel',
+
+ /**
+ * @static
+ * @property Excel导出后事件
+ */
+ AIMEXCEL: 'afterimportexcel',
+
+ /**
+ * @static
+ * @property PDF打印前事件
+ */
+ BPDFPRINT: 'beforepdfprint',
+
+ /**
+ * @static
+ * @property PDF打印后事件
+ */
+ APDFPRINT: 'afterpdfprint',
+
+ /**
+ * @static
+ * @property Flash打印前事件
+ */
+ BFLASHPRINT: 'beforeflashprint',
+
+ /**
+ * @static
+ * @property Flash打印后事件
+ */
+ AFLASHPRINT: 'afterflashprint',
+
+ /**
+ * @static
+ * @property Applet打印前事件
+ */
+ BAPPLETPRINT: 'beforeappletprint',
+
+ /**
+ * @static
+ * @property Applet打印后事件
+ */
+ AAPPLETPRINT: 'afterappletprint',
+
+ /**
+ * @static
+ * @property 服务器打印前事件
+ */
+ BSEVERPRINT: 'beforeserverprint',
+
+ /**
+ * @static
+ * @property 服务器打印后事件
+ */
+ ASERVERPRINT: 'afterserverprint',
+
+ /**
+ * @static
+ * @property 邮件发送前事件
+ */
+ BEMAIL: 'beforeemail',
+
+ /**
+ * @static
+ * @property 邮件发送后事件
+ */
+ AEMAIL: 'afteremail'
+ }
+});/**
+ * guy
+ * 最基础的dom操作
+ */
+BI.extend(jQuery.fn, {
+
+ destroy: function () {
+ this.remove();
+ if (BI.isIE() === true) {
+ this[0].outerHTML = '';
+ }
+ },
+ /**
+ * 高亮显示
+ * @param text 必需
+ * @param keyword
+ * @param py 必需
+ * @returns {*}
+ * @private
+ */
+ __textKeywordMarked__: function (text, keyword, py) {
+ if (!BI.isKey(keyword) || (text + "").length > 100) {
+ return this.text((text + "").replaceAll(" ", " "));
+ }
+ keyword = keyword + "";
+ keyword = BI.toUpperCase(keyword);
+ var textLeft = (text || "") + "";
+ py = (py || BI.makeFirstPY(text)) + "";
+ if (py != null) {
+ py = BI.toUpperCase(py);
+ }
+ this.empty();
+ while (true) {
+ var tidx = BI.toUpperCase(textLeft).indexOf(keyword);
+ var pidx = null;
+ if (py != null) {
+ pidx = py.indexOf(keyword);
+ if (pidx >= 0) {
+ pidx = pidx % text.length;
+ }
+ }
+
+ if (tidx >= 0) {
+ this.append(textLeft.substr(0, tidx));
+ this.append($("").addClass("bi-keyword-red-mark")
+ .text(textLeft.substr(tidx, keyword.length).replaceAll(" ", " ")));
+
+ textLeft = textLeft.substr(tidx + keyword.length);
+ if (py != null) {
+ py = py.substr(tidx + keyword.length);
+ }
+ } else if (pidx != null && pidx >= 0 && Math.floor(pidx / text.length) === Math.floor((pidx + keyword.length - 1) / text.length)) {
+ this.append(textLeft.substr(0, pidx));
+ this.append($("").addClass("bi-keyword-red-mark")
+ .text(textLeft.substr(pidx, keyword.length).replaceAll(" ", " ")));
+ if (py != null) {
+ py = py.substr(pidx + keyword.length);
+ }
+ textLeft = textLeft.substr(pidx + keyword.length);
+ } else {
+ this.append(textLeft);
+ break;
+ }
+ }
+
+ return this;
+ },
+
+ getDomHeight: function (parent) {
+ var clone = $(this).clone();
+ clone.appendTo($(parent || "body"));
+ var height = clone.height();
+ clone.remove();
+ return height;
+ },
+
+ //是否有竖直滚动条
+ hasVerticalScroll: function () {
+ return this.height() > 0 && this[0].clientWidth < this[0].offsetWidth;
+ },
+
+ //是否有水平滚动条
+ hasHorizonScroll: function () {
+ return this.width() > 0 && this[0].clientHeight < this[0].offsetHeight;
+ },
+
+ //获取计算后的样式
+ getStyle: function (name) {
+ var node = this[0];
+ var computedStyle = void 0;
+
+ // W3C Standard
+ if (window.getComputedStyle) {
+ // In certain cases such as within an iframe in FF3, this returns null.
+ computedStyle = window.getComputedStyle(node, null);
+ if (computedStyle) {
+ return computedStyle.getPropertyValue(BI.hyphenate(name));
+ }
+ }
+ // Safari
+ if (document.defaultView && document.defaultView.getComputedStyle) {
+ computedStyle = document.defaultView.getComputedStyle(node, null);
+ // A Safari bug causes this to return null for `display: none` elements.
+ if (computedStyle) {
+ return computedStyle.getPropertyValue(BI.hyphenate(name));
+ }
+ if (name === 'display') {
+ return 'none';
+ }
+ }
+ // Internet Explorer
+ if (node.currentStyle) {
+ if (name === 'float') {
+ return node.currentStyle.cssFloat || node.currentStyle.styleFloat;
+ }
+ return node.currentStyle[BI.camelize(name)];
+ }
+ return node.style && node.style[BI.camelize(name)];
+ },
+
+ __isMouseInBounds__: function (e) {
+ var offset2Body = this.offset();
+ return !(e.pageX < offset2Body.left || e.pageX > offset2Body.left + this.outerWidth()
+ || e.pageY < offset2Body.top || e.pageY > offset2Body.top + this.outerHeight())
+ },
+
+ __hasZIndexMask__: function (zindex) {
+ return zindex && this.zIndexMask[zindex] != null;
+ },
+
+ __buildZIndexMask__: function (zindex, domArray) {
+ this.zIndexMask = this.zIndexMask || {};//存储z-index的mask
+ this.indexMask = this.indexMask || [];//存储mask
+ var mask = BI.createWidget({
+ type: "bi.center_adapt",
+ cls: "bi-z-index-mask",
+ items: domArray
+ });
+
+ mask.element.css({"z-index": zindex});
+ BI.createWidget({
+ type: "bi.absolute",
+ element: this,
+ items: [{
+ el: mask,
+ left: 0,
+ right: 0,
+ top: 0,
+ bottom: 0
+ }]
+ });
+ this.indexMask.push(mask);
+ zindex && (this.zIndexMask[zindex] = mask);
+ return mask.element;
+ },
+
+ __releaseZIndexMask__: function (zindex) {
+ if (zindex && this.zIndexMask[zindex]) {
+ this.indexMask.remove(this.zIndexMask[zindex]);
+ this.zIndexMask[zindex].destroy();
+ return;
+ }
+ this.indexMask = this.indexMask || [];
+ var indexMask = this.indexMask.pop();
+ indexMask && indexMask.destroy();
+ }
+});
+
+BI.extend(jQuery, {
+
+ getLeftPosition: function (combo, popup, extraWidth) {
+ return {
+ left: combo.element.offset().left - popup.element.outerWidth() - (extraWidth || 0)
+ };
+ },
+
+ getRightPosition: function (combo, popup, extraWidth) {
+ var el = combo.element;
+ return {
+ left: el.offset().left + el.outerWidth() + (extraWidth || 0)
+ }
+ },
+
+ getTopPosition: function (combo, popup, extraHeight) {
+ return {
+ top: combo.element.offset().top - popup.element.outerHeight() - (extraHeight || 0)
+ };
+ },
+
+ getBottomPosition: function (combo, popup, extraHeight) {
+ var el = combo.element;
+ return {
+ top: el.offset().top + el.outerHeight() + (extraHeight || 0)
+ };
+ },
+
+ isLeftSpaceEnough: function (combo, popup, extraWidth) {
+ return $.getLeftPosition(combo, popup, extraWidth).left >= 0;
+ },
+
+ isRightSpaceEnough: function (combo, popup, extraWidth) {
+ var viewBounds = popup.element.bounds(), windowBounds = $("body").bounds();
+ return $.getRightPosition(combo, popup, extraWidth).left + viewBounds.width <= windowBounds.width;
+ },
+
+ isTopSpaceEnough: function (combo, popup, extraHeight) {
+ return $.getTopPosition(combo, popup, extraHeight).top >= 0;
+ },
+
+ isBottomSpaceEnough: function (combo, popup, extraHeight) {
+ var viewBounds = popup.element.bounds(), windowBounds = $("body").bounds();
+ return $.getBottomPosition(combo, popup, extraHeight).top + viewBounds.height <= windowBounds.height;
+ },
+
+ isRightSpaceLarger: function (combo) {
+ var windowBounds = $("body").bounds();
+ return windowBounds.width - combo.element.offset().left - combo.element.bounds().width >= combo.element.offset().left;
+ },
+
+ isBottomSpaceLarger: function (combo) {
+ var windowBounds = $("body").bounds();
+ return windowBounds.height - combo.element.offset().top - combo.element.bounds().height >= combo.element.offset().top;
+ },
+
+ getLeftAlignPosition: function (combo, popup, extraWidth) {
+ var viewBounds = popup.element.bounds(), windowBounds = $("body").bounds();
+ var left = combo.element.offset().left + extraWidth;
+ if (left + viewBounds.width > windowBounds.width) {
+ left = windowBounds.width - viewBounds.width;
+ }
+ if (left < 0) {
+ left = 0;
+ }
+ return {
+ left: left
+ }
+ },
+
+ getLeftAdaptPosition: function (combo, popup, extraWidth) {
+ if ($.isLeftSpaceEnough(combo, popup, extraWidth)) {
+ return $.getLeftPosition(combo, popup, extraWidth);
+ }
+ return {
+ left: 0
+ }
+ },
+
+ getRightAlignPosition: function (combo, popup, extraWidth) {
+ var comboBounds = combo.element.bounds(), viewBounds = popup.element.bounds();
+ var left = combo.element.offset().left + comboBounds.width - viewBounds.width - extraWidth;
+ if (left < 0) {
+ left = 0;
+ }
+ return {
+ left: left
+ }
+ },
+
+ getRightAdaptPosition: function (combo, popup, extraWidth) {
+ if ($.isRightSpaceEnough(combo, popup, extraWidth)) {
+ return $.getRightPosition(combo, popup, extraWidth);
+ }
+ return {
+ left: $("body").bounds().width - popup.element.bounds().width
+ }
+ },
+
+ getTopAlignPosition: function (combo, popup, extraHeight, needAdaptHeight) {
+ var comboOffset = combo.element.offset();
+ var comboBounds = combo.element.bounds(), popupBounds = popup.element.bounds(),
+ windowBounds = $("body").bounds();
+ var top, adaptHeight;
+ if ($.isBottomSpaceEnough(combo, popup, -1 * comboBounds.height + extraHeight)) {
+ top = comboOffset.top + extraHeight;
+ } else if (needAdaptHeight) {
+ top = comboOffset.top + extraHeight;
+ adaptHeight = windowBounds.height - top;
+ } else {
+ top = windowBounds.height - popupBounds.height;
+ if (top < extraHeight) {
+ adaptHeight = windowBounds.height - extraHeight;
+ }
+ }
+ if (top < extraHeight) {
+ top = extraHeight;
+ }
+ return adaptHeight ? {
+ top: top,
+ adaptHeight: adaptHeight
+ } : {
+ top: top
+ }
+ },
+
+ getTopAdaptPosition: function (combo, popup, extraHeight, needAdaptHeight) {
+ var popupBounds = popup.element.bounds(), windowBounds = $("body").bounds();
+ if ($.isTopSpaceEnough(combo, popup, extraHeight)) {
+ return $.getTopPosition(combo, popup, extraHeight);
+ }
+ if (needAdaptHeight) {
+ return {
+ top: 0,
+ adaptHeight: combo.element.offset().top - extraHeight
+ }
+ }
+ if (popupBounds.height + extraHeight > windowBounds.height) {
+ return {
+ top: 0,
+ adaptHeight: windowBounds.height - extraHeight
+ }
+ }
+ return {
+ top: 0
+ }
+ },
+
+ getBottomAlignPosition: function (combo, popup, extraHeight, needAdaptHeight) {
+ var comboOffset = combo.element.offset();
+ var comboBounds = combo.element.bounds(), popupBounds = popup.element.bounds(),
+ windowBounds = $("body").bounds();
+ var top, adaptHeight;
+ if ($.isTopSpaceEnough(combo, popup, -1 * comboBounds.height + extraHeight)) {
+ top = comboOffset.top + comboBounds.height - popupBounds.height - extraHeight;
+ } else if (needAdaptHeight) {
+ top = 0;
+ adaptHeight = comboOffset.top + comboBounds.height - extraHeight;
+ } else {
+ top = 0;
+ if (popupBounds.height + extraHeight > windowBounds.height) {
+ adaptHeight = windowBounds.height - extraHeight;
+ }
+ }
+ if (top < 0) {
+ top = 0;
+ }
+ return adaptHeight ? {
+ top: top,
+ adaptHeight: adaptHeight
+ } : {
+ top: top
+ }
+ },
+
+ getBottomAdaptPosition: function (combo, popup, extraHeight, needAdaptHeight) {
+ var comboOffset = combo.element.offset();
+ var comboBounds = combo.element.bounds(), popupBounds = popup.element.bounds(),
+ windowBounds = $("body").bounds();
+ if ($.isBottomSpaceEnough(combo, popup, extraHeight)) {
+ return $.getBottomPosition(combo, popup, extraHeight);
+ }
+ if (needAdaptHeight) {
+ return {
+ top: comboOffset.top + comboBounds.height + extraHeight,
+ adaptHeight: windowBounds.height - comboOffset.top - comboBounds.height - extraHeight
+ }
+ }
+ if (popupBounds.height + extraHeight > windowBounds.height) {
+ return {
+ top: extraHeight,
+ adaptHeight: windowBounds.height - extraHeight
+ }
+ }
+ return {
+ top: windowBounds.height - popupBounds.height - extraHeight
+ }
+ },
+
+ getCenterAdaptPosition: function (combo, popup) {
+ var comboOffset = combo.element.offset();
+ var comboBounds = combo.element.bounds(), popupBounds = popup.element.bounds(),
+ windowBounds = $("body").bounds();
+ var left;
+ if (comboOffset.left + comboBounds.width / 2 + popupBounds.width / 2 > windowBounds.width) {
+ left = windowBounds.width - popupBounds.width;
+ } else {
+ left = comboOffset.left + comboBounds.width / 2 - popupBounds.width / 2;
+ }
+ if (left < 0) {
+ left = 0;
+ }
+ return {
+ left: left
+ }
+ },
+
+ getMiddleAdaptPosition: function (combo, popup) {
+ var comboOffset = combo.element.offset();
+ var comboBounds = combo.element.bounds(), popupBounds = popup.element.bounds(),
+ windowBounds = $("body").bounds();
+ var top;
+ if (comboOffset.top + comboBounds.height / 2 + popupBounds.height / 2 > windowBounds.height) {
+ top = windowBounds.height - popupBounds.height;
+ } else {
+ top = comboOffset.top + comboBounds.height / 2 - popupBounds.height / 2;
+ }
+ if (top < 0) {
+ top = 0;
+ }
+ return {
+ top: top
+ }
+ },
+
+ getComboPositionByDirections: function (combo, popup, extraWidth, extraHeight, needAdaptHeight, directions) {
+ extraWidth || (extraWidth = 0);
+ extraHeight || (extraHeight = 0);
+ var i, direct;
+ var leftRight = [], topBottom = [];
+ var isNeedAdaptHeight = false, tbFirst = false, lrFirst = false;
+ var left, top, pos;
+ for (i = 0; i < directions.length; i++) {
+ direct = directions[i];
+ switch (direct) {
+ case "left":
+ leftRight.push(direct);
+ break;
+ case "right":
+ leftRight.push(direct);
+ break;
+ case "top":
+ topBottom.push(direct);
+ break;
+ case "bottom":
+ topBottom.push(direct);
+ break;
+ }
+ }
+ for (i = 0; i < directions.length; i++) {
+ direct = directions[i];
+ switch (direct) {
+ case "left":
+ if (!isNeedAdaptHeight) {
+ var tW = tbFirst ? extraHeight : extraWidth, tH = tbFirst ? 0 : extraHeight;
+ if ($.isLeftSpaceEnough(combo, popup, tW)) {
+ left = $.getLeftPosition(combo, popup, tW).left;
+ if (topBottom[0] === "bottom") {
+ pos = $.getTopAlignPosition(combo, popup, tH, needAdaptHeight);
+ pos.dir = "left,bottom";
+ } else {
+ pos = $.getBottomAlignPosition(combo, popup, tH, needAdaptHeight);
+ pos.dir = "left,top";
+ }
+ if (tbFirst) {
+ pos.change = "left";
+ }
+ pos.left = left;
+ return pos;
+ }
+ }
+ lrFirst = true;
+ break;
+ case "right":
+ if (!isNeedAdaptHeight) {
+ var tW = tbFirst ? extraHeight : extraWidth, tH = tbFirst ? extraWidth : extraHeight;
+ if ($.isRightSpaceEnough(combo, popup, tW)) {
+ left = $.getRightPosition(combo, popup, tW).left;
+ if (topBottom[0] === "bottom") {
+ pos = $.getTopAlignPosition(combo, popup, tH, needAdaptHeight);
+ pos.dir = "right,bottom";
+ } else {
+ pos = $.getBottomAlignPosition(combo, popup, tH, needAdaptHeight);
+ pos.dir = "right,top";
+ }
+ if (tbFirst) {
+ pos.change = "right";
+ }
+ pos.left = left;
+ return pos;
+ }
+ }
+ lrFirst = true;
+ break;
+ case "top":
+ var tW = lrFirst ? extraHeight : extraWidth, tH = lrFirst ? extraWidth : extraHeight;
+ if ($.isTopSpaceEnough(combo, popup, tH)) {
+ top = $.getTopPosition(combo, popup, tH).top;
+ if (leftRight[0] === "right") {
+ pos = $.getLeftAlignPosition(combo, popup, tW, needAdaptHeight);
+ pos.dir = "top,right";
+ } else {
+ pos = $.getRightAlignPosition(combo, popup, tW);
+ pos.dir = "top,left";
+ }
+ if (lrFirst) {
+ pos.change = "top";
+ }
+ pos.top = top;
+ return pos;
+ }
+ if (needAdaptHeight) {
+ isNeedAdaptHeight = true;
+ }
+ tbFirst = true;
+ break;
+ case "bottom":
+ var tW = lrFirst ? extraHeight : extraWidth, tH = lrFirst ? extraWidth : extraHeight;
+ if ($.isBottomSpaceEnough(combo, popup, tH)) {
+ top = $.getBottomPosition(combo, popup, tH).top;
+ if (leftRight[0] === "right") {
+ pos = $.getLeftAlignPosition(combo, popup, tW, needAdaptHeight);
+ pos.dir = "bottom,right";
+ } else {
+ pos = $.getRightAlignPosition(combo, popup, tW);
+ pos.dir = "bottom,left";
+ }
+ if (lrFirst) {
+ pos.change = "bottom";
+ }
+ pos.top = top;
+ return pos;
+ }
+ if (needAdaptHeight) {
+ isNeedAdaptHeight = true;
+ }
+ tbFirst = true;
+ break;
+ }
+ }
+
+ switch (directions[0]) {
+ case "left":
+ case "right":
+ if ($.isRightSpaceLarger(combo)) {
+ left = $.getRightAdaptPosition(combo, popup, extraWidth).left;
+ } else {
+ left = $.getLeftAdaptPosition(combo, popup, extraWidth).left;
+ }
+ if (topBottom[0] === "bottom") {
+ pos = $.getTopAlignPosition(combo, popup, extraHeight, needAdaptHeight);
+ pos.left = left;
+ pos.dir = directions[0] + ",bottom";
+ return pos;
+ }
+ pos = $.getBottomAlignPosition(combo, popup, extraHeight, needAdaptHeight);
+ pos.left = left;
+ pos.dir = directions[0] + ",top";
+ return pos;
+ default :
+ if ($.isBottomSpaceLarger(combo)) {
+ pos = $.getBottomAdaptPosition(combo, popup, extraHeight, needAdaptHeight);
+ } else {
+ pos = $.getTopAdaptPosition(combo, popup, extraHeight, needAdaptHeight);
+ }
+ if (leftRight[0] === "right") {
+ left = $.getLeftAlignPosition(combo, popup, extraWidth, needAdaptHeight).left;
+ pos.left = left;
+ pos.dir = directions[0] + ",right";
+ return pos;
+ }
+ left = $.getRightAlignPosition(combo, popup, extraWidth).left;
+ pos.left = left;
+ pos.dir = directions[0] + ",left";
+ return pos;
+ }
+ },
+
+
+ getComboPosition: function (combo, popup, extraWidth, extraHeight, needAdaptHeight, directions, offsetStyle) {
+ extraWidth || (extraWidth = 0);
+ extraHeight || (extraHeight = 0);
+ var bodyHeight = $("body").bounds().height - extraHeight;
+ var maxHeight = Math.min(popup.attr("maxHeight") || bodyHeight, bodyHeight);
+ popup.resetHeight && popup.resetHeight(maxHeight);
+ var position = $.getComboPositionByDirections(combo, popup, extraWidth, extraHeight, needAdaptHeight, directions || ['bottom', 'top', 'right', 'left']);
+ switch (offsetStyle) {
+ case "center":
+ if (position.change) {
+ var p = $.getMiddleAdaptPosition(combo, popup);
+ position.top = p.top;
+ } else {
+ var p = $.getCenterAdaptPosition(combo, popup);
+ position.left = p.left;
+ }
+ break;
+ case "middle":
+ if (position.change) {
+ var p = $.getCenterAdaptPosition(combo, popup);
+ position.left = p.left;
+ } else {
+ var p = $.getMiddleAdaptPosition(combo, popup);
+ position.top = p.top;
+ }
+ break;
+ }
+ if (needAdaptHeight === true) {
+ popup.resetHeight && popup.resetHeight(Math.min(bodyHeight - position.top, maxHeight));
+ }
+ return position;
+ }
+});/**
+ * 基本的函数
+ * Created by GUY on 2015/6/24.
+ */
+BI.Func = {};
+BI.extend(BI.Func, {
+
+ /**
+ * 获取搜索结果
+ * @param items
+ * @param keyword
+ * @param param 搜索哪个属性
+ */
+ getSearchResult: function (items, keyword, param) {
+ var isArray = BI.isArray(items);
+ items = isArray ? BI.flatten(items) : items;
+ param || (param = "text");
+ if (!BI.isKey(keyword)) {
+ return {
+ finded: BI.deepClone(items),
+ matched: isArray ? [] : {}
+ };
+ }
+ var t, text, py;
+ keyword = BI.toUpperCase(keyword);
+ var matched = isArray ? [] : {}, finded = isArray ? [] : {};
+ BI.each(items, function (i, item) {
+ item = BI.deepClone(item);
+ t = BI.stripEL(item);
+ text = t[param] || t.text || t.value || t.name || t;
+ py = BI.makeFirstPY(text);
+ text = BI.toUpperCase(text);
+ py = BI.toUpperCase(py);
+ var pidx;
+ if (text.indexOf(keyword) > -1) {
+ if (text === keyword) {
+ isArray ? matched.push(item) : (matched[i] = item);
+ } else {
+ isArray ? finded.push(item) : (finded[i] = item);
+ }
+ } else if (pidx = py.indexOf(keyword), (pidx > -1 && Math.floor(pidx / text.length) === Math.floor((pidx + keyword.length - 1) / text.length))) {
+ if (text === keyword || keyword.length === text.length) {
+ isArray ? matched.push(item) : (matched[i] = item);
+ } else {
+ isArray ? finded.push(item) : (finded[i] = item);
+ }
+ }
+ });
+ return {
+ matched: matched,
+ finded: finded
+ }
+ },
+});
+
+/**
+ * 对DOM操作的通用函数
+ * @type {{}}
+ */
+BI.DOM = {};
+BI.extend(BI.DOM, {
+
+ /**
+ * 把dom数组或元素悬挂起来,使其不对html产生影响
+ * @param dom
+ */
+ hang: function (doms) {
+ if (BI.isEmpty(doms)) {
+ return;
+ }
+ var frag = document.createDocumentFragment();
+ BI.each(doms, function (i, dom) {
+ dom instanceof BI.Widget && (dom = dom.element);
+ dom instanceof $ && dom[0] && frag.appendChild(dom[0]);
+ });
+ return frag;
+ },
+
+ isExist: function (obj) {
+ return $("body").find(obj.element).length > 0;
+ },
+
+ //预加载图片
+ preloadImages: function (srcArray, onload) {
+ var count = 0, images = [];
+
+ function complete() {
+ count++;
+ if (count >= srcArray.length) {
+ onload();
+ }
+ }
+
+ BI.each(srcArray, function (i, src) {
+ images[i] = new Image();
+ images[i].src = src;
+ images[i].onload = function () {
+ complete()
+ };
+ images[i].onerror = function () {
+ complete()
+ };
+ });
+ },
+
+ isColor: function (color) {
+ return color && (this.isRGBColor(color) || this.isHexColor(color));
+ },
+
+ isRGBColor: function (color) {
+ if (!color) {
+ return false;
+ }
+ return color.substr(0, 3) === "rgb";
+ },
+
+ isHexColor: function (color) {
+ if (!color) {
+ return false;
+ }
+ return color[0] === "#" && color.length === 7;
+ },
+
+ isDarkColor: function (hex) {
+ if (!hex || !this.isHexColor(hex)) {
+ return false;
+ }
+ var rgb = this.rgb2json(this.hex2rgb(hex));
+ var grayLevel = Math.round(rgb.r * 0.299 + rgb.g * 0.587 + rgb.b * 0.114);
+ if (grayLevel < 192/**网上给的是140**/) {
+ return true;
+ }
+ return false;
+ },
+
+ //获取对比颜色
+ getContrastColor: function (color) {
+ if (!color || !this.isColor(color)) {
+ return "";
+ }
+ if (this.isDarkColor(color)) {
+ return "#ffffff";
+ }
+ return "#1a1a1a";
+ },
+
+ rgb2hex: function (rgbColour) {
+ if (!rgbColour || rgbColour.substr(0, 3) != "rgb") {
+ return "";
+ }
+ var rgbValues = rgbColour.match(/\d+(\.\d+)?/g);
+ var red = BI.parseInt(rgbValues[0]);
+ var green = BI.parseInt(rgbValues[1]);
+ var blue = BI.parseInt(rgbValues[2]);
+
+ var hexColour = "#" + this.int2hex(red) + this.int2hex(green) + this.int2hex(blue);
+
+ return hexColour;
+ },
+
+ rgb2json: function (rgbColour) {
+ if (!rgbColour) {
+ return {};
+ }
+ if (!this.isRGBColor(rgbColour)) {
+ return {};
+ }
+ var rgbValues = rgbColour.match(/\d+(\.\d+)?/g);
+ return {
+ r: BI.parseInt(rgbValues[0]),
+ g: BI.parseInt(rgbValues[1]),
+ b: BI.parseInt(rgbValues[2])
+ };
+ },
+
+ rgba2json: function (rgbColour) {
+ if (!rgbColour) {
+ return {};
+ }
+ var rgbValues = rgbColour.match(/\d+(\.\d+)?/g);
+ return {
+ r: BI.parseInt(rgbValues[0]),
+ g: BI.parseInt(rgbValues[1]),
+ b: BI.parseInt(rgbValues[2]),
+ a: BI.parseFloat(rgbValues[3])
+ };
+ },
+
+ json2rgb: function (rgb) {
+ if (!BI.isKey(rgb.r) || !BI.isKey(rgb.g) || !BI.isKey(rgb.b)) {
+ return "";
+ }
+ return "rgb(" + rgb.r + "," + rgb.g + "," + rgb.b + ")";
+ },
+
+ json2rgba: function (rgba) {
+ if (!BI.isKey(rgba.r) || !BI.isKey(rgba.g) || !BI.isKey(rgba.b)) {
+ return "";
+ }
+ return "rgba(" + rgba.r + "," + rgba.g + "," + rgba.b + "," + rgba.a + ")";
+ },
+
+ int2hex: function (strNum) {
+ var hexdig = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
+
+ return hexdig[strNum >>> 4] + '' + hexdig[strNum & 15];
+ },
+
+ hex2rgb: function (color) {
+ if (!color) {
+ return "";
+ }
+ if (!this.isHexColor(color)) {
+ return color;
+ }
+ var tempValue = "rgb(", colorArray;
+
+ if (color.length === 7) {
+ colorArray = [BI.parseInt('0x' + color.substring(1, 3)),
+ BI.parseInt('0x' + color.substring(3, 5)),
+ BI.parseInt('0x' + color.substring(5, 7))];
+ }
+ else if (color.length === 4) {
+ colorArray = [BI.parseInt('0x' + color.substring(1, 2)),
+ BI.parseInt('0x' + color.substring(2, 3)),
+ BI.parseInt('0x' + color.substring(3, 4))];
+ }
+ tempValue += colorArray[0] + ",";
+ tempValue += colorArray[1] + ",";
+ tempValue += colorArray[2] + ")";
+
+ return tempValue;
+ },
+
+ rgba2rgb: function (rgbColour, BGcolor) {
+ if (BI.isNull(BGcolor)) {
+ BGcolor = 1;
+ }
+ if (rgbColour.substr(0, 4) != "rgba") {
+ return "";
+ }
+ var rgbValues = rgbColour.match(/\d+(\.\d+)?/g);
+ if (rgbValues.length < 4) {
+ return "";
+ }
+ var R = BI.parseFloat(rgbValues[0]);
+ var G = BI.parseFloat(rgbValues[1]);
+ var B = BI.parseFloat(rgbValues[2]);
+ var A = BI.parseFloat(rgbValues[3]);
+
+ return "rgb(" + Math.floor(255 * (BGcolor * (1 - A )) + R * A) + "," +
+ Math.floor(255 * (BGcolor * (1 - A )) + G * A) + "," +
+ Math.floor(255 * (BGcolor * (1 - A )) + B * A) + ")";
+ },
+
+ getTextSizeWidth: function (text, fontSize) {
+ var span = $(" ").addClass("text-width-span").appendTo($("body"));
+
+ if (fontSize == null) {
+ fontSize = 12;
+ }
+ fontSize = fontSize + "px";
+
+ span.css("font-size", fontSize).text(text);
+
+ var width = span.width();
+ span.remove();
+
+ return width;
+ },
+
+ //获取滚动条的宽度
+ getScrollWidth: function () {
+ if (this._scrollWidth == null) {
+ var ul = $("").width(50).height(50).css({
+ position: "absolute",
+ top: "-9999px",
+ overflow: "scroll"
+ }).appendTo($("body"));
+ this._scrollWidth = ul[0].offsetWidth - ul[0].clientWidth;
+ ul.destroy();
+ }
+ return this._scrollWidth;
+ }
+});/**
+ * guy
+ * 检测某个Widget的EventChange事件然后去show某个card
+ * @type {*|void|Object}
+ * @class BI.ShowListener
+ * @extends BI.OB
+ */
+BI.ShowListener = BI.inherit(BI.OB, {
+ _defaultConfig: function () {
+ return BI.extend(BI.ShowListener.superclass._defaultConfig.apply(this, arguments), {
+ eventObj: BI.createWidget(),
+ cardLayout: null,
+ cardNameCreator: function (v) {
+ return v;
+ },
+ cardCreator: BI.emptyFn,
+ afterCardCreated: BI.emptyFn,
+ afterCardShow: BI.emptyFn
+ });
+ },
+
+ _init: function () {
+ BI.ShowListener.superclass._init.apply(this, arguments);
+ var self = this, o = this.options;
+ o.eventObj.on(BI.Controller.EVENT_CHANGE, function (type, v, ob) {
+ if (type === BI.Events.CLICK) {
+ v = v || o.eventObj.getValue();
+ v = BI.isArray(v) ? (v.length > 1 ? v.toString() : v[0]) : v;
+ if (BI.isNull(v)) {
+ throw new Error("value cannot be null");
+ }
+ var cardName = o.cardNameCreator(v);
+ if (!o.cardLayout.isCardExisted(cardName)) {
+ var card = o.cardCreator(cardName);
+ o.cardLayout.addCardByName(cardName, card);
+ o.afterCardCreated(cardName);
+ }
+ o.cardLayout.showCardByName(cardName);
+ BI.nextTick(function () {
+ o.afterCardShow(cardName);
+ self.fireEvent(BI.ShowListener.EVENT_CHANGE, cardName);
+ });
+ }
+ })
+ }
+});
+BI.ShowListener.EVENT_CHANGE = "ShowListener.EVENT_CHANGE";/**
+ * style加载管理器
+ *
+ * Created by GUY on 2015/9/7.
+ * @class
+ */
+BI.StyleLoaderManager = BI.inherit(BI.OB, {
+ _defaultConfig: function () {
+ return BI.extend(BI.StyleLoaderManager.superclass._defaultConfig.apply(this, arguments), {});
+ },
+
+ _init: function () {
+ BI.StyleLoaderManager.superclass._init.apply(this, arguments);
+ this.stylesManager = {};
+ },
+
+ loadStyle: function (name, styleString) {
+ var d = document, styles = d.createElement('style');
+ d.getElementsByTagName('head')[0].appendChild(styles);
+ styles.setAttribute('type', 'text/css');
+ if (styles.styleSheet) {
+ styles.styleSheet.cssText = styleString;
+ } else {
+ styles.appendChild(document.createTextNode(styleString));
+ }
+ this.stylesManager[name] = styles;
+
+ return this;
+ },
+
+ get: function (name) {
+ return this.stylesManager[name];
+ },
+
+ has: function (name) {
+ return this.stylesManager[name] != null;
+ },
+
+ removeStyle: function (name) {
+ if (!this.has(name)) {
+ return this;
+ }
+ this.stylesManager[name].parentNode.removeChild(this.stylesManager[name]);
+ delete this.stylesManager[name];
+ return this;
+ }
+});/**
+ * @class BI.Logic
+ * @extends BI.OB
+ */
+BI.Logic = BI.inherit(BI.OB, {
+ createLogic: function () {
+ return this.options || {};
+ }
+});
+
+BI.LogicFactory = {
+ Type: {
+ Vertical: "vertical",
+ Horizontal: "horizontal",
+ Table: "table",
+ HorizontalFill: "horizontal_fill"
+ },
+ createLogic: function (key, options) {
+ var logic;
+ switch (key) {
+ case BI.LogicFactory.Type.Vertical:
+ logic = BI.VerticalLayoutLogic;
+ break;
+ case BI.LogicFactory.Type.Horizontal:
+ logic = BI.HorizontalLayoutLogic;
+ break;
+ case BI.LogicFactory.Type.Table:
+ logic = BI.TableLayoutLogic;
+ break;
+ case BI.LogicFactory.Type.HorizontalFill:
+ logic = BI.HorizontalFillLayoutLogic;
+ break;
+ default :
+ logic = BI.Logic;
+ break;
+ }
+ return new logic(options).createLogic();
+ },
+
+ createLogicTypeByDirection: function (direction) {
+ switch (direction) {
+ case BI.Direction.Top:
+ case BI.Direction.Bottom:
+ case BI.Direction.Custom:
+ return BI.LogicFactory.Type.Vertical;
+ break;
+ case BI.Direction.Left:
+ case BI.Direction.Right:
+ return BI.LogicFactory.Type.Horizontal;
+ }
+ },
+
+ createLogicItemsByDirection: function (direction) {
+ var layout;
+ var items = Array.prototype.slice.call(arguments, 1);
+ items = BI.map(items, function (i, item) {
+ if (BI.isWidget(item)) {
+ return {
+ el: item,
+ width: item.options.width,
+ height: item.options.height
+ }
+ }
+ return item;
+ });
+ switch (direction) {
+ case BI.Direction.Bottom:
+ layout = BI.LogicFactory.Type.Vertical;
+ items.reverse();
+ break;
+ case BI.Direction.Right:
+ layout = BI.LogicFactory.Type.Horizontal;
+ items.reverse();
+ break;
+ case BI.Direction.Custom:
+ items = items.slice(1);
+ break;
+ }
+ return items;
+ }
+};/**
+ * guy
+ * 上下布局逻辑
+ * 上下布局的时候要考虑到是动态布局还是静态布局
+ *
+ * @class BI.VerticalLayoutLogic
+ * @extends BI.Logic
+ */
+BI.VerticalLayoutLogic = BI.inherit(BI.Logic, {
+ _defaultConfig: function () {
+ return BI.extend(BI.VerticalLayoutLogic.superclass._defaultConfig.apply(this, arguments), {
+ dynamic: false,
+ scrollable: null,
+ scrolly: false,
+ scrollx: false,
+ items: [],
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+
+ createLogic: function () {
+ var layout, o = this.options;
+ if (o.dynamic) {
+ layout = "bi.vertical";
+ } else {
+ layout = "bi.vtape";
+ }
+ return {
+ type: layout,
+ scrollable: o.scrollable,
+ scrolly: o.scrolly,
+ scrollx: o.scrollx,
+ hgap: o.hgap,
+ vgap: o.vgap,
+ lgap: o.lgap,
+ rgap: o.rgap,
+ tgap: o.tgap,
+ bgap: o.bgap,
+ items: o.items
+ }
+ },
+
+ _init: function () {
+ BI.VerticalLayoutLogic.superclass._init.apply(this, arguments);
+ }
+});
+
+
+/**
+ * guy
+ * 左右布局逻辑
+ * 左右布局的时候要考虑到是动态布局还是静态布局
+ *
+ * @class BI.HorizontalLayoutLogic
+ * @extends BI.Logic
+ */
+BI.HorizontalLayoutLogic = BI.inherit(BI.Logic, {
+ _defaultConfig: function () {
+ return BI.extend(BI.HorizontalLayoutLogic.superclass._defaultConfig.apply(this, arguments), {
+ dynamic: false,
+ scrollable: null,
+ scrolly: false,
+ scrollx: false,
+ items: [],
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+
+ createLogic: function () {
+ var layout, o = this.options;
+ if (o.dynamic) {
+ layout = "bi.horizontal";
+ } else {
+ layout = "bi.htape";
+ }
+ return {
+ type: layout,
+ scrollable: o.scrollable,
+ scrolly: o.scrolly,
+ scrollx: o.scrollx,
+ hgap: o.hgap,
+ vgap: o.vgap,
+ lgap: o.lgap,
+ rgap: o.rgap,
+ tgap: o.tgap,
+ bgap: o.bgap,
+ items: o.items
+ }
+ },
+
+ _init: function () {
+ BI.HorizontalLayoutLogic.superclass._init.apply(this, arguments);
+ }
+});
+
+/**
+ * guy
+ * 表格布局逻辑
+ * 表格布局的时候要考虑到是动态布局还是静态布局
+ *
+ * @class BI.TableLayoutLogic
+ * @extends BI.OB
+ */
+BI.TableLayoutLogic = BI.inherit(BI.Logic, {
+ _defaultConfig: function () {
+ return BI.extend(BI.TableLayoutLogic.superclass._defaultConfig.apply(this, arguments), {
+ dynamic: false,
+ scrollable: null,
+ scrolly: false,
+ scrollx: false,
+ columns: 0,
+ rows: 0,
+ columnSize: [],
+ rowSize: [],
+ hgap: 0,
+ vgap: 0,
+ items: []
+ });
+ },
+
+ createLogic: function () {
+ var layout, o = this.options;
+ if (o.dynamic) {
+ layout = "bi.table";
+ } else {
+ layout = "bi.window";
+ }
+ return {
+ type: layout,
+ scrollable: o.scrollable,
+ scrolly: o.scrolly,
+ scrollx: o.scrollx,
+ columns: o.columns,
+ rows: o.rows,
+ columnSize: o.columnSize,
+ rowSize: o.rowSize,
+ hgap: o.hgap,
+ vgap: o.vgap,
+ items: o.items
+ }
+ },
+
+ _init: function () {
+ BI.TableLayoutLogic.superclass._init.apply(this, arguments);
+ }
+});
+
+/**
+ * guy
+ * 左右充满布局逻辑
+ *
+ * @class BI.HorizontalFillLayoutLogic
+ * @extends BI.Logic
+ */
+BI.HorizontalFillLayoutLogic = BI.inherit(BI.Logic, {
+ _defaultConfig: function () {
+ return BI.extend(BI.HorizontalFillLayoutLogic.superclass._defaultConfig.apply(this, arguments), {
+ dynamic: false,
+ scrollable: null,
+ scrolly: false,
+ scrollx: false,
+ items: [],
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+
+ createLogic: function () {
+ var layout, o = this.options;
+ var columnSize = [];
+ BI.each(o.items, function (i, item) {
+ columnSize.push(item.width || 0);
+ });
+ if (o.dynamic) {
+ layout = "bi.horizontal_adapt";
+ } else {
+ layout = "bi.htape";
+ }
+ return {
+ type: layout,
+ columnSize: columnSize,
+ scrollable: o.scrollable,
+ scrolly: o.scrolly,
+ scrollx: o.scrollx,
+ hgap: o.hgap,
+ vgap: o.vgap,
+ lgap: o.lgap,
+ rgap: o.rgap,
+ tgap: o.tgap,
+ bgap: o.bgap,
+ items: o.items
+ }
+ },
+
+ _init: function () {
+ BI.HorizontalFillLayoutLogic.superclass._init.apply(this, arguments);
+ }
+});BI.Plugin = BI.Plugin || {};
+;
+(function () {
+ var _WidgetsPlugin = {};
+ var _ObjectPlugin = {};
+ BI.extend(BI.Plugin, {
+
+ getWidget: function (type, options) {
+ if (_WidgetsPlugin[type]) {
+ var res;
+ for (var i = _WidgetsPlugin[type].length-1; i >=0; i--) {
+ if (res = _WidgetsPlugin[type][i](options)) {
+ return res;
+ }
+ }
+ }
+ return options;
+ },
+
+ registerWidget: function (type, fn) {
+ if (!_WidgetsPlugin[type]) {
+ _WidgetsPlugin[type] = [];
+ }
+ if (_WidgetsPlugin[type].length > 0) {
+ console.log("组件已经注册过了!");
+ }
+ _WidgetsPlugin[type].push(fn);
+ },
+
+ relieveWidget: function (type) {
+ delete _WidgetsPlugin[type];
+ },
+
+ getObject: function (type, object) {
+ if (_ObjectPlugin[type]) {
+ var res;
+ for (var i = 0, len = _ObjectPlugin[type].length; i < len; i++) {
+ res = _ObjectPlugin[type][i](object);
+ }
+ }
+ return res || object;
+ },
+
+ registerObject: function (type, fn) {
+ if (!_ObjectPlugin[type]) {
+ _ObjectPlugin[type] = [];
+ }
+ if (_ObjectPlugin[type].length > 0) {
+ console.log("对象已经注册过了!");
+ }
+ _ObjectPlugin[type].push(fn);
+ },
+
+ relieveObject: function (type) {
+ delete _ObjectPlugin[type];
+ }
+ });
+})();/**
+ * 对数组对象的扩展
+ * @class Array
+ */
+$.extend(Array.prototype, {
+ contains: function (o) {
+ return this.indexOf(o) > -1;
+ },
+
+ /**
+ * 从数组中移除指定的值,如果值不在数组中,则不产生任何效果
+ * @param {Object} o 要移除的值
+ * @return {Array} 移除制定值后的数组
+ */
+ remove: function (o) {
+ var index = this.indexOf(o);
+ if (index !== -1) {
+ this.splice(index, 1);
+ }
+ return this;
+ },
+
+ pushArray: function (array) {
+ for (var i = 0; i < array.length; i++) {
+ this.push(array[i]);
+ }
+ },
+ pushDistinct: function (obj) {
+ if (!this.contains(obj)) {
+ this.push(obj);
+ }
+ },
+ pushDistinctArray: function (array) {
+ for (var i = 0, len = array.length; i < len; i++) {
+ this.pushDistinct(array[i]);
+ }
+ }
+});
+
+BI.Cache = {
+ _prefix: "bi",
+ setUsername: function (username) {
+ localStorage.setItem(BI.Cache._prefix + ".username", (username + "" || "").toUpperCase());
+ },
+ getUsername: function () {
+ return localStorage.getItem(BI.Cache._prefix + ".username") || "";
+ },
+ _getKeyPrefix: function () {
+ return BI.Cache.getUsername() + "." + BI.Cache._prefix + ".";
+ },
+ _generateKey: function (key) {
+ return BI.Cache._getKeyPrefix() + (key || "");
+ },
+ getItem: function (key) {
+ return localStorage.getItem(BI.Cache._generateKey(key));
+ },
+ setItem: function (key, value) {
+ localStorage.setItem(BI.Cache._generateKey(key), value);
+ },
+ removeItem: function (key) {
+ localStorage.removeItem(BI.Cache._generateKey(key));
+ },
+ clear: function () {
+ for (var i = localStorage.length; i >= 0; i--) {
+ var key = localStorage.key(i);
+ if (key) {
+ if (key.indexOf(BI.Cache._getKeyPrefix()) === 0) {
+ localStorage.removeItem(key);
+ }
+ }
+ }
+ },
+ keys: function () {
+ var result = [];
+ for (var i = localStorage.length; i >= 0; i--) {
+ var key = localStorage.key(i);
+ if (key) {
+ var prefix = BI.Cache._getKeyPrefix();
+ if (key.indexOf(prefix) === 0) {
+ result[result.length] = key.substring(prefix.length);
+ }
+ }
+ }
+ return result;
+ },
+
+ addCookie: function (name, value, path, expiresHours) {
+ var cookieString = name + "=" + escape(value);
+ // 判断是否设置过期时间
+ if (expiresHours && expiresHours > 0) {
+ var date = new Date();
+ date.setTime(date.getTime() + expiresHours * 3600 * 1000);
+ cookieString = cookieString + "; expires=" + date.toGMTString();
+ }
+ if (path) {
+ cookieString = cookieString + "; path=" + path;
+ }
+ document.cookie = cookieString;
+ },
+ getCookie: function (name) {
+ var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
+ if (arr = document.cookie.match(reg))
+ return unescape(arr[2]);
+ else
+ return null;
+ },
+ deleteCookie: function (name, path) {
+ var date = new Date();
+ date.setTime(date.getTime() - 10000);
+ var cookieString = name + "=v; expires=" + date.toGMTString();
+ if (path) {
+ cookieString = cookieString + "; path=" + path;
+ }
+ document.cookie = cookieString;
+ }
+};// full day names
+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 = [BI.i18nText("BI-Basic_Simple_Sunday"),
+ BI.i18nText("BI-Basic_Simple_Monday"),
+ BI.i18nText("BI-Basic_Simple_Tuesday"),
+ BI.i18nText("BI-Basic_Simple_Wednesday"),
+ BI.i18nText("BI-Basic_Simple_Thursday"),
+ BI.i18nText("BI-Basic_Simple_Friday"),
+ BI.i18nText("BI-Basic_Simple_Saturday"),
+ BI.i18nText("BI-Basic_Simple_Sunday")];
+
+// Monday first, etc.
+Date._FD = 1;
+
+// full month namesdat
+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 = [0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11];
+
+Date._QN = ["", BI.i18nText("BI-Quarter_1"),
+ BI.i18nText("BI-Quarter_2"),
+ BI.i18nText("BI-Quarter_3"),
+ BI.i18nText("BI-Quarter_4")];
+
+/** Adds the number of days array to the Date object. */
+Date._MD = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+
+/** Constants used for time computations */
+Date.SECOND = 1000 /* milliseconds */;
+Date.MINUTE = 60 * Date.SECOND;
+Date.HOUR = 60 * Date.MINUTE;
+Date.DAY = 24 * Date.HOUR;
+Date.WEEK = 7 * Date.DAY;
+
+/**
+ * 获取时区
+ * @returns {String}
+ */
+Date.prototype.getTimezone = function () {
+ return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
+};
+
+/** Returns the number of days in the current month */
+Date.prototype.getMonthDays = function (month) {
+ var year = this.getFullYear();
+ if (typeof month == "undefined") {
+ month = this.getMonth();
+ }
+ if (((0 == (year % 4)) && ( (0 != (year % 100)) || (0 == (year % 400)))) && month == 1) {
+ return 29;
+ } else {
+ return Date._MD[month];
+ }
+};
+
+/** Returns the number of day in the year. */
+Date.prototype.getDayOfYear = function () {
+ var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
+ var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
+ var time = now - then;
+ return Math.floor(time / Date.DAY);
+};
+
+/** Returns the number of the week in year, as defined in ISO 8601. */
+Date.prototype.getWeekNumber = function () {
+ var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
+ var week = d.getDay();
+ if (this.getMonth() === 0 && this.getDate() <= week) {
+ return 1;
+ }
+ d.setDate(this.getDate() - week);
+ var ms = d.valueOf(); // GMT
+ d.setMonth(0);
+ d.setDate(1);
+ var offset = Math.floor((ms - d.valueOf()) / (7 * 864e5)) + 1;
+ if (d.getDay() > 0) {
+ offset++;
+ }
+ return offset;
+};
+
+//离当前时间多少天的时间
+Date.prototype.getOffsetDate = function (offset) {
+ return new Date(this.getTime() + offset * 864e5);
+};
+
+Date.prototype.getAfterMulQuarter = function (n) {
+ var dt = new Date(this.getTime());
+ dt.setMonth(dt.getMonth() + n * 3);
+ return dt;
+};
+//获得n个季度前的日期
+Date.prototype.getBeforeMulQuarter = function (n) {
+ var dt = new Date(this.getTime());
+ dt.setMonth(dt.getMonth() - n * 3);
+ return dt;
+};
+//得到本季度的起始月份
+Date.prototype.getQuarterStartMonth = function () {
+ var quarterStartMonth = 0;
+ var nowMonth = this.getMonth();
+ if (nowMonth < 3) {
+ quarterStartMonth = 0;
+ }
+ if (2 < nowMonth && nowMonth < 6) {
+ quarterStartMonth = 3;
+ }
+ if (5 < nowMonth && nowMonth < 9) {
+ quarterStartMonth = 6;
+ }
+ if (nowMonth > 8) {
+ quarterStartMonth = 9;
+ }
+ return quarterStartMonth;
+};
+//获得本季度的起始日期
+Date.prototype.getQuarterStartDate = function () {
+ return new Date(this.getFullYear(), this.getQuarterStartMonth(), 1);
+};
+//得到本季度的结束日期
+Date.prototype.getQuarterEndDate = function () {
+ var quarterEndMonth = this.getQuarterStartMonth() + 2;
+ return new Date(this.getFullYear(), quarterEndMonth, this.getMonthDays(quarterEndMonth));
+};
+Date.prototype.getAfterMultiMonth = function (n) {
+ var dt = new Date(this.getTime());
+ dt.setMonth(dt.getMonth() + n | 0);
+ return dt;
+};
+Date.prototype.getBeforeMultiMonth = function (n) {
+ var dt = new Date(this.getTime());
+ dt.setMonth(dt.getMonth() - n | 0);
+ return dt;
+};
+
+Date.prototype.getAfterMulQuarter = function (n) {
+ var dt = new Date(this.getTime());
+ dt.setMonth(dt.getMonth() + n * 3);
+ return dt;
+};
+//获得n个季度前的日期
+Date.prototype.getBeforeMulQuarter = function (n) {
+ var dt = new Date(this.getTime());
+ dt.setMonth(dt.getMonth() - n * 3);
+ return dt;
+};
+//得到本季度的起始月份
+Date.prototype.getQuarterStartMonth = function () {
+ var quarterStartMonth = 0;
+ var nowMonth = this.getMonth();
+ if (nowMonth < 3) {
+ quarterStartMonth = 0;
+ }
+ if (2 < nowMonth && nowMonth < 6) {
+ quarterStartMonth = 3;
+ }
+ if (5 < nowMonth && nowMonth < 9) {
+ quarterStartMonth = 6;
+ }
+ if (nowMonth > 8) {
+ quarterStartMonth = 9;
+ }
+ return quarterStartMonth;
+};
+
+//指定日期n个月之前或之后的日期
+Date.prototype.getOffsetMonth = function (n) {
+ var dt = new Date(this.getTime());
+ var day = dt.getDate();
+ var monthDay = new Date(dt.getFullYear(), dt.getMonth() + parseInt(n), 1).getMonthDays();
+ if (day > monthDay) {
+ day = monthDay;
+ }
+ dt.setDate(day);
+ dt.setMonth(dt.getMonth() + parseInt(n));
+ return dt;
+};
+
+//获得本周的起始日期
+Date.prototype.getWeekStartDate = function () {
+ var w = this.getDay();
+ return this.getOffsetDate(-w);
+};
+//得到本周的结束日期
+Date.prototype.getWeekEndDate = function () {
+ var w = this.getDay();
+ var offset = (w === 0 ? 6 : 6 - w);
+ return this.getOffsetDate(offset);
+};
+
+//获得本季度的起始日期
+Date.prototype.getQuarterStartDate = function () {
+ return new Date(this.getFullYear(), this.getQuarterStartMonth(), 1);
+};
+//得到本季度的结束日期
+Date.prototype.getQuarterEndDate = function () {
+ var quarterEndMonth = this.getQuarterStartMonth() + 2;
+ return new Date(this.getFullYear(), quarterEndMonth, this.getMonthDays(quarterEndMonth));
+};
+Date.prototype.getAfterMultiMonth = function (n) {
+ var dt = new Date(this.getTime());
+ dt.setMonth(dt.getMonth() + n | 0);
+ return dt;
+};
+Date.prototype.getBeforeMultiMonth = function (n) {
+ var dt = new Date(this.getTime());
+ dt.setMonth(dt.getMonth() - n | 0);
+ return dt;
+};
+
+/** Checks date and time equality */
+Date.prototype.equalsTo = function (date) {
+ return ((this.getFullYear() == date.getFullYear()) &&
+ (this.getMonth() == date.getMonth()) &&
+ (this.getDate() == date.getDate()) &&
+ (this.getHours() == date.getHours()) &&
+ (this.getMinutes() == date.getMinutes()) &&
+ (this.getSeconds() == date.getSeconds()));
+};
+
+/** Set only the year, month, date parts (keep existing time) */
+Date.prototype.setDateOnly = function (date) {
+ var tmp = new Date(date);
+ this.setDate(1);
+ this.setFullYear(tmp.getFullYear());
+ this.setMonth(tmp.getMonth());
+ this.setDate(tmp.getDate());
+};
+/** Prints the date in a string according to the given format. */
+Date.prototype.print = function (str) {
+ var m = this.getMonth();
+ var d = this.getDate();
+ var y = this.getFullYear();
+ var wn = this.getWeekNumber();
+ var w = this.getDay();
+ var s = {};
+ var hr = this.getHours();
+ var pm = (hr >= 12);
+ var ir = (pm) ? (hr - 12) : hr;
+ var dy = this.getDayOfYear();
+ if (ir == 0) {
+ ir = 12;
+ }
+ var min = this.getMinutes();
+ var sec = this.getSeconds();
+ s["%a"] = Date._SDN[w]; // abbreviated weekday name [FIXME: I18N]
+ s["%A"] = Date._DN[w]; // full weekday name
+ s["%b"] = Date._SMN[m]; // abbreviated month name [FIXME: I18N]
+ s["%B"] = Date._MN[m]; // full month name
+ // FIXME: %c : preferred date and time representation for the current locale
+ s["%C"] = 1 + Math.floor(y / 100); // the century number
+ s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
+ s["%e"] = d; // the day of the month (range 1 to 31)
+ // FIXME: %D : american date style: %m/%d/%y
+ // FIXME: %E, %F, %G, %g, %h (man strftime)
+ s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
+ s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
+ s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
+ s["%k"] = hr; // hour, range 0 to 23 (24h format)
+ s["%l"] = ir; // hour, range 1 to 12 (12h format)
+ s["%X"] = (m < 9) ? ("0" + (1 + m)) : (1 + m); // month, range 01 to 12
+ s["%x"] = m + 1 // month, range 1 to 12
+ s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
+ s["%n"] = "\n"; // a newline character
+ s["%p"] = pm ? "PM" : "AM";
+ s["%P"] = pm ? "pm" : "am";
+ // FIXME: %r : the time in am/pm notation %I:%M:%S %p
+ // FIXME: %R : the time in 24-hour notation %H:%M
+ s["%s"] = Math.floor(this.getTime() / 1000);
+ s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
+ s["%t"] = "\t"; // a tab character
+ // FIXME: %T : the time in 24-hour notation (%H:%M:%S)
+ s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
+ s["%u"] = w + 1; // the day of the week (range 1 to 7, 1 = MON)
+ s["%w"] = w; // the day of the week (range 0 to 6, 0 = SUN)
+ // FIXME: %x : preferred date representation for the current locale without the time
+ // FIXME: %X : preferred time representation for the current locale without the date
+ s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99)
+ s["%Y"] = y; // year with the century
+ s["%%"] = "%"; // a literal '%' character
+
+ var re = /%./g;
+ if (!BI.isKhtml()) {
+ return str.replace(re, function (par) {
+ return s[par] || par;
+ });
+ }
+
+ var a = str.match(re);
+ for (var i = 0; i < a.length; i++) {
+ var tmp = s[a[i]];
+ if (tmp) {
+ re = new RegExp(a[i], 'g');
+ str = str.replace(re, tmp);
+ }
+ }
+
+ return str;
+};
+
+/**
+ * 是否是闰年
+ * @param year
+ * @returns {boolean}
+ */
+Date.isLeap = function (year) {
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
+};
+
+/**
+ * 检测是否在有效期
+ *
+ * @param YY 年
+ * @param MM 月
+ * @param DD 日
+ * @param minDate '1900-01-01'
+ * @param maxDate '2099-12-31'
+ * @returns {Array} 若无效返回无效状态
+ */
+Date.checkVoid = function (YY, MM, DD, minDate, maxDate) {
+ var back = [];
+ YY = YY | 0;
+ MM = MM | 0;
+ DD = DD | 0;
+ minDate = BI.isString(minDate) ? minDate.match(/\d+/g) : minDate;
+ maxDate = BI.isString(maxDate) ? maxDate.match(/\d+/g) : maxDate;
+ if (YY < minDate[0]) {
+ back = ['y'];
+ } else if (YY > maxDate[0]) {
+ back = ['y', 1];
+ } else if (YY >= minDate[0] && YY <= maxDate[0]) {
+ if (YY == minDate[0]) {
+ if (MM < minDate[1]) {
+ back = ['m'];
+ } else if (MM == minDate[1]) {
+ if (DD < minDate[2]) {
+ back = ['d'];
+ }
+ }
+ }
+ if (YY == maxDate[0]) {
+ if (MM > maxDate[1]) {
+ back = ['m', 1];
+ } else if (MM == maxDate[1]) {
+ if (DD > maxDate[2]) {
+ back = ['d', 1];
+ }
+ }
+ }
+ }
+ return back;
+};
+
+Date.checkLegal = function (str) {
+ var ar = str.match(/\d+/g);
+ var YY = ar[0] | 0, MM = ar[1] | 0, DD = ar[2] | 0;
+ if (ar.length <= 1) {
+ return true;
+ }
+ if (ar.length <= 2) {
+ return MM >= 1 && MM <= 12;
+ }
+ var MD = Date._MD.slice(0);
+ MD[1] = Date.isLeap(YY) ? 29 : 28;
+ return MM >= 1 && MM <= 12 && DD <= MD[MM - 1];
+};
+
+Date.parseDateTime = function (str, fmt) {
+ var today = new Date();
+ var y = 0;
+ var m = 0;
+ var d = 1;
+ //wei : 对于fmt为‘YYYYMM’或者‘YYYYMMdd’的格式,str的值为类似'201111'的形式,因为年月之间没有分隔符,所以正则表达式分割无效,导致bug7376。
+ var a = str.split(/\W+/);
+ if (fmt.toLowerCase() == '%y%x' || fmt.toLowerCase() == '%y%x%d') {
+ var yearlength = 4;
+ var otherlength = 2;
+ a[0] = str.substring(0, yearlength);
+ a[1] = str.substring(yearlength, yearlength + otherlength);
+ a[2] = str.substring(yearlength + otherlength, yearlength + otherlength * 2);
+ }
+ var b = fmt.match(/%./g);
+ var i = 0, j = 0;
+ var hr = 0;
+ var min = 0;
+ var sec = 0;
+ for (i = 0; i < a.length; ++i) {
+ switch (b[i]) {
+ case "%d":
+ case "%e":
+ d = parseInt(a[i], 10);
+ break;
+
+ case "%X":
+ m = parseInt(a[i], 10) - 1;
+ break;
+ case "%x":
+ m = parseInt(a[i], 10) - 1;
+ break;
+
+ case "%Y":
+ case "%y":
+ y = parseInt(a[i], 10);
+ (y < 100) && (y += (y > 29) ? 1900 : 2000);
+ break;
+
+ case "%b":
+ case "%B":
+ for (j = 0; j < 12; ++j) {
+ if (Date._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) {
+ m = j;
+ break;
+ }
+ }
+ break;
+
+ case "%H":
+ case "%I":
+ case "%k":
+ case "%l":
+ hr = parseInt(a[i], 10);
+ break;
+
+ case "%P":
+ case "%p":
+ if (/pm/i.test(a[i]) && hr < 12) {
+ hr += 12;
+ } else if (/am/i.test(a[i]) && hr >= 12) {
+ hr -= 12;
+ }
+ break;
+
+ case "%M":
+ min = parseInt(a[i], 10);
+ case "%S":
+ sec = parseInt(a[i], 10);
+ break;
+ }
+ }
+// if (!a[i]) {
+// continue;
+// }
+ if (isNaN(y)) {
+ y = today.getFullYear();
+ }
+ if (isNaN(m)) {
+ m = today.getMonth();
+ }
+ if (isNaN(d)) {
+ d = today.getDate();
+ }
+ if (isNaN(hr)) {
+ hr = today.getHours();
+ }
+ if (isNaN(min)) {
+ min = today.getMinutes();
+ }
+ if (isNaN(sec)) {
+ sec = today.getSeconds();
+ }
+ if (y != 0) {
+ return new Date(y, m, d, hr, min, sec);
+ }
+ y = 0;
+ m = -1;
+ d = 0;
+ for (i = 0; i < a.length; ++i) {
+ if (a[i].search(/[a-zA-Z]+/) != -1) {
+ var t = -1;
+ for (j = 0; j < 12; ++j) {
+ if (Date._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) {
+ t = j;
+ break;
+ }
+ }
+ if (t != -1) {
+ if (m != -1) {
+ d = m + 1;
+ }
+ m = t;
+ }
+ } else if (parseInt(a[i], 10) <= 12 && m == -1) {
+ m = a[i] - 1;
+ } else if (parseInt(a[i], 10) > 31 && y == 0) {
+ y = parseInt(a[i], 10);
+ (y < 100) && (y += (y > 29) ? 1900 : 2000);
+ } else if (d == 0) {
+ d = a[i];
+ }
+ }
+ if (y == 0) {
+ y = today.getFullYear();
+ }
+ if (m != -1 && d != 0) {
+ return new Date(y, m, d, hr, min, sec);
+ }
+ return today;
+};
+/*
+ * 给jQuery.Event对象添加的工具方法
+ */
+$.extend($.Event.prototype, {
+ // event.stopEvent
+ stopEvent: function () {
+ this.stopPropagation();
+ this.preventDefault();
+ }
+});Function.prototype.before = function (func) {
+ var __self = this;
+ return function () {
+ if (func.apply(this, arguments) === false) {
+ return false;
+ }
+ return __self.apply(this, arguments);
+ }
+};
+
+Function.prototype.after = function (func) {
+ var __self = this;
+ return function () {
+ var ret = __self.apply(this, arguments);
+ if (ret === false) {
+ return false;
+ }
+ func.apply(this, arguments);
+ return ret;
+ }
+};/*!
+ * jLayout JQuery Plugin v0.11
+ *
+ * Licensed under the revised BSD License.
+ * Copyright 2008, Bram Stein
+ * All rights reserved.
+ */
+if (jQuery) {
+ (function ($) {
+ // richer:容器在其各个边缘留出的空间
+ if (!$.fn.insets) {
+ $.fn.insets = function () {
+ var p = this.padding(),
+ b = this.border();
+ return {
+ 'top': p.top,
+ 'bottom': p.bottom + b.bottom + b.top,
+ 'left': p.left,
+ 'right': p.right + b.right + b.left
+ };
+ };
+ }
+
+ // richer:获取 && 设置jQuery元素的边界
+ if (!$.fn.bounds) {
+ $.fn.bounds = function (value) {
+ var tmp = {hasIgnoredBounds: true};
+
+ if (value) {
+ if (!isNaN(value.x)) {
+ tmp.left = value.x;
+ }
+ if (!isNaN(value.y)) {
+ tmp.top = value.y;
+ }
+ if (value.width != null) {
+ tmp.width = (value.width - (this.outerWidth(true) - this.width()));
+ tmp.width = (tmp.width >= 0) ? tmp.width : value.width;
+ // fix chrome
+ //tmp.width = (tmp.width >= 0) ? tmp.width : 0;
+ }
+ if (value.height != null) {
+ tmp.height = value.height - (this.outerHeight(true) - this.height());
+ tmp.height = (tmp.height >= 0) ? tmp.height : value.height;
+ // fix chrome
+ //tmp.height = (tmp.height >= 0) ? tmp.height : value.0;
+ }
+ this.css(tmp);
+ return this;
+ }
+ else {
+ // richer:注意此方法只对可见元素有效
+ tmp = this.position();
+ return {
+ 'x': tmp.left,
+ 'y': tmp.top,
+ // richer:这里计算外部宽度和高度的时候,都不包括边框
+ 'width': this.outerWidth(),
+ 'height': this.outerHeight()
+ };
+ }
+ };
+ }
+ })(jQuery);
+}
+;if (!Number.prototype.toFixed || (0.00008).toFixed(3) !== '0.000' ||
+ (0.9).toFixed(0) === '0' || (1.255).toFixed(2) !== '1.25' ||
+ (1000000000000000128).toFixed(0) !== "1000000000000000128") {
+ (function () {
+ var base, size, data, i;
+ base = 1e7;
+ size = 6;
+ data = [0, 0, 0, 0, 0, 0];
+ function multiply(n, c) {
+ var i = -1;
+ while (++i < size) {
+ c += n * data[i];
+ data[i] = c % base;
+ c = Math.floor(c / base);
+ }
+ }
+
+ function divide(n) {
+ var i = size, c = 0;
+ while (--i >= 0) {
+ c += data[i];
+ data[i] = Math.floor(c / n);
+ c = (c % n) * base;
+ }
+ }
+
+ function toString() {
+ var i = size;
+ var s = '';
+ while (--i >= 0) {
+ if (s !== '' || i === 0 || data[i] !== 0) {
+ var t = String(data[i]);
+ if (s === '') {
+ s = t;
+ } else {
+ s += '0000000'.slice(0, 7 - t.length) + t;
+ }
+ }
+ }
+ return s;
+ }
+
+ function pow(x, n, acc) {
+ return (n === 0 ? acc : (n % 2 === 1 ? pow(x, n - 1, acc * x)
+ : pow(x * x, n / 2, acc)));
+ }
+
+ function log(x) {
+ var n = 0;
+ while (x >= 4096) {
+ n += 12;
+ x /= 4096;
+ }
+ while (x >= 2) {
+ n += 1;
+ x /= 2;
+ }
+ return n;
+ }
+
+ Number.prototype.toFixed = function (fractionDigits) {
+ var f, x, s, m, e, z, j, k;
+ f = Number(fractionDigits);
+ f = f !== f ? 0 : Math.floor(f);
+
+ if (f < 0 || f > 20) {
+ throw new RangeError('Number.toFixed called with invalid number of decimals');
+ }
+
+ x = Number(this);
+
+ if (x !== x) {
+ return "NaN";
+ }
+
+ if (x <= -1e21 || x > 1e21) {
+ return String(x);
+ }
+
+ s = "";
+
+ if (x < 0) {
+ s = "-";
+ x = -x;
+ }
+
+ m = "0";
+
+ if (x > 1e-21) {
+ //1e-21
0) {
+ multiply(0, z);
+ j = f;
+
+ while (j >= 7) {
+ multiply(1e7, 0);
+ j -= 7;
+ }
+
+ multiply(pow(10, j, 1), 0);
+ j = e - 1;
+
+ while (j >= 23) {
+ divide(1 << 23);
+ j -= 23;
+ }
+ divide(1 << j);
+ multiply(1, 1);
+ divide(2);
+ m = toString();
+ } else {
+ multiply(0, z);
+ multiply(1 << (-e), 0);
+ m = toString() + '0.00000000000000000000'.slice(2, 2 + f);
+ }
+ }
+
+ if (f > 0) {
+ k = m.length;
+
+ if (k <= f) {
+ m = s + '0.0000000000000000000'.slice(0, f - k + 2) + m;
+ } else {
+ m = s + m.slice(0, k - f) + '.' + m.slice(k - f);
+ }
+ } else {
+ m = s + m;
+ }
+
+ return m;
+ }
+
+ })();
+}
+
+
+/**
+ ** 加法函数,用来得到精确的加法结果
+ ** 说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
+ ** 调用:accAdd(arg1,arg2)
+ ** 返回值:arg1加上arg2的精确结果
+ **/
+function accAdd(arg1, arg2) {
+ var r1, r2, m, c;
+ try {
+ r1 = arg1.toString().split(".")[1].length;
+ }
+ catch (e) {
+ r1 = 0;
+ }
+ try {
+ r2 = arg2.toString().split(".")[1].length;
+ }
+ catch (e) {
+ r2 = 0;
+ }
+ c = Math.abs(r1 - r2);
+ m = Math.pow(10, Math.max(r1, r2));
+ if (c > 0) {
+ var cm = Math.pow(10, c);
+ if (r1 > r2) {
+ arg1 = Number(arg1.toString().replace(".", ""));
+ arg2 = Number(arg2.toString().replace(".", "")) * cm;
+ } else {
+ arg1 = Number(arg1.toString().replace(".", "")) * cm;
+ arg2 = Number(arg2.toString().replace(".", ""));
+ }
+ } else {
+ arg1 = Number(arg1.toString().replace(".", ""));
+ arg2 = Number(arg2.toString().replace(".", ""));
+ }
+ return (arg1 + arg2) / m;
+}
+
+//给Number类型增加一个add方法,调用起来更加方便。
+Number.prototype.add = function (arg) {
+ return accAdd(arg, this);
+};
+/**
+ ** 减法函数,用来得到精确的减法结果
+ ** 说明:javascript的减法结果会有误差,在两个浮点数相减的时候会比较明显。这个函数返回较为精确的减法结果。
+ ** 调用:accSub(arg1,arg2)
+ ** 返回值:arg1加上arg2的精确结果
+ **/
+function accSub(arg1, arg2) {
+ var r1, r2, m, n;
+ try {
+ r1 = arg1.toString().split(".")[1].length;
+ }
+ catch (e) {
+ r1 = 0;
+ }
+ try {
+ r2 = arg2.toString().split(".")[1].length;
+ }
+ catch (e) {
+ r2 = 0;
+ }
+ m = Math.pow(10, Math.max(r1, r2)); //last modify by deeka //动态控制精度长度
+ n = (r1 >= r2) ? r1 : r2;
+ return ((arg1 * m - arg2 * m) / m).toFixed(n);
+}
+
+// 给Number类型增加一个mul方法,调用起来更加方便。
+Number.prototype.sub = function (arg) {
+ return accSub(this, arg);
+};
+/**
+ ** 乘法函数,用来得到精确的乘法结果
+ ** 说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
+ ** 调用:accMul(arg1,arg2)
+ ** 返回值:arg1乘以 arg2的精确结果
+ **/
+function accMul(arg1, arg2) {
+ var m = 0, s1 = arg1.toString(), s2 = arg2.toString();
+ try {
+ m += s1.split(".")[1].length;
+ }
+ catch (e) {
+ }
+ try {
+ m += s2.split(".")[1].length;
+ }
+ catch (e) {
+ }
+ return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
+}
+
+// 给Number类型增加一个mul方法,调用起来更加方便。
+Number.prototype.mul = function (arg) {
+ return accMul(arg, this);
+};
+/**
+ ** 除法函数,用来得到精确的除法结果
+ ** 说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
+ ** 调用:accDiv(arg1,arg2)
+ ** 返回值:arg1除以arg2的精确结果
+ **/
+function accDiv(arg1, arg2) {
+ var t1 = 0, t2 = 0, r1, r2;
+ try {
+ t1 = arg1.toString().split(".")[1].length;
+ }
+ catch (e) {
+ }
+ try {
+ t2 = arg2.toString().split(".")[1].length;
+ }
+ catch (e) {
+ }
+ with (Math) {
+ r1 = Number(arg1.toString().replace(".", ""));
+ r2 = Number(arg2.toString().replace(".", ""));
+ return (t2 > t1) ? (r1 / r2) * pow(10, t2 - t1) : (r1 / r2) / pow(10, t1 - t2);
+ }
+}
+
+//给Number类型增加一个div方法,调用起来更加方便。
+Number.prototype.div = function (arg) {
+ return accDiv(this, arg);
+};/**
+ * 对字符串对象的扩展
+ * @class String
+ */
+$.extend(String.prototype, {
+
+ /**
+ * 判断字符串是否已指定的字符串开始
+ * @param {String} startTag 指定的开始字符串
+ * @return {Boolean} 如果字符串以指定字符串开始则返回true,否则返回false
+ */
+ startWith: function (startTag) {
+ if (startTag == null || startTag == "" || this.length === 0 || startTag.length > this.length) {
+ return false;
+ }
+ return this.substr(0, startTag.length) == startTag;
+ },
+ /**
+ * 判断字符串是否以指定的字符串结束
+ * @param {String} endTag 指定的字符串
+ * @return {Boolean} 如果字符串以指定字符串结束则返回true,否则返回false
+ */
+ endWith: function (endTag) {
+ if (endTag == null || endTag == "" || this.length === 0 || endTag.length > this.length) {
+ return false;
+ }
+ return this.substring(this.length - endTag.length) == endTag;
+ },
+
+ /**
+ * 获取url中指定名字的参数
+ * @param {String} name 参数的名字
+ * @return {String} 参数的值
+ */
+ getQuery: function (name) {
+ var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
+ var r = this.substr(this.indexOf("?") + 1).match(reg);
+ if (r) {
+ return unescape(r[2]);
+ }
+ return null;
+ },
+
+ /**
+ * 给url加上给定的参数
+ * @param {Object} paras 参数对象,是一个键值对对象
+ * @return {String} 添加了给定参数的url
+ */
+ appendQuery: function (paras) {
+ if (!paras) {
+ return this;
+ }
+ var src = this;
+ // 没有问号说明还没有参数
+ if (src.indexOf("?") === -1) {
+ src += "?";
+ }
+ // 如果以问号结尾,说明没有其他参数
+ if (src.endWith("?") !== false) {
+ } else {
+ src += "&";
+ }
+ $.each(paras, function (name, value) {
+ if (typeof(name) === 'string') {
+ src += name + "=" + value + "&";
+ }
+ });
+ src = src.substr(0, src.length - 1);
+ return src;
+ },
+ /**
+ * 将所有符合第一个字符串所表示的字符串替换成为第二个字符串
+ * @param {String} s1 要替换的字符串的正则表达式
+ * @param {String} s2 替换的结果字符串
+ * @returns {String} 替换后的字符串
+ */
+ replaceAll: function (s1, s2) {
+ return this.replace(new RegExp(s1, "gm"), s2);
+ },
+ /**
+ * 总是让字符串以指定的字符开头
+ * @param {String} start 指定的字符
+ * @returns {String} 以指定字符开头的字符串
+ */
+ perfectStart: function (start) {
+ if (this.startWith(start)) {
+ return this;
+ } else {
+ return start + this;
+ }
+ },
+
+ /**
+ * 获取字符串中某字符串的所有项位置数组
+ * @param {String} sub 子字符串
+ * @return {Number[]} 子字符串在父字符串中出现的所有位置组成的数组
+ */
+ allIndexOf: function (sub) {
+ if (typeof sub != 'string') {
+ return [];
+ }
+ var str = this;
+ var location = [];
+ var offset = 0;
+ while (str.length > 0) {
+ var loc = str.indexOf(sub);
+ if (loc === -1) {
+ break;
+ }
+ location.push(offset + loc);
+ str = str.substring(loc + sub.length, str.length);
+ offset += loc + sub.length;
+ }
+ return location;
+ }
+});
+
+/**
+ * 对字符串对象的扩展
+ * @class String
+ */
+$.extend(String, {
+
+ /**
+ * 对字符串中的'和\做编码处理
+ * @static
+ * @param {String} string 要做编码处理的字符串
+ * @return {String} 编码后的字符串
+ */
+ escape: function (string) {
+ return string.replace(/('|\\)/g, "\\$1");
+ },
+
+ /**
+ * 让字符串通过指定字符做补齐的函数
+ *
+ * var s = String.leftPad('123', 5, '0');//s的值为:'00123'
+ *
+ * @static
+ * @param {String} val 原始值
+ * @param {Number} size 总共需要的位数
+ * @param {String} ch 用于补齐的字符
+ * @return {String} 补齐后的字符串
+ */
+ leftPad: function (val, size, ch) {
+ var result = String(val);
+ if (!ch) {
+ ch = " ";
+ }
+ while (result.length < size) {
+ result = ch + result;
+ }
+ return result.toString();
+ },
+
+ /**
+ * 对字符串做替换的函数
+ *
+ * var cls = 'my-class', text = 'Some text';
+ * var res = String.format('Some text
';
+ *
+ * @static
+ * @param {String} format 要做替换的字符串,替换字符串1,替换字符串2...
+ * @return {String} 做了替换后的字符串
+ */
+ format: function (format) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return format.replace(/\{(\d+)\}/g, function (m, i) {
+ return args[i];
+ });
+ }
+});BI.EventListener = {
+ listen: function listen(target, eventType, callback) {
+ if (target.addEventListener) {
+ target.addEventListener(eventType, callback, false);
+ return {
+ remove: function remove() {
+ target.removeEventListener(eventType, callback, false);
+ }
+ };
+ } else if (target.attachEvent) {
+ target.attachEvent('on' + eventType, callback);
+ return {
+ remove: function remove() {
+ target.detachEvent('on' + eventType, callback);
+ }
+ };
+ }
+ },
+
+ capture: function capture(target, eventType, callback) {
+ if (target.addEventListener) {
+ target.addEventListener(eventType, callback, true);
+ return {
+ remove: function remove() {
+ target.removeEventListener(eventType, callback, true);
+ }
+ };
+ } else {
+ return {
+ remove: BI.emptyFn
+ };
+ }
+ },
+
+ registerDefault: function registerDefault() {
+ }
+};!(function () {
+ var cancelAnimationFrame =
+ window.cancelAnimationFrame ||
+ window.webkitCancelAnimationFrame ||
+ window.mozCancelAnimationFrame ||
+ window.oCancelAnimationFrame ||
+ window.msCancelAnimationFrame ||
+ window.clearTimeout;
+
+ var requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || window.setTimeout;
+
+
+ BI.MouseMoveTracker = function (onMove, onMoveEnd, domNode) {
+ this._isDragging = false;
+ this._animationFrameID = null;
+ this._domNode = domNode;
+ this._onMove = onMove;
+ this._onMoveEnd = onMoveEnd;
+
+ this._onMouseMove = BI.bind(this._onMouseMove, this);
+ this._onMouseUp = BI.bind(this._onMouseUp, this);
+ this._didMouseMove = BI.bind(this._didMouseMove, this);
+ };
+ BI.MouseMoveTracker.prototype = {
+ constructor: BI.MouseMoveTracker,
+ captureMouseMoves: function (/*object*/ event) {
+ if (!this._eventMoveToken && !this._eventUpToken) {
+ this._eventMoveToken = BI.EventListener.listen(
+ this._domNode,
+ 'mousemove',
+ this._onMouseMove
+ );
+ this._eventUpToken = BI.EventListener.listen(
+ this._domNode,
+ 'mouseup',
+ this._onMouseUp
+ );
+ }
+
+ if (!this._isDragging) {
+ this._deltaX = 0;
+ this._deltaY = 0;
+ this._isDragging = true;
+ this._x = event.clientX;
+ this._y = event.clientY;
+ }
+ event.preventDefault ? event.preventDefault() : (event.returnValue = false);
+ },
+
+ releaseMouseMoves: function () {
+ if (this._eventMoveToken && this._eventUpToken) {
+ this._eventMoveToken.remove();
+ this._eventMoveToken = null;
+ this._eventUpToken.remove();
+ this._eventUpToken = null;
+ }
+
+ if (this._animationFrameID !== null) {
+ cancelAnimationFrame(this._animationFrameID);
+ this._animationFrameID = null;
+ }
+
+ if (this._isDragging) {
+ this._isDragging = false;
+ this._x = null;
+ this._y = null;
+ }
+ },
+
+ isDragging: function () /*boolean*/ {
+ return this._isDragging;
+ },
+
+ _onMouseMove: function (/*object*/ event) {
+ var x = event.clientX;
+ var y = event.clientY;
+
+ this._deltaX += (x - this._x);
+ this._deltaY += (y - this._y);
+
+ if (this._animationFrameID === null) {
+ // The mouse may move faster then the animation frame does.
+ // Use `requestAnimationFrame` to avoid over-updating.
+ this._animationFrameID =
+ requestAnimationFrame(this._didMouseMove);
+ }
+
+ this._x = x;
+ this._y = y;
+ event.preventDefault ? event.preventDefault() : (event.returnValue = false);
+ },
+
+ _didMouseMove: function () {
+ this._animationFrameID = null;
+ this._onMove(this._deltaX, this._deltaY);
+ this._deltaX = 0;
+ this._deltaY = 0;
+ },
+
+ _onMouseUp: function () {
+ if (this._animationFrameID) {
+ this._didMouseMove();
+ }
+ this._onMoveEnd();
+ }
+ };
+})();!(function () {
+ var PIXEL_STEP = 10;
+ var LINE_HEIGHT = 40;
+ var PAGE_HEIGHT = 800;
+ var requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || window.setTimeout;
+
+ function normalizeWheel(/*object*/event) /*object*/ {
+ var sX = 0,
+ sY = 0,
+ // spinX, spinY
+ pX = 0,
+ pY = 0; // pixelX, pixelY
+
+ // Legacy
+ if ('detail' in event) {
+ sY = event.detail;
+ }
+ if ('wheelDelta' in event) {
+ sY = -event.wheelDelta / 120;
+ }
+ if ('wheelDeltaY' in event) {
+ sY = -event.wheelDeltaY / 120;
+ }
+ if ('wheelDeltaX' in event) {
+ sX = -event.wheelDeltaX / 120;
+ }
+
+ // side scrolling on FF with DOMMouseScroll
+ if ('axis' in event && event.axis === event.HORIZONTAL_AXIS) {
+ sX = sY;
+ sY = 0;
+ }
+
+ pX = sX * PIXEL_STEP;
+ pY = sY * PIXEL_STEP;
+
+ if ('deltaY' in event) {
+ pY = event.deltaY;
+ }
+ if ('deltaX' in event) {
+ pX = event.deltaX;
+ }
+
+ if ((pX || pY) && event.deltaMode) {
+ if (event.deltaMode === 1) {
+ // delta in LINE units
+ pX *= LINE_HEIGHT;
+ pY *= LINE_HEIGHT;
+ } else {
+ // delta in PAGE units
+ pX *= PAGE_HEIGHT;
+ pY *= PAGE_HEIGHT;
+ }
+ }
+
+ // Fall-back if spin cannot be determined
+ if (pX && !sX) {
+ sX = pX < 1 ? -1 : 1;
+ }
+ if (pY && !sY) {
+ sY = pY < 1 ? -1 : 1;
+ }
+
+ return {
+ spinX: sX,
+ spinY: sY,
+ pixelX: pX,
+ pixelY: pY
+ };
+ }
+
+ BI.WheelHandler = function (onWheel, handleScrollX, handleScrollY, stopPropagation) {
+ this._animationFrameID = null;
+ this._deltaX = 0;
+ this._deltaY = 0;
+ this._didWheel = BI.bind(this._didWheel, this);
+ if (typeof handleScrollX !== 'function') {
+ handleScrollX = handleScrollX ?
+ function () {
+ return true
+ } :
+ function () {
+ return false
+ };
+ }
+
+ if (typeof handleScrollY !== 'function') {
+ handleScrollY = handleScrollY ?
+ function () {
+ return true
+ } :
+ function () {
+ return false
+ };
+ }
+
+ if (typeof stopPropagation !== 'function') {
+ stopPropagation = stopPropagation ?
+ function () {
+ return true
+ } :
+ function () {
+ return false
+ };
+ }
+
+ this._handleScrollX = handleScrollX;
+ this._handleScrollY = handleScrollY;
+ this._stopPropagation = stopPropagation;
+ this._onWheelCallback = onWheel;
+ this.onWheel = BI.bind(this.onWheel, this);
+ };
+ BI.WheelHandler.prototype = {
+ constructor: BI.WheelHandler,
+ onWheel: function (/*object*/ event) {
+ var normalizedEvent = normalizeWheel(event);
+ var deltaX = this._deltaX + normalizedEvent.pixelX;
+ var deltaY = this._deltaY + normalizedEvent.pixelY;
+ var handleScrollX = this._handleScrollX(deltaX, deltaY);
+ var handleScrollY = this._handleScrollY(deltaY, deltaX);
+ if (!handleScrollX && !handleScrollY) {
+ return;
+ }
+
+ this._deltaX += handleScrollX ? normalizedEvent.pixelX : 0;
+ this._deltaY += handleScrollY ? normalizedEvent.pixelY : 0;
+ event.preventDefault ? event.preventDefault() : (event.returnValue = false);
+
+ var changed;
+ if (this._deltaX !== 0 || this._deltaY !== 0) {
+ if (this._stopPropagation()) {
+ event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true);
+ }
+ changed = true;
+ }
+
+ if (changed === true && this._animationFrameID === null) {
+ this._animationFrameID = requestAnimationFrame(this._didWheel);
+ }
+ },
+
+ _didWheel: function () {
+ this._animationFrameID = null;
+ this._onWheelCallback(this._deltaX, this._deltaY);
+ this._deltaX = 0;
+ this._deltaY = 0;
+ }
+ };
+})();/**
+ * 常量
+ */
+
+_.extend(BI, {
+ MAX: 0xfffffffffffffff,
+ MIN: -0xfffffffffffffff,
+ EVENT_RESPONSE_TIME: 200,
+ zIndex_layer: 1e5,
+ zIndex_floatbox: 1e6,
+ zIndex_popup: 1e7,
+ zIndex_masker: 1e8,
+ zIndex_tip: 1e9,
+ emptyStr: "",
+ emptyFn: function () {
+ },
+ empty: null,
+ KeyCode: {
+ BACKSPACE: 8,
+ COMMA: 188,
+ DELETE: 46,
+ DOWN: 40,
+ END: 35,
+ ENTER: 13,
+ ESCAPE: 27,
+ HOME: 36,
+ LEFT: 37,
+ NUMPAD_ADD: 107,
+ NUMPAD_DECIMAL: 110,
+ NUMPAD_DIVIDE: 111,
+ NUMPAD_ENTER: 108,
+ NUMPAD_MULTIPLY: 106,
+ NUMPAD_SUBTRACT: 109,
+ PAGE_DOWN: 34,
+ PAGE_UP: 33,
+ PERIOD: 190,
+ RIGHT: 39,
+ SPACE: 32,
+ TAB: 9,
+ UP: 38
+ },
+ Status: {
+ SUCCESS: 1,
+ WRONG: 2,
+ START: 3,
+ END: 4,
+ WAITING: 5,
+ READY: 6,
+ RUNNING: 7,
+ OUTOFBOUNDS: 8,
+ NULL: -1
+ },
+ Direction: {
+ Top: "top",
+ Bottom: "bottom",
+ Left: "left",
+ Right: "right",
+ Custom: "custom"
+ },
+ Axis: {
+ Vertical: "vertical",
+ Horizontal: "horizontal"
+ },
+ Selection: {
+ Default: -2,
+ None: -1,
+ Single: 0,
+ Multi: 1,
+ All: 2
+ },
+ HorizontalAlign: {
+ Left: "left",
+ Right: "right",
+ Center: "center"
+ },
+ VerticalAlign: {
+ Middle: "middle",
+ Top: "top",
+ Bottom: "bottom"
+ }
+});BI.version = "2.0";/**
+ * absolute实现的居中布局
+ * @class BI.AbsoluteCenterLayout
+ * @extends BI.Layout
+ */
+BI.AbsoluteCenterLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.AbsoluteCenterLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-absolute-center-layout",
+ hgap: 0,
+ lgap: 0,
+ rgap: 0,
+ vgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+
+ render: function () {
+ BI.AbsoluteCenterLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.AbsoluteCenterLayout.superclass._addElement.apply(this, arguments);
+ w.element.css({
+ "position": "absolute",
+ "left": o.hgap + o.lgap + (item.lgap || 0),
+ "right": o.hgap + o.rgap + (item.rgap || 0),
+ "top": o.vgap + o.tgap + (item.tgap || 0),
+ "bottom": o.vgap + o.bgap + (item.bgap || 0),
+ "margin": "auto"
+ });
+ return w;
+ },
+
+ resize: function () {
+ // console.log("absolute_center_adapt布局不需要resize");
+ },
+
+ populate: function (items) {
+ BI.AbsoluteCenterLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.absolute_center_adapt', BI.AbsoluteCenterLayout);/**
+ * absolute实现的居中布局
+ * @class BI.AbsoluteHorizontalLayout
+ * @extends BI.Layout
+ */
+BI.AbsoluteHorizontalLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.AbsoluteHorizontalLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-absolute-horizontal-layout",
+ hgap: 0,
+ lgap: 0,
+ rgap: 0,
+ vgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+
+ render: function () {
+ BI.AbsoluteHorizontalLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.AbsoluteHorizontalLayout.superclass._addElement.apply(this, arguments);
+ w.element.css({
+ "position": "absolute",
+ "left": o.hgap + o.lgap + (item.lgap || 0),
+ "right": o.hgap + o.rgap + (item.rgap || 0),
+ "margin": "auto"
+ });
+ if (o.vgap + o.tgap + (item.tgap || 0) !== 0) {
+ w.element.css("top", o.vgap + o.tgap + (item.tgap || 0));
+ }
+ if (o.vgap + o.bgap + (item.bgap || 0) !== 0) {
+ w.element.css("bottom", o.vgap + o.bgap + (item.bgap || 0));
+ }
+ return w;
+ },
+
+ resize: function () {
+ // console.log("absolute_horizontal_adapt布局不需要resize");
+ },
+
+ populate: function (items) {
+ BI.AbsoluteHorizontalLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.absolute_horizontal_adapt', BI.AbsoluteHorizontalLayout);/**
+ * absolute实现的居中布局
+ * @class BI.AbsoluteVerticalLayout
+ * @extends BI.Layout
+ */
+BI.AbsoluteVerticalLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.AbsoluteVerticalLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-absolute-vertical-layout",
+ hgap: 0,
+ lgap: 0,
+ rgap: 0,
+ vgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+
+ render: function () {
+ BI.AbsoluteVerticalLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.AbsoluteVerticalLayout.superclass._addElement.apply(this, arguments);
+ w.element.css({
+ "position": "absolute",
+ "left": item.lgap,
+ "right": item.rgap,
+ "top": o.vgap + o.tgap + (item.tgap || 0),
+ "bottom": o.vgap + o.bgap + (item.bgap || 0),
+ "margin": "auto"
+ });
+ if (o.hgap + o.lgap + (item.lgap || 0) !== 0) {
+ w.element.css("left", o.hgap + o.lgap + (item.lgap || 0));
+ }
+ if (o.hgap + o.rgap + (item.rgap || 0) !== 0) {
+ w.element.css("right", o.hgap + o.rgap + (item.rgap || 0));
+ }
+ return w;
+ },
+
+ resize: function () {
+ // console.log("absolute_vertical_adapt布局不需要resize");
+ },
+
+ populate: function (items) {
+ BI.AbsoluteVerticalLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.absolute_vertical_adapt', BI.AbsoluteVerticalLayout);/**
+ * 自适应水平和垂直方向都居中容器
+ * @class BI.CenterAdaptLayout
+ * @extends BI.Layout
+ */
+BI.CenterAdaptLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.CenterAdaptLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-center-adapt-layout",
+ columnSize: [],
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+ render: function () {
+ BI.CenterAdaptLayout.superclass.render.apply(this, arguments);
+ this.$table = $("").attr({"cellspacing": 0, "cellpadding": 0}).css({
+ "position": "relative",
+ "width": "100%",
+ "height": "100%",
+ "white-space": "nowrap",
+ "border-spacing": "0px",
+ "border": "none",
+ "border-collapse": "separate"
+ });
+ this.$tr = $("");
+ this.$tr.appendTo(this.$table);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var td;
+ var width = o.columnSize[i] <= 1 ? (o.columnSize[i] * 100 + "%") : o.columnSize[i];
+ if (!this.hasWidget(this._getChildName(i))) {
+ var w = BI.createWidget(item);
+ w.element.css({"position": "relative", "top": "0", "left": "0", "margin": "0px auto"});
+ td = BI.createWidget({
+ type: "bi.default",
+ tagName: "td",
+ attributes: {
+ width: width
+ },
+ items: [w]
+ });
+ this.addWidget(this._getChildName(i), td);
+ } else {
+ td = this.getWidgetByName(this._getChildName(i));
+ td.element.attr("width", width);
+ }
+ td.element.css({"max-width": o.columnSize[i]});
+ if (i === 0) {
+ td.element.addClass("first-element");
+ }
+ td.element.css({
+ "position": "relative",
+ "height": "100%",
+ "vertical-align": "middle",
+ "margin": "0",
+ "padding": "0",
+ "border": "none"
+ });
+ if (o.hgap + o.lgap + (item.lgap || 0) !== 0) {
+ w.element.css({
+ "margin-left": o.hgap + o.lgap + (item.lgap || 0) + "px"
+ })
+ }
+ if (o.hgap + o.rgap + (item.rgap || 0) !== 0) {
+ w.element.css({
+ "margin-right": o.hgap + o.rgap + (item.rgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.tgap + (item.tgap || 0) !== 0) {
+ w.element.css({
+ "margin-top": o.vgap + o.tgap + (item.tgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.bgap + (item.bgap || 0) !== 0) {
+ w.element.css({
+ "margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + "px"
+ })
+ }
+ return td;
+ },
+
+ _mountChildren: function () {
+ var self = this;
+ var frag = document.createDocumentFragment();
+ var hasChild = false;
+ BI.each(this._children, function (i, widget) {
+ if (widget.element !== self.element) {
+ frag.appendChild(widget.element[0]);
+ hasChild = true;
+ }
+ });
+ if (hasChild === true) {
+ this.$tr.append(frag);
+ this.element.append(this.$table);
+ }
+ },
+
+ resize: function () {
+ // console.log("center_adapt布局不需要resize");
+ },
+
+ _getWrapper: function(){
+ return this.$tr;
+ },
+
+ populate: function (items) {
+ BI.CenterAdaptLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.center_adapt', BI.CenterAdaptLayout);/**
+ * 水平方向居中容器
+ * @class BI.HorizontalAdaptLayout
+ * @extends BI.Layout
+ */
+BI.HorizontalAdaptLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.HorizontalAdaptLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-horizontal-adapt-layout",
+ verticalAlign: BI.VerticalAlign.Middle,
+ columnSize: [],
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+ render: function () {
+ BI.HorizontalAdaptLayout.superclass.render.apply(this, arguments);
+ this.$table = $("").attr({"cellspacing": 0, "cellpadding": 0}).css({
+ "position": "relative",
+ "width": "100%",
+ "white-space": "nowrap",
+ "border-spacing": "0px",
+ "border": "none",
+ "border-collapse": "separate"
+ });
+ this.$tr = $("");
+ this.$tr.appendTo(this.$table);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var td;
+ var width = o.columnSize[i] <= 1 ? (o.columnSize[i] * 100 + "%") : o.columnSize[i];
+ if (!this.hasWidget(this._getChildName(i))) {
+ var w = BI.createWidget(item);
+ w.element.css({"position": "relative", "top": "0", "left": "0", "margin": "0px auto"});
+ td = BI.createWidget({
+ type: "bi.default",
+ tagName: "td",
+ attributes: {
+ width: width
+ },
+ items: [w]
+ });
+ this.addWidget(this._getChildName(i), td);
+ } else {
+ td = this.getWidgetByName(this._getChildName(i));
+ td.element.attr("width", width);
+ }
+ td.element.css({"max-width": o.columnSize[i] + "px"});
+ if (i === 0) {
+ td.element.addClass("first-element");
+ }
+ td.element.css({
+ "position": "relative",
+ "vertical-align": o.verticalAlign,
+ "margin": "0",
+ "padding": "0",
+ "border": "none"
+ });
+ if (o.hgap + o.lgap + (item.lgap || 0) !== 0) {
+ w.element.css({
+ "margin-left": o.hgap + o.lgap + (item.lgap || 0) + "px"
+ })
+ }
+ if (o.hgap + o.rgap + (item.rgap || 0) !== 0) {
+ w.element.css({
+ "margin-right": o.hgap + o.rgap + (item.rgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.tgap + (item.tgap || 0) !== 0) {
+ w.element.css({
+ "margin-top": o.vgap + o.tgap + (item.tgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.bgap + (item.bgap || 0) !== 0) {
+ w.element.css({
+ "margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + "px"
+ })
+ }
+ return td;
+ },
+
+ _mountChildren: function () {
+ var self = this;
+ var frag = document.createDocumentFragment();
+ var hasChild = false;
+ BI.each(this._children, function (i, widget) {
+ if (widget.element !== self.element) {
+ frag.appendChild(widget.element[0]);
+ hasChild = true;
+ }
+ });
+ if (hasChild === true) {
+ this.$tr.append(frag);
+ this.element.append(this.$table);
+ }
+ },
+
+ resize: function () {
+ // console.log("horizontal_adapt布局不需要resize");
+ },
+
+ _getWrapper: function () {
+ return this.$tr;
+ },
+
+ populate: function (items) {
+ BI.HorizontalAdaptLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.horizontal_adapt', BI.HorizontalAdaptLayout);/**
+ * 左右分离,垂直方向居中容器
+ * items:{
+ left: [{el:{type:"bi.button"}}],
+ right:[{el:{type:"bi.button"}}]
+ }
+ * @class BI.LeftRightVerticalAdaptLayout
+ * @extends BI.Layout
+ */
+BI.LeftRightVerticalAdaptLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.LeftRightVerticalAdaptLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-left-right-vertical-adapt-layout",
+ items: {},
+ llgap: 0,
+ lrgap: 0,
+ lhgap: 0,
+ rlgap: 0,
+ rrgap: 0,
+ rhgap: 0
+ });
+ },
+ render: function () {
+ BI.LeftRightVerticalAdaptLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ resize: function () {
+ // console.log("left_right_vertical_adapt布局不需要resize");
+ },
+
+ addItem: function () {
+ //do nothing
+ throw new Error("cannot be added")
+ },
+
+ stroke: function (items) {
+ var o = this.options;
+ if ("left" in items) {
+ var left = BI.createWidget({
+ type: "bi.vertical_adapt",
+ items: items.left,
+ hgap: o.lhgap,
+ lgap: o.llgap,
+ rgap: o.lrgap
+ });
+ left.element.css("height", "100%");
+ BI.createWidget({
+ type: "bi.left",
+ element: this,
+ items: [left]
+ });
+ }
+ if ("right" in items) {
+ var right = BI.createWidget({
+ type: "bi.vertical_adapt",
+ items: items.right,
+ hgap: o.rhgap,
+ lgap: o.rlgap,
+ rgap: o.rrgap
+ });
+ right.element.css("height", "100%");
+ BI.createWidget({
+ type: "bi.right",
+ element: this,
+ items: [right]
+ });
+ }
+ },
+
+ populate: function (items) {
+ BI.LeftRightVerticalAdaptLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.left_right_vertical_adapt', BI.LeftRightVerticalAdaptLayout);
+
+
+BI.LeftVerticalAdaptLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.LeftRightVerticalAdaptLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-left-vertical-adapt-layout",
+ items: [],
+ lgap: 0,
+ rgap: 0,
+ hgap: 0
+ });
+ },
+ render: function () {
+ BI.LeftVerticalAdaptLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ resize: function () {
+ // console.log("left_vertical_adapt布局不需要resize");
+ },
+
+ addItem: function () {
+ //do nothing
+ throw new Error("cannot be added")
+ },
+
+ stroke: function (items) {
+ var o = this.options;
+ var left = BI.createWidget({
+ type: "bi.vertical_adapt",
+ items: items,
+ lgap: o.lgap,
+ hgap: o.hgap,
+ rgap: o.rgap
+ });
+ left.element.css("height", "100%");
+ BI.createWidget({
+ type: "bi.left",
+ element: this,
+ items: [left]
+ });
+ },
+
+ populate: function (items) {
+ BI.LeftVerticalAdaptLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.left_vertical_adapt', BI.LeftVerticalAdaptLayout);
+
+BI.RightVerticalAdaptLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.RightVerticalAdaptLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-right-vertical-adapt-layout",
+ items: [],
+ lgap: 0,
+ rgap: 0,
+ hgap: 0
+ });
+ },
+ render: function () {
+ BI.RightVerticalAdaptLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ resize: function () {
+
+ },
+
+ addItem: function () {
+ //do nothing
+ throw new Error("cannot be added")
+ },
+
+ stroke: function (items) {
+ var o = this.options;
+ var right = BI.createWidget({
+ type: "bi.vertical_adapt",
+ items: items,
+ lgap: o.lgap,
+ hgap: o.hgap,
+ rgap: o.rgap
+ });
+ right.element.css("height", "100%");
+ BI.createWidget({
+ type: "bi.right",
+ element: this,
+ items: [right]
+ });
+ },
+
+ populate: function (items) {
+ BI.RightVerticalAdaptLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.right_vertical_adapt', BI.RightVerticalAdaptLayout);/**
+ * 垂直方向居中容器
+ * @class BI.VerticalAdaptLayout
+ * @extends BI.Layout
+ */
+BI.VerticalAdaptLayout = BI.inherit(BI.Layout, {
+ props: {
+ baseCls: "bi-vertical-adapt-layout",
+ columnSize: [],
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ },
+ render: function () {
+ BI.VerticalAdaptLayout.superclass.render.apply(this, arguments);
+ this.$table = $("").attr({"cellspacing": 0, "cellpadding": 0}).css({
+ "position": "relative",
+ "height": "100%",
+ "white-space": "nowrap",
+ "border-spacing": "0px",
+ "border": "none",
+ "border-collapse": "separate"
+ });
+ this.$tr = $("");
+ this.$tr.appendTo(this.$table);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var td;
+ var width = o.columnSize[i] <= 1 ? (o.columnSize[i] * 100 + "%") : o.columnSize[i];
+ if (!this.hasWidget(this._getChildName(i))) {
+ var w = BI.createWidget(item);
+ w.element.css({"position": "relative", "top": "0", "left": "0", "margin": "0px auto"});
+ td = BI.createWidget({
+ type: "bi.default",
+ tagName: "td",
+ attributes: {
+ width: width
+ },
+ items: [w]
+ });
+ this.addWidget(this._getChildName(i), td);
+ } else {
+ td = this.getWidgetByName(this._getChildName(i));
+ td.element.attr("width", width);
+ }
+
+ if (i === 0) {
+ td.element.addClass("first-element");
+ }
+ td.element.css({
+ "position": "relative",
+ "height": "100%",
+ "vertical-align": "middle",
+ "margin": "0",
+ "padding": "0",
+ "border": "none"
+ });
+ if (o.hgap + o.lgap + (item.lgap || 0) !== 0) {
+ w.element.css({
+ "margin-left": o.hgap + o.lgap + (item.lgap || 0) + "px"
+ })
+ }
+ if (o.hgap + o.rgap + (item.rgap || 0) !== 0) {
+ w.element.css({
+ "margin-right": o.hgap + o.rgap + (item.rgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.tgap + (item.tgap || 0) !== 0) {
+ w.element.css({
+ "margin-top": o.vgap + o.tgap + (item.tgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.bgap + (item.bgap || 0) !== 0) {
+ w.element.css({
+ "margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + "px"
+ })
+ }
+ return td;
+ },
+
+ _mountChildren: function () {
+ var self = this;
+ var frag = document.createDocumentFragment();
+ var hasChild = false;
+ BI.each(this._children, function (i, widget) {
+ if (widget.element !== self.element) {
+ frag.appendChild(widget.element[0]);
+ hasChild = true;
+ }
+ });
+ if (hasChild === true) {
+ this.$tr.append(frag);
+ this.element.append(this.$table);
+ }
+ },
+
+ _getWrapper: function(){
+ return this.$tr;
+ },
+
+ resize: function () {
+ // console.log("vertical_adapt布局不需要resize");
+ },
+
+ populate: function (items) {
+ BI.VerticalAdaptLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.vertical_adapt', BI.VerticalAdaptLayout);/**
+ * 水平方向居中自适应容器
+ * @class BI.HorizontalAutoLayout
+ * @extends BI.Layout
+ */
+BI.HorizontalAutoLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.HorizontalAutoLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-horizon-auto-layout",
+ hgap: 0,
+ lgap: 0,
+ rgap: 0,
+ vgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+
+ render: function () {
+ BI.HorizontalAutoLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.HorizontalAutoLayout.superclass._addElement.apply(this, arguments);
+ w.element.css({
+ "position": "relative",
+ "margin": "0px auto"
+ });
+ if (o.hgap + o.lgap + (item.lgap || 0) !== 0) {
+ w.element.css({
+ "margin-left": o.hgap + o.lgap + (item.lgap || 0) + "px"
+ })
+ }
+ if (o.hgap + o.rgap + (item.rgap || 0) !== 0) {
+ w.element.css({
+ "margin-right": o.hgap + o.rgap + (item.rgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.tgap + (item.tgap || 0) !== 0) {
+ w.element.css({
+ "margin-top": o.vgap + o.tgap + (item.tgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.bgap + (item.bgap || 0) !== 0) {
+ w.element.css({
+ "margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + "px"
+ })
+ }
+ return w;
+ },
+
+ resize: function () {
+ // console.log("horizontal_adapt布局不需要resize");
+ },
+
+ populate: function (items) {
+ BI.HorizontalAutoLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.horizontal_auto', BI.HorizontalAutoLayout);/**
+ * 浮动的居中布局
+ */
+BI.FloatCenterAdaptLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.FloatCenterAdaptLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-float-center-adapt-layout",
+ items: [],
+ hgap: 0,
+ vgap: 0,
+ tgap: 0,
+ bgap: 0,
+ lgap: 0,
+ rgap: 0
+ });
+ },
+ render: function () {
+ BI.FloatCenterAdaptLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ resize: function () {
+ // console.log("float_center_adapt布局不需要resize");
+ },
+
+ addItem: function () {
+ //do nothing
+ throw new Error("cannot be added")
+ },
+
+ mounted: function () {
+ var self = this;
+ var width = this.left.element.outerWidth(),
+ height = this.left.element.outerHeight();
+ this.left.element.width(width).height(height).css("float", "none");
+ BI.remove(this._children, function (i, wi) {
+ if (wi === self.container) {
+ delete self._children[i];
+ }
+ });
+ BI.createWidget({
+ type: "bi.center_adapt",
+ element: this,
+ items: [this.left]
+ });
+ },
+
+ stroke: function (items) {
+ var self = this, o = this.options;
+ this.left = BI.createWidget({
+ type: "bi.vertical",
+ items: items,
+ hgap: o.hgap,
+ vgap: o.vgap,
+ tgap: o.tgap,
+ bgap: o.bgap,
+ lgap: o.lgap,
+ rgap: o.rgap
+ });
+
+ this.container = BI.createWidget({
+ type: "bi.left",
+ element: this,
+ items: [this.left]
+ });
+
+ },
+
+ populate: function (items) {
+ BI.FloatCenterAdaptLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.float_center_adapt', BI.FloatCenterAdaptLayout);/**
+ * 浮动的水平居中布局
+ */
+BI.FloatHorizontalLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.FloatHorizontalLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-float-horizontal-adapt-layout",
+ items: [],
+ hgap: 0,
+ vgap: 0,
+ tgap: 0,
+ bgap: 0,
+ lgap: 0,
+ rgap: 0
+ });
+ },
+ render: function () {
+ BI.FloatHorizontalLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ resize: function () {
+ // console.log("float_horizontal_adapt布局不需要resize");
+ },
+
+ mounted: function () {
+ var self = this;
+ var width = this.left.element.width(),
+ height = this.left.element.height();
+ this.left.element.width(width).height(height).css("float", "none");
+ BI.remove(this._children, function (i, wi) {
+ if (wi === self.container) {
+ delete self._children[i];
+ }
+ });
+ BI.createWidget({
+ type: "bi.horizontal_auto",
+ element: this,
+ items: [this.left]
+ });
+ },
+
+ _addElement: function (i, item) {
+ var self = this, o = this.options;
+ this.left = BI.createWidget({
+ type: "bi.vertical",
+ items: [item],
+ hgap: o.hgap,
+ vgap: o.vgap,
+ tgap: o.tgap,
+ bgap: o.bgap,
+ lgap: o.lgap,
+ rgap: o.rgap
+ });
+
+ this.container = BI.createWidget({
+ type: "bi.left",
+ element: this,
+ items: [this.left]
+ });
+
+ return this.left;
+ },
+
+ populate: function (items) {
+ BI.HorizontalAutoLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.horizontal_float', BI.FloatHorizontalLayout);/**
+ *自适应水平和垂直方向都居中容器
+ * Created by GUY on 2016/12/2.
+ *
+ * @class BI.FlexCenterLayout
+ * @extends BI.Layout
+ */
+BI.FlexCenterLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.FlexCenterLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-flex-center-layout"
+ });
+ },
+ render: function () {
+ BI.FlexCenterLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.FlexCenterLayout.superclass._addElement.apply(this, arguments);
+ w.element.css({"position": "relative", "flex-shrink": "0"});
+ return w;
+ },
+
+ resize: function () {
+ // console.log("flex_center布局不需要resize");
+ },
+
+ populate: function (items) {
+ BI.FlexCenterLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.flex_center', BI.FlexCenterLayout);/**
+ *自适应水平和垂直方向都居中容器
+ * Created by GUY on 2016/12/2.
+ *
+ * @class BI.FlexHorizontalLayout
+ * @extends BI.Layout
+ */
+BI.FlexHorizontalLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.FlexHorizontalLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-flex-horizontal-layout",
+ verticalAlign: "middle",
+ columnSize: [],
+ scrollx: true,
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+ render: function () {
+ BI.FlexHorizontalLayout.superclass.render.apply(this, arguments);
+ var o = this.options;
+ this.element.addClass(o.verticalAlign);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.FlexHorizontalLayout.superclass._addElement.apply(this, arguments);
+ w.element.css({"position": "relative", "flex-shrink": "0"});
+ if (o.hgap + o.lgap + (item.lgap || 0) > 0) {
+ w.element.css({
+ "margin-left": o.hgap + o.lgap + (item.lgap || 0) + "px"
+ })
+ }
+ if (o.hgap + o.rgap + (item.rgap || 0) > 0) {
+ w.element.css({
+ "margin-right": o.hgap + o.rgap + (item.rgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.tgap + (item.tgap || 0) > 0) {
+ w.element.css({
+ "margin-top": o.vgap + o.tgap + (item.tgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.bgap + (item.bgap || 0) > 0) {
+ w.element.css({
+ "margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + "px"
+ })
+ }
+ return w;
+ },
+
+ resize: function () {
+ // console.log("flex_horizontal布局不需要resize");
+ },
+
+ populate: function (items) {
+ BI.FlexHorizontalLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.flex_horizontal', BI.FlexHorizontalLayout);/**
+ *自适应水平和垂直方向都居中容器
+ * Created by GUY on 2016/12/2.
+ *
+ * @class BI.FlexVerticalCenter
+ * @extends BI.Layout
+ */
+BI.FlexVerticalCenter = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.FlexVerticalCenter.superclass.props.apply(this, arguments), {
+ baseCls: "bi-flex-vertical-center",
+ columnSize: [],
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+ render: function () {
+ BI.FlexVerticalCenter.superclass.render.apply(this, arguments);
+ var o = this.options;
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.FlexVerticalCenter.superclass._addElement.apply(this, arguments);
+ w.element.css({"position": "relative", "flex-shrink": "0"});
+ if (o.hgap + o.lgap + (item.lgap || 0) > 0) {
+ w.element.css({
+ "margin-left": o.hgap + o.lgap + (item.lgap || 0) + "px"
+ })
+ }
+ if (o.hgap + o.rgap + (item.rgap || 0) > 0) {
+ w.element.css({
+ "margin-right": o.hgap + o.rgap + (item.rgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.tgap + (item.tgap || 0) > 0) {
+ w.element.css({
+ "margin-top": o.vgap + o.tgap + (item.tgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.bgap + (item.bgap || 0) > 0) {
+ w.element.css({
+ "margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + "px"
+ })
+ }
+ return w;
+ },
+
+ resize: function () {
+ // console.log("flex_vertical_center布局不需要resize");
+ },
+
+ populate: function (items) {
+ BI.FlexVerticalCenter.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.flex_vertical_center', BI.FlexVerticalCenter);/**
+ *自适应水平和垂直方向都居中容器
+ * Created by GUY on 2016/12/2.
+ *
+ * @class BI.FlexCenterLayout
+ * @extends BI.Layout
+ */
+BI.FlexCenterLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.FlexCenterLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-flex-wrapper-center-layout clearfix"
+ });
+ },
+ render: function () {
+ BI.FlexCenterLayout.superclass.render.apply(this, arguments);
+ this.$wrapper = $("").addClass("flex-wrapper-center-layout-wrapper");
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.FlexCenterLayout.superclass._addElement.apply(this, arguments);
+ w.element.css({"position": "relative"});
+ return w;
+ },
+
+ _mountChildren: function () {
+ var self = this;
+ var frag = document.createDocumentFragment();
+ var hasChild = false;
+ BI.each(this._children, function (i, widget) {
+ if (widget.element !== self.element) {
+ frag.appendChild(widget.element[0]);
+ hasChild = true;
+ }
+ });
+ if (hasChild === true) {
+ this.$wrapper.append(frag);
+ this.element.append(this.$wrapper);
+ }
+ },
+
+ _getWrapper: function(){
+ return this.$wrapper;
+ },
+
+ resize: function () {
+ // console.log("flex_center布局不需要resize");
+ },
+
+ populate: function (items) {
+ BI.FlexCenterLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.flex_wrapper_center', BI.FlexCenterLayout);/**
+ *自适应水平和垂直方向都居中容器
+ * Created by GUY on 2016/12/2.
+ *
+ * @class BI.FlexHorizontalLayout
+ * @extends BI.Layout
+ */
+BI.FlexHorizontalLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.FlexHorizontalLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-flex-wrapper-horizontal-layout clearfix",
+ verticalAlign: "middle",
+ columnSize: [],
+ scrollx: true,
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+ render: function () {
+ BI.FlexHorizontalLayout.superclass.render.apply(this, arguments);
+ var o = this.options;
+ this.$wrapper = $("
").addClass("flex-wrapper-horizontal-layout-wrapper " + o.verticalAlign);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.FlexHorizontalLayout.superclass._addElement.apply(this, arguments);
+ w.element.css({"position": "relative"});
+ if (o.hgap + o.lgap + (item.lgap || 0) > 0) {
+ w.element.css({
+ "margin-left": o.hgap + o.lgap + (item.lgap || 0) + "px"
+ })
+ }
+ if (o.hgap + o.rgap + (item.rgap || 0) > 0) {
+ w.element.css({
+ "margin-right": o.hgap + o.rgap + (item.rgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.tgap + (item.tgap || 0) > 0) {
+ w.element.css({
+ "margin-top": o.vgap + o.tgap + (item.tgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.bgap + (item.bgap || 0) > 0) {
+ w.element.css({
+ "margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + "px"
+ })
+ }
+ return w;
+ },
+
+ _mountChildren: function () {
+ var self = this;
+ var frag = document.createDocumentFragment();
+ var hasChild = false;
+ BI.each(this._children, function (i, widget) {
+ if (widget.element !== self.element) {
+ frag.appendChild(widget.element[0]);
+ hasChild = true;
+ }
+ });
+ if (hasChild === true) {
+ this.$wrapper.append(frag);
+ this.element.append(this.$wrapper);
+ }
+ },
+
+ _getWrapper: function(){
+ return this.$wrapper;
+ },
+
+ resize: function () {
+ // console.log("flex_horizontal布局不需要resize");
+ },
+
+ populate: function (items) {
+ BI.FlexHorizontalLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.flex_wrapper_horizontal', BI.FlexHorizontalLayout);/**
+ *自适应水平和垂直方向都居中容器
+ * Created by GUY on 2016/12/2.
+ *
+ * @class BI.FlexVerticalCenter
+ * @extends BI.Layout
+ */
+BI.FlexVerticalCenter = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.FlexVerticalCenter.superclass.props.apply(this, arguments), {
+ baseCls: "bi-flex-wrapper-vertical-center clearfix",
+ columnSize: [],
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+ render: function () {
+ BI.FlexVerticalCenter.superclass.render.apply(this, arguments);
+ var o = this.options;
+ this.$wrapper = $("
").addClass("flex-wrapper-vertical-center-wrapper");
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.FlexVerticalCenter.superclass._addElement.apply(this, arguments);
+ w.element.css({"position": "relative"});
+ if (o.hgap + o.lgap + (item.lgap || 0) > 0) {
+ w.element.css({
+ "margin-left": o.hgap + o.lgap + (item.lgap || 0) + "px"
+ })
+ }
+ if (o.hgap + o.rgap + (item.rgap || 0) > 0) {
+ w.element.css({
+ "margin-right": o.hgap + o.rgap + (item.rgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.tgap + (item.tgap || 0) > 0) {
+ w.element.css({
+ "margin-top": o.vgap + o.tgap + (item.tgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.bgap + (item.bgap || 0) > 0) {
+ w.element.css({
+ "margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + "px"
+ })
+ }
+ return w;
+ },
+
+ _mountChildren: function () {
+ var self = this;
+ var frag = document.createDocumentFragment();
+ var hasChild = false;
+ BI.each(this._children, function (i, widget) {
+ if (widget.element !== self.element) {
+ frag.appendChild(widget.element[0]);
+ hasChild = true;
+ }
+ });
+ if (hasChild === true) {
+ this.$wrapper.append(frag);
+ this.element.append(this.$wrapper);
+ }
+ },
+
+ _getWrapper: function(){
+ return this.$wrapper;
+ },
+
+ resize: function () {
+ // console.log("flex_vertical_center布局不需要resize");
+ },
+
+ populate: function (items) {
+ BI.FlexVerticalCenter.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.flex_wrapper_vertical_center', BI.FlexVerticalCenter);/**
+ * 固定子组件上下左右的布局容器
+ * @class BI.AbsoluteLayout
+ * @extends BI.Layout
+ */
+BI.AbsoluteLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.AbsoluteLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-absolute-layout",
+ hgap: null,
+ vgap: null,
+ lgap: null,
+ rgap: null,
+ tgap: null,
+ bgap: null
+ });
+ },
+ render: function () {
+ BI.AbsoluteLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.AbsoluteLayout.superclass._addElement.apply(this, arguments);
+ var left = 0, right = 0, top = 0, bottom = 0;
+ if (BI.isNotNull(item.left)) {
+ w.element.css({"left": item.left});
+ left += item.left;
+ }
+ if (BI.isNotNull(item.right)) {
+ w.element.css({"right": item.right});
+ right += item.right;
+ }
+ if (BI.isNotNull(item.top)) {
+ w.element.css({"top": item.top});
+ top += item.top;
+ }
+ if (BI.isNotNull(item.bottom)) {
+ w.element.css({"bottom": item.bottom});
+ bottom += item.bottom;
+ }
+
+ if (BI.isNotNull(o.hgap)) {
+ left += o.hgap;
+ w.element.css({"left": left});
+ right += o.hgap;
+ w.element.css({"right": right});
+ }
+ if (BI.isNotNull(o.vgap)) {
+ top += o.vgap;
+ w.element.css({"top": top});
+ bottom += o.vgap;
+ w.element.css({"bottom": bottom});
+ }
+
+ if (BI.isNotNull(o.lgap)) {
+ left += o.lgap;
+ w.element.css({"left": left});
+ }
+ if (BI.isNotNull(o.rgap)) {
+ right += o.rgap;
+ w.element.css({"right": right});
+ }
+ if (BI.isNotNull(o.tgap)) {
+ top += o.tgap;
+ w.element.css({"top": top});
+ }
+ if (BI.isNotNull(o.bgap)) {
+ bottom += o.bgap;
+ w.element.css({"bottom": bottom});
+ }
+
+
+ if (BI.isNotNull(item.width)) {
+ w.element.css({"width": item.width});
+ }
+ if (BI.isNotNull(item.height)) {
+ w.element.css({"height": item.height});
+ }
+ w.element.css({"position": "absolute"});
+ return w;
+ },
+
+ resize: function () {
+ this.stroke(this.options.items);
+ },
+
+ stroke: function (items) {
+ this.options.items = items || [];
+ var self = this;
+ BI.each(items, function (i, item) {
+ if (!!item) {
+ if (!BI.isWidget(item) && !item.el) {
+ throw new Error("el must be exist");
+ }
+ self._addElement(i, item);
+ }
+ });
+ },
+
+ populate: function (items) {
+ BI.AbsoluteLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.absolute', BI.AbsoluteLayout);BI.AdaptiveLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.AdaptiveLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-adaptive-layout",
+ hgap: null,
+ vgap: null,
+ lgap: null,
+ rgap: null,
+ tgap: null,
+ bgap: null
+ });
+ },
+ render: function () {
+ BI.AdaptiveLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.AdaptiveLayout.superclass._addElement.apply(this, arguments);
+ w.element.css({"position": "relative"});
+ var left = 0, right = 0, top = 0, bottom = 0;
+ if (BI.isNotNull(item.left)) {
+ w.element.css({
+ "margin-left": item.left
+ })
+ }
+ if (BI.isNotNull(item.right)) {
+ w.element.css({
+ "margin-right": item.right
+ })
+ }
+ if (BI.isNotNull(item.top)) {
+ w.element.css({
+ "margin-top": item.top
+ })
+ }
+ if (BI.isNotNull(item.bottom)) {
+ w.element.css({
+ "margin-bottom": item.bottom
+ })
+ }
+
+ if (BI.isNotNull(o.hgap)) {
+ left += o.hgap;
+ w.element.css({"left": left});
+ right += o.hgap;
+ w.element.css({"right": right});
+ }
+ if (BI.isNotNull(o.vgap)) {
+ top += o.vgap;
+ w.element.css({"top": top});
+ bottom += o.vgap;
+ w.element.css({"bottom": bottom});
+ }
+
+ if (BI.isNotNull(o.lgap)) {
+ left += o.lgap;
+ w.element.css({"left": left});
+ }
+ if (BI.isNotNull(o.rgap)) {
+ right += o.rgap;
+ w.element.css({"right": right});
+ }
+ if (BI.isNotNull(o.tgap)) {
+ top += o.tgap;
+ w.element.css({"top": top});
+ }
+ if (BI.isNotNull(o.bgap)) {
+ bottom += o.bgap;
+ w.element.css({"bottom": bottom});
+ }
+
+ if (BI.isNotNull(item.width)) {
+ w.element.css({"width": item.width});
+ }
+ if (BI.isNotNull(item.height)) {
+ w.element.css({"height": item.height});
+ }
+ return w;
+ },
+
+ resize: function () {
+ this.stroke(this.options.items);
+ },
+
+ populate: function (items) {
+ BI.AbsoluteLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.adaptive', BI.AdaptiveLayout);/**
+ * 上下的高度固定/左右的宽度固定,中间的高度/宽度自适应
+ *
+ * @class BI.BorderLayout
+ * @extends BI.Layout
+ */
+BI.BorderLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.BorderLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-border-layout",
+ items: {}
+ });
+ },
+ render: function () {
+ BI.BorderLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ resize: function () {
+ this.stroke(this.options.items);
+ },
+
+ addItem: function (item) {
+ // do nothing
+ throw new Error("cannot be added")
+ },
+
+ stroke: function(regions){
+ var item;
+ var top = 0;
+ var bottom = 0;
+ var left = 0;
+ var right = 0;
+ if ("north" in regions) {
+ item = regions["north"];
+ if (item != null) {
+ if (item.el) {
+ if (!this.hasWidget(this.getName() + "north")) {
+ var w = BI.createWidget(item);
+ this.addWidget(this.getName() + "north", w);
+ }
+ this.getWidgetByName(this.getName() + "north").element.height(item.height)
+ .css({
+ "position": "absolute",
+ "top": (item.top || 0),
+ "left": (item.left || 0),
+ "right": (item.right || 0),
+ "bottom": "initial"
+ });
+ }
+ top = (item.height || 0) + (item.top || 0) + (item.bottom || 0);
+ }
+ }
+ if ("south" in regions) {
+ item = regions["south"];
+ if (item != null) {
+ if (item.el) {
+ if (!this.hasWidget(this.getName() + "south")) {
+ var w = BI.createWidget(item);
+ this.addWidget(this.getName() + "south", w);
+ }
+ this.getWidgetByName(this.getName() + "south").element.height(item.height)
+ .css({
+ "position": "absolute",
+ "bottom": (item.bottom || 0),
+ "left": (item.left || 0),
+ "right": (item.right || 0),
+ "top": "initial"
+ });
+ }
+ bottom = (item.height || 0) + (item.top || 0) + (item.bottom || 0);
+ }
+ }
+ if ("west" in regions) {
+ item = regions["west"];
+ if (item != null) {
+ if (item.el) {
+ if (!this.hasWidget(this.getName() + "west")) {
+ var w = BI.createWidget(item);
+ this.addWidget(this.getName() + "west", w);
+ }
+ this.getWidgetByName(this.getName() + "west").element.width(item.width)
+ .css({
+ "position": "absolute",
+ "left": (item.left || 0),
+ top: top,
+ bottom: bottom,
+ "right": "initial"
+ });
+ }
+ left = (item.width || 0) + (item.left || 0) + (item.right || 0);
+ }
+ }
+ if ("east" in regions) {
+ item = regions["east"];
+ if (item != null) {
+ if (item.el) {
+ if (!this.hasWidget(this.getName() + "east")) {
+ var w = BI.createWidget(item);
+ this.addWidget(this.getName() + "east", w);
+ }
+ this.getWidgetByName(this.getName() + "east").element.width(item.width)
+ .css({
+ "position": "absolute",
+ "right": (item.right || 0),
+ top: top,
+ bottom: bottom,
+ "left": "initial"
+ });
+ }
+ right = (item.width || 0) + (item.left || 0) + (item.right || 0);
+ }
+ }
+ if ("center" in regions) {
+ item = regions["center"];
+ if (item != null) {
+ if (!this.hasWidget(this.getName() + "center")) {
+ var w = BI.createWidget(item);
+ this.addWidget(this.getName() + "center", w);
+ }
+ this.getWidgetByName(this.getName() + "center").element
+ .css({"position": "absolute", "top": top, "bottom": bottom, "left": left, "right": right});
+ }
+ }
+ },
+
+ populate: function (items) {
+ BI.BorderLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.border', BI.BorderLayout);/**
+ * 卡片布局,可以做到当前只显示一个组件,其他的都隐藏
+ * @class BI.CardLayout
+ * @extends BI.Layout
+ *
+ * @cfg {JSON} options 配置属性
+ * @cfg {String} options.defaultShowName 默认展示的子组件名
+ */
+BI.CardLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.CardLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-card-layout",
+ items: []
+ });
+ },
+ render: function () {
+ BI.CardLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ resize: function () {
+ // console.log("default布局不需要resize");
+ },
+
+ stroke: function (items) {
+ var self = this, o = this.options;
+ this.showIndex = void 0;
+ BI.each(items, function (i, item) {
+ if (!!item) {
+ if (!self.hasWidget(item.cardName)) {
+ var w = BI.createWidget(item);
+ w.on(BI.Events.DESTROY, function () {
+ var index = BI.findIndex(o.items, function (i, tItem) {
+ return tItem.cardName == item.cardName;
+ });
+ if (index > -1) {
+ o.items.splice(index, 1);
+ }
+ });
+ self.addWidget(item.cardName, w);
+ } else {
+ var w = self.getWidgetByName(item.cardName);
+ }
+ w.element.css({"position": "absolute", "top": "0", "right": "0", "bottom": "0", "left": "0"});
+ w.setVisible(false);
+ }
+ });
+ },
+
+ update: function () {
+ },
+
+ empty: function () {
+ BI.CardLayout.superclass.empty.apply(this, arguments);
+ this.options.items = [];
+ },
+
+ populate: function (items) {
+ BI.CardLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ this.options.defaultShowName && this.showCardByName(this.options.defaultShowName);
+ },
+
+ isCardExisted: function (cardName) {
+ return BI.some(this.options.items, function (i, item) {
+ return item.cardName == cardName && item.el;
+ });
+ },
+
+ getCardByName: function (cardName) {
+ if (!this.isCardExisted(cardName)) {
+ throw new Error("cardName is not exist");
+ }
+ return this._children[cardName];
+ },
+
+ _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();
+ },
+
+ addCardByName: function (cardName, cardItem) {
+ if (this.isCardExisted(cardName)) {
+ throw new Error("cardName is already exist");
+ }
+ var widget = BI.createWidget(cardItem);
+ widget.element.css({
+ "position": "relative",
+ "top": "0",
+ "left": "0",
+ "width": "100%",
+ "height": "100%"
+ }).appendTo(this.element);
+ widget.invisible();
+ this.addWidget(cardName, widget);
+ this.options.items.push({el: cardItem, cardName: cardName});
+ return widget;
+ },
+
+ showCardByName: function (name, action, callback) {
+ var self = this;
+ //name不存在的时候全部隐藏
+ var exist = this.isCardExisted(name);
+ if (this.showIndex != null) {
+ this.lastShowIndex = this.showIndex;
+ }
+ this.showIndex = name;
+ var flag = false;
+ BI.each(this.options.items, function (i, item) {
+ var el = self._children[item.cardName];
+ 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())
+ }
+ }
+ });
+ },
+
+ showLastCard: function () {
+ var self = this;
+ this.showIndex = this.lastShowIndex;
+ BI.each(this.options.items, function (i, item) {
+ self._children[item.cardName].setVisible(self.showIndex == i);
+ })
+ },
+
+ setDefaultShowName: function (name) {
+ this.options.defaultShowName = name;
+ return this;
+ },
+
+ getDefaultShowName: function () {
+ return this.options.defaultShowName;
+ },
+
+ getAllCardNames: function () {
+ return BI.map(this.options.items, function (i, item) {
+ return item.cardName;
+ })
+ },
+
+ getShowingCard: function () {
+ if (!BI.isKey(this.showIndex)) {
+ return void 0;
+ }
+ return this.getWidgetByName(this.showIndex);
+ },
+
+ deleteAllCard: function () {
+ var self = this;
+ BI.each(this.getAllCardNames(), function (i, name) {
+ self.deleteCardByName(name);
+ })
+ },
+
+ hideAllCard: function () {
+ var self = this;
+ BI.each(this.options.items, function (i, item) {
+ self._children[item.cardName].invisible();
+ });
+ },
+
+ isAllCardHide: function () {
+ var self = this;
+ var flag = true;
+ BI.some(this.options.items, function (i, item) {
+ if (self._children[item.cardName].isVisible()) {
+ flag = false;
+ return false;
+ }
+ });
+ 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);/**
+ * 默认的布局方式
+ *
+ * @class BI.DefaultLayout
+ * @extends BI.Layout
+ */
+BI.DefaultLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.DefaultLayout.superclass.props.apply(this, arguments), {
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0,
+ items: []
+ });
+ },
+ render: function () {
+ BI.DefaultLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.DefaultLayout.superclass._addElement.apply(this, arguments);
+ if (o.vgap + o.tgap + (item.tgap || 0) !== 0) {
+ w.element.css({
+ "margin-top": o.vgap + o.tgap + (item.tgap || 0) + "px"
+ })
+ }
+ if (o.hgap + o.lgap + (item.lgap || 0) !== 0) {
+ w.element.css({
+ "margin-left": o.hgap + o.lgap + (item.lgap || 0) + "px"
+ })
+ }
+ if (o.hgap + o.rgap + (item.rgap || 0) !== 0) {
+ w.element.css({
+ "margin-right": o.hgap + o.rgap + (item.rgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.bgap + (item.bgap || 0) !== 0) {
+ w.element.css({
+ "margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + "px"
+ })
+ }
+ return w;
+ },
+
+ resize: function () {
+ // console.log("default布局不需要resize")
+ },
+
+ populate: function (items) {
+ BI.DefaultLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.default', BI.DefaultLayout);/**
+ * 分隔容器的控件,按照宽度和高度所占比平分整个容器
+ *
+ * @class BI.DivisionLayout
+ * @extends BI.Layout
+ */
+BI.DivisionLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.DivisionLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-division-layout",
+ columns: null,
+ rows: null,
+ items: []
+ // [
+ // {
+ // column: 0,
+ // row: 0,
+ // width: 0.25,
+ // height: 0.33,
+ // el: {type: 'bi.button', text: 'button1'}
+ // },
+ // {
+ // column: 1,
+ // row: 1,
+ // width: 0.25,
+ // height: 0.33,
+ // el: {type: 'bi.button', text: 'button2'}
+ // },
+ // {
+ // column: 3,
+ // row: 2,
+ // width: 0.25,
+ // height: 0.33,
+ // el: {type: 'bi.button', text: 'button3'}
+ // }
+ //]
+ });
+ },
+ render: function () {
+ BI.DivisionLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ resize: function () {
+ this.stroke(this.opitons.items);
+ },
+
+ addItem: function (item) {
+ // do nothing
+ throw new Error("cannot be added")
+ },
+
+ stroke: function(items){
+ var o = this.options;
+ var rows = o.rows || o.items.length, columns = o.columns || ((o.items[0] && o.items[0].length) | 0);
+ var map = BI.makeArray(rows), widths = {}, heights = {};
+ function firstElement(item, row, col) {
+ if (row === 0) {
+ item.addClass("first-row")
+ }
+ if (col === 0) {
+ item.addClass("first-col");
+ }
+ item.addClass(BI.isOdd(row + 1) ? "odd-row" : "even-row");
+ item.addClass(BI.isOdd(col + 1) ? "odd-col" : "even-col");
+ item.addClass("center-element");
+ }
+
+ function firstObject(item, row, col) {
+ var cls = "";
+ if (row === 0) {
+ cls += " first-row";
+ }
+ if (col === 0) {
+ cls += " first-col";
+ }
+ BI.isOdd(row + 1) ? (cls += " odd-row") : (cls += " even-row");
+ BI.isOdd(col + 1) ? (cls += " odd-col") : (cls += " even-col");
+ item.cls = (item.cls || "") + cls + " center-element";
+ }
+
+ function first(item, row, col) {
+ if (item instanceof BI.Widget) {
+ firstElement(item.element, row, col);
+ } else if (item.el instanceof BI.Widget) {
+ firstElement(item.el.element, row, col);
+ } else if (item.el) {
+ firstObject(item.el, row, col)
+ } else {
+ firstObject(item, row, col);
+ }
+ }
+ BI.each(map, function (i) {
+ map[i] = BI.makeArray(columns);
+ });
+ BI.each(items, function (i, item) {
+ if (BI.isArray(item)) {
+ BI.each(item, function (j, el) {
+ widths[i] = (widths[i] || 0) + item.width;
+ heights[j] = (heights[j] || 0) + item.height;
+ map[i][j] = el;
+ });
+ return;
+ }
+ widths[item.row] = (widths[item.row] || 0) + item.width;
+ heights[item.column] = (heights[item.column] || 0) + item.height;
+ map[item.row][item.column] = item;
+ });
+ for (var i = 0; i < rows; i++) {
+ var totalW = 0;
+ for (var j = 0; j < columns; j++) {
+ if (!map[i][j]) {
+ throw new Error("item be required");
+ }
+ if(!this.hasWidget(this.getName() + i + "_" + j)) {
+ var w = BI.createWidget(map[i][j]);
+ this.addWidget(this.getName() + i + "_" + j, w);
+ } else {
+ w = this.getWidgetByName(this.getName() + i + "_" + j);
+ }
+ var left = totalW * 100 / widths[i];
+ w.element.css({"position": "absolute", "left": left + "%"});
+ if (j > 0) {
+ var lastW = this.getWidgetByName(this.getName() + i + "_" + (j - 1));
+ lastW.element.css({"right": (100 - left) + "%"});
+ }
+ if (j == o.columns - 1) {
+ w.element.css({"right": "0%"});
+ }
+ first(w, i, j);
+ totalW += map[i][j].width;
+ }
+ }
+ for (var j = 0; j < o.columns; j++) {
+ var totalH = 0;
+ for (var i = 0; i < o.rows; i++) {
+ var w = this.getWidgetByName(this.getName() + i + "_" + j);
+ var top = totalH * 100 / heights[j];
+ w.element.css({"top": top + "%"});
+ if (i > 0) {
+ var lastW = this.getWidgetByName(this.getName() + (i - 1) + "_" + j);
+ lastW.element.css({"bottom": (100 - top) + "%"});
+ }
+ if (i == o.rows - 1) {
+ w.element.css({"bottom": "0%"});
+ }
+ totalH += map[i][j].height;
+ }
+ }
+ },
+
+ populate: function (items) {
+ BI.DivisionLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.division', BI.DivisionLayout);/**
+ * 靠左对齐的自由浮动布局
+ * @class BI.FloatLeftLayout
+ * @extends BI.Layout
+ *
+ * @cfg {JSON} options 配置属性
+ * @cfg {Number} [hgap=0] 水平间隙
+ * @cfg {Number} [vgap=0] 垂直间隙
+ */
+BI.FloatLeftLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.FloatLeftLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-float-left-layout clearfix",
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+ render: function () {
+ BI.FloatLeftLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.FloatLeftLayout.superclass._addElement.apply(this, arguments);
+ w.element.css({"position": "relative", "float": "left"});
+ if (BI.isNotNull(item.left)) {
+ w.element.css({"left": item.left});
+ }
+ if (BI.isNotNull(item.right)) {
+ w.element.css({"right": item.right});
+ }
+ if (BI.isNotNull(item.top)) {
+ w.element.css({"top": item.top});
+ }
+ if ((item.lgap || 0) + o.hgap + o.lgap !== 0) {
+ w.element.css("margin-left", (item.lgap || 0) + o.hgap + o.lgap);
+ }
+ if ((item.rgap || 0) + o.hgap + o.rgap !== 0) {
+ w.element.css("margin-right", (item.rgap || 0) + o.hgap + o.rgap);
+ }
+ if ((item.tgap || 0) + o.vgap + o.tgap !== 0) {
+ w.element.css("margin-top", (item.tgap || 0) + o.vgap + o.tgap);
+ }
+ if ((item.bgap || 0) + o.vgap + o.bgap !== 0) {
+ w.element.css("margin-bottom", (item.bgap || 0) + o.vgap + o.bgap);
+ }
+ return w;
+ },
+
+ resize: function () {
+ this.stroke(this.options.items);
+ },
+
+ populate: function (items) {
+ BI.FloatLeftLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.left', BI.FloatLeftLayout);
+
+/**
+ * 靠右对齐的自由浮动布局
+ * @class BI.FloatRightLayout
+ * @extends BI.Layout
+ *
+ * @cfg {JSON} options 配置属性
+ * @cfg {Number} [hgap=0] 水平间隙
+ * @cfg {Number} [vgap=0] 垂直间隙
+ */
+BI.FloatRightLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.FloatRightLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-float-right-layout clearfix",
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+ render: function () {
+ BI.FloatRightLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.FloatRightLayout.superclass._addElement.apply(this, arguments);
+ w.element.css({"position": "relative", "float": "right"});
+ if (BI.isNotNull(item.left)) {
+ w.element.css({"left": item.left});
+ }
+ if (BI.isNotNull(item.right)) {
+ w.element.css({"right": item.right});
+ }
+ if (BI.isNotNull(item.top)) {
+ w.element.css({"top": item.top});
+ }
+ if ((item.lgap || 0) + o.hgap + o.lgap !== 0) {
+ w.element.css("margin-left", (item.lgap || 0) + o.hgap + o.lgap);
+ }
+ if ((item.rgap || 0) + o.hgap + o.rgap !== 0) {
+ w.element.css("margin-right", (item.rgap || 0) + o.hgap + o.rgap);
+ }
+ if ((item.tgap || 0) + o.vgap + o.tgap !== 0) {
+ w.element.css("margin-top", (item.tgap || 0) + o.vgap + o.tgap);
+ }
+ if ((item.bgap || 0) + o.vgap + o.bgap !== 0) {
+ w.element.css("margin-bottom", (item.bgap || 0) + o.vgap + o.bgap);
+ }
+ return w;
+ },
+
+ resize: function () {
+ this.stroke(this.options.items);
+ },
+
+ populate: function (items) {
+ BI.FloatRightLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.right', BI.FloatRightLayout);/**
+ * 上下的高度固定/左右的宽度固定,中间的高度/宽度自适应
+ *
+ * @class BI.BorderLayout
+ * @extends BI.Layout
+ */
+BI.GridLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.GridLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-grid-layout",
+ columns: null,
+ rows: null,
+ items: []
+ /*[
+ {
+ column: 0,
+ row: 0,
+ el: {type: 'bi.button', text: 'button1'}
+ },
+ {
+ column: 1,
+ row: 1,
+ el: {type: 'bi.button', text: 'button2'}
+ },
+ {
+ column: 3,
+ row: 2,
+ el: {type: 'bi.button', text: 'button3'}
+ }
+ ]*/
+ });
+ },
+ render: function () {
+ BI.GridLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ resize: function () {
+ // console.log("grid布局不需要resize")
+ },
+
+ addItem: function () {
+ //do nothing
+ throw new Error("cannot be added")
+ },
+
+ stroke: function (items) {
+ var o = this.options;
+ var rows = o.rows || o.items.length, columns = o.columns || ((o.items[0] && o.items[0].length) | 0);
+ var width = 100 / columns, height = 100 / rows;
+ var els = [];
+ for (var i = 0; i < rows; i++) {
+ els[i] = [];
+ }
+ function firstElement(item, row, col) {
+ if (row === 0) {
+ item.addClass("first-row")
+ }
+ if (col === 0) {
+ item.addClass("first-col");
+ }
+ item.addClass(BI.isOdd(row + 1) ? "odd-row" : "even-row");
+ item.addClass(BI.isOdd(col + 1) ? "odd-col" : "even-col");
+ item.addClass("center-element");
+ }
+
+ function firstObject(item, row, col) {
+ var cls = "";
+ if (row === 0) {
+ cls += " first-row";
+ }
+ if (col === 0) {
+ cls += " first-col";
+ }
+ BI.isOdd(row + 1) ? (cls += " odd-row") : (cls += " even-row");
+ BI.isOdd(col + 1) ? (cls += " odd-col") : (cls += " even-col");
+ item.cls = (item.cls || "") + cls + " center-element";
+ }
+
+ function first(item, row, col) {
+ if (item instanceof BI.Widget) {
+ firstElement(item.element, row, col);
+ } else if (item.el instanceof BI.Widget) {
+ firstElement(item.el.element, row, col);
+ } else if (item.el) {
+ firstObject(item.el, row, col)
+ } else {
+ firstObject(item, row, col);
+ }
+ }
+
+ BI.each(items, function (i, item) {
+ if (BI.isArray(item)) {
+ BI.each(item, function (j, el) {
+ els[i][j] = BI.createWidget(el);
+ });
+ return;
+ }
+ els[item.row][item.column] = BI.createWidget(item);
+ });
+ for (var i = 0; i < rows; i++) {
+ for (var j = 0; j < columns; j++) {
+ if (!els[i][j]) {
+ els[i][j] = BI.createWidget({
+ type: "bi.layout"
+ });
+ }
+ first(els[i][j], i, j);
+ els[i][j].element.css({
+ "position": "absolute",
+ "top": height * i + "%",
+ "left": width * j + "%",
+ "right": (100 - (width * (j + 1))) + "%",
+ "bottom": (100 - (height * (i + 1))) + "%"
+ });
+ this.addWidget(els[i][j]);
+ }
+ }
+ },
+
+ populate: function (items) {
+ BI.GridLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.grid', BI.GridLayout);/**
+ * 水平布局
+ * @class BI.HorizontalLayout
+ * @extends BI.Layout
+ */
+BI.HorizontalLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.HorizontalLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-horizontal-layout",
+ verticalAlign: "middle",
+ columnSize: [],
+ scrollx: true,
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+ render: function () {
+ BI.HorizontalLayout.superclass.render.apply(this, arguments);
+ this.$table = $("
").attr({"cellspacing": 0, "cellpadding": 0}).css({
+ "position": "relative",
+ "white-space": "nowrap",
+ "border-spacing": "0px",
+ "border": "none",
+ "border-collapse": "separate"
+ });
+ this.$tr = $("");
+ this.$tr.appendTo(this.$table);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var td;
+ var width = o.columnSize[i] <= 1 ? (o.columnSize[i] * 100 + "%") : o.columnSize[i];
+ if (!this.hasWidget(this._getChildName(i))) {
+ var w = BI.createWidget(item);
+ w.element.css({"position": "relative", "margin": "0px auto"});
+ td = BI.createWidget({
+ type: "bi.default",
+ tagName: "td",
+ attributes: {
+ width: width
+ },
+ items: [w]
+ });
+ this.addWidget(this._getChildName(i), td);
+ } else {
+ td = this.getWidgetByName(this._getChildName(i));
+ td.element.attr("width", width);
+ }
+
+ if (i === 0) {
+ td.element.addClass("first-element");
+ }
+ td.element.css({
+ "position": "relative",
+ "vertical-align": o.verticalAlign,
+ "margin": "0",
+ "padding": "0",
+ "border": "none"
+ });
+ if (o.hgap + o.lgap + (item.lgap || 0) > 0) {
+ w.element.css({
+ "margin-left": o.hgap + o.lgap + (item.lgap || 0) + "px"
+ })
+ }
+ if (o.hgap + o.rgap + (item.rgap || 0) > 0) {
+ w.element.css({
+ "margin-right": o.hgap + o.rgap + (item.rgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.tgap + (item.tgap || 0) > 0) {
+ w.element.css({
+ "margin-top": o.vgap + o.tgap + (item.tgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.bgap + (item.bgap || 0) > 0) {
+ w.element.css({
+ "margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + "px"
+ })
+ }
+ return td;
+ },
+
+ _mountChildren: function () {
+ var self = this;
+ var frag = document.createDocumentFragment();
+ var hasChild = false;
+ BI.each(this._children, function (i, widget) {
+ if (widget.element !== self.element) {
+ frag.appendChild(widget.element[0]);
+ hasChild = true;
+ }
+ });
+ if (hasChild === true) {
+ this.$tr.append(frag);
+ this.element.append(this.$table);
+ }
+ },
+
+
+ resize: function () {
+ // console.log("horizontal layout do not need to resize");
+ },
+
+ _getWrapper: function(){
+ return this.$tr;
+ },
+
+ populate: function (items) {
+ BI.HorizontalLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.horizontal', BI.HorizontalLayout);
+
+/**
+ * 水平布局
+ * @class BI.HorizontalCellLayout
+ * @extends BI.Layout
+ */
+BI.HorizontalCellLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.HorizontalCellLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-horizontal-cell-layout",
+ scrollable: true,
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+ render: function () {
+ BI.HorizontalCellLayout.superclass.render.apply(this, arguments);
+ this.element.css({"display": "table", "vertical-align": "top"});
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.HorizontalCellLayout.superclass._addElement.apply(this, arguments);
+ w.element.css({"position": "relative", "display": "table-cell", "vertical-align": "middle"});
+ if (o.hgap + o.lgap > 0) {
+ w.element.css({
+ "margin-left": o.hgap + o.lgap + "px"
+ })
+ }
+ if (o.hgap + o.rgap > 0) {
+ w.element.css({
+ "margin-right": o.hgap + o.rgap + "px"
+ })
+ }
+ if (o.vgap + o.tgap > 0) {
+ w.element.css({
+ "margin-top": o.vgap + o.tgap + "px"
+ })
+ }
+ if (o.vgap + o.bgap > 0) {
+ w.element.css({
+ "margin-bottom": o.vgap + o.bgap + "px"
+ })
+ }
+ return w;
+ },
+
+ resize: function () {
+ // console.log("horizontal do not need to resize");
+ },
+
+ populate: function (items) {
+ BI.HorizontalCellLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.horizontal_cell', BI.HorizontalCellLayout);/**
+ * 靠左对齐的自由浮动布局
+ * @class BI.LatticeLayout
+ * @extends BI.Layout
+ *
+ * @cfg {JSON} options 配置属性
+ * @cfg {Number} [hgap=0] 水平间隙
+ * @cfg {Number} [vgap=0] 垂直间隙
+ */
+BI.LatticeLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.LatticeLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-lattice-layout clearfix"
+ //columnSize: [0.2, 0.2, 0.6],
+ });
+ },
+ render: function () {
+ BI.LatticeLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.LatticeLayout.superclass._addElement.apply(this, arguments);
+ if (o.columnSize && o.columnSize[i]) {
+ var width = o.columnSize[i] / BI.sum(o.columnSize) * 100 + "%";
+ } else {
+ var width = 1 / this.options.items.length * 100 + "%"
+ }
+ w.element.css({"position": "relative", "float": "left", "width": width});
+ return w;
+ },
+
+ addItem: function (item) {
+ var w = BI.LatticeLayout.superclass.addItem.apply(this, arguments);
+ this.resize();
+ return w;
+ },
+
+ addItemAt: function (item) {
+ var w = BI.LatticeLayout.superclass.addItemAt.apply(this, arguments);
+ this.resize();
+ return w;
+ },
+
+ resize: function () {
+ this.stroke(this.options.items);
+ },
+
+ populate: function (items) {
+ BI.LatticeLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.lattice', BI.LatticeLayout);/**
+ * 上下的高度固定/左右的宽度固定,中间的高度/宽度自适应
+ *
+ * @class BI.TableLayout
+ * @extends BI.Layout
+ */
+BI.TableLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.TableLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-table-layout",
+ scrolly: true,
+ columnSize: [200, 200, 'fill'],
+ rowSize: 30, //or [30,30,30]
+ hgap: 0,
+ vgap: 0,
+ items: [[
+ {
+ el: {text: 'label1'}
+ },
+ {
+ el: {text: 'label2'}
+ },
+ {
+ el: {text: 'label3'}
+ }
+ ]]
+ });
+ },
+ render: function () {
+ BI.TableLayout.superclass.render.apply(this, arguments);
+ this.rows = 0;
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (idx, arr) {
+ var o = this.options;
+ var abs = [], left = 0, right = 0, i, j;
+
+ function firstElement(item, row, col) {
+ if (row === 0) {
+ item.addClass("first-row")
+ }
+ if (col === 0) {
+ item.addClass("first-col");
+ }
+ item.addClass(BI.isOdd(row + 1) ? "odd-row" : "even-row");
+ item.addClass(BI.isOdd(col + 1) ? "odd-col" : "even-col");
+ item.addClass("center-element");
+ }
+
+ function firstObject(item, row, col) {
+ var cls = "";
+ if (row === 0) {
+ cls += " first-row";
+ }
+ if (col === 0) {
+ cls += " first-col";
+ }
+ BI.isOdd(row + 1) ? (cls += " odd-row") : (cls += " even-row");
+ BI.isOdd(col + 1) ? (cls += " odd-col") : (cls += " even-col");
+ item.cls = (item.cls || "") + cls + " center-element";
+ }
+
+ function first(item, row, col) {
+ if (item instanceof BI.Widget) {
+ firstElement(item.element, row, col);
+ } else if (item.el instanceof BI.Widget) {
+ firstElement(item.el.element, row, col);
+ } else if (item.el) {
+ firstObject(item.el, row, col)
+ } else {
+ firstObject(item, row, col);
+ }
+ }
+
+ for (i = 0; i < arr.length; i++) {
+ if (BI.isNumber(o.columnSize[i])) {
+ first(arr[i], this.rows, i);
+ abs.push(BI.extend({
+ top: 0,
+ bottom: 0,
+ left: o.columnSize[i] <= 1 ? left * 100 + "%" : left,
+ width: o.columnSize[i] <= 1 ? o.columnSize[i] * 100 + "%" : o.columnSize[i]
+ }, arr[i]));
+ left += o.columnSize[i] + (o.columnSize[i] < 1 ? 0 : o.hgap);
+ } else {
+ break;
+ }
+ }
+ for (j = arr.length - 1; j > i; j--) {
+ if (BI.isNumber(o.columnSize[j])) {
+ first(arr[j], this.rows, j);
+ abs.push(BI.extend({
+ top: 0,
+ bottom: 0,
+ right: o.columnSize[j] <= 1 ? right * 100 + "%" : right,
+ width: o.columnSize[j] <= 1 ? o.columnSize[j] * 100 + "%" : o.columnSize[j]
+ }, arr[j]))
+ right += o.columnSize[j] + (o.columnSize[j] < 1 ? 0 : o.hgap);
+ } else {
+ throw new Error("item with fill can only be one");
+ }
+ }
+ if (i >= 0 && i < arr.length) {
+ first(arr[i], this.rows, i);
+ abs.push(BI.extend({
+ top: 0,
+ bottom: 0,
+ left: left <= 1 ? left * 100 + "%" : left,
+ right: right <= 1 ? right * 100 + "%" : right
+ }, arr[i]))
+ }
+ var w = BI.createWidget({
+ type: "bi.absolute",
+ height: BI.isArray(o.rowSize) ? o.rowSize[this.rows] : o.rowSize,
+ items: abs
+ });
+ if (this.rows > 0) {
+ this.getWidgetByName(this.getName() + (this.rows - 1)).element.css({
+ "margin-bottom": o.vgap
+ })
+ }
+ w.element.css({
+ "position": "relative"
+ });
+ this.addWidget(this.getName() + (this.rows++), w);
+ return w;
+ },
+
+ resize: function () {
+ // console.log("table布局不需要resize");
+ },
+
+ addItem: function (arr) {
+ if (!BI.isArray(arr)) {
+ throw new Error("item must be array");
+ }
+ return BI.TableLayout.superclass.addItem.apply(this, arguments);
+ },
+
+ populate: function (items) {
+ BI.TableLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.table', BI.TableLayout);/**
+ * 水平tape布局
+ * @class BI.HTapeLayout
+ * @extends BI.Layout
+ */
+BI.HTapeLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.HTapeLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-h-tape-layout",
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0,
+ items: [
+ {
+ width: 100,
+ el: {type: 'bi.button', text: 'button1'}
+ },
+ {
+ width: 'fill',
+ el: {type: 'bi.button', text: 'button2'}
+ },
+ {
+ width: 200,
+ el: {type: 'bi.button', text: 'button3'}
+ }
+ ]
+ });
+ },
+ render: function () {
+ BI.HTapeLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ resize: function () {
+ this.stroke(this.options.items);
+ },
+ addItem: function (item) {
+ // do nothing
+ throw new Error("cannot be added")
+ },
+
+ stroke: function (items) {
+ var self = this, o = this.options;
+ items = BI.compact(items);
+ BI.each(items, function (i, item) {
+ if (!self.hasWidget(self.getName() + i + "")) {
+ var w = BI.createWidget(item);
+ self.addWidget(self.getName() + i + "", w);
+ } else {
+ w = self.getWidgetByName(self.getName() + i + "");
+ }
+ w.element.css({"position": "absolute", top: o.vgap + o.tgap + "px", bottom: o.vgap + o.bgap + "px"});
+ });
+
+ var left = {}, right = {};
+ left[0] = 0;
+ right[items.length - 1] = 0;
+
+ BI.any(items, function (i, item) {
+ var w = self.getWidgetByName(self.getName() + i + "");
+ if (BI.isNull(left[i])) {
+ left[i] = left[i - 1] + items[i - 1].width + 2 * o.hgap + o.lgap + o.rgap;
+ }
+ if (item.width < 1 && item.width >= 0) {
+ w.element.css({"left": left[i] * 100 + "%", width: item.width * 100 + "%"})
+ } else {
+ w.element.css({
+ "left": left[i] + o.hgap + o.lgap + "px",
+ width: BI.isNumber(item.width) ? item.width : ""
+ });
+ }
+ if (!BI.isNumber(item.width)) {
+ return true;
+ }
+ });
+ BI.backAny(items, function (i, item) {
+ var w = self.getWidgetByName(self.getName() + i + "");
+ if (BI.isNull(right[i])) {
+ right[i] = right[i + 1] + items[i + 1].width + 2 * o.hgap + o.lgap + o.rgap;
+ }
+ if (item.width < 1 && item.width >= 0) {
+ w.element.css({"right": right[i] * 100 + "%", width: item.width * 100 + "%"})
+ } else {
+ w.element.css({
+ "right": right[i] + o.hgap + o.rgap + "px",
+ width: BI.isNumber(item.width) ? item.width : ""
+ });
+ }
+ if (!BI.isNumber(item.width)) {
+ return true;
+ }
+ })
+ },
+
+ populate: function (items) {
+ BI.HTapeLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.htape', BI.HTapeLayout);
+
+/**
+ * 垂直tape布局
+ * @class BI.VTapeLayout
+ * @extends BI.Layout
+ */
+BI.VTapeLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.VTapeLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-v-tape-layout",
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0,
+ items: [
+ {
+ height: 100,
+ el: {type: 'bi.button', text: 'button1'}
+ },
+ {
+ height: 'fill',
+ el: {type: 'bi.button', text: 'button2'}
+ },
+ {
+ height: 200,
+ el: {type: 'bi.button', text: 'button3'}
+ }
+ ]
+ });
+ },
+ render: function () {
+ BI.VTapeLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ resize: function () {
+ this.stroke(this.options.items);
+ },
+
+ addItem: function (item) {
+ // do nothing
+ throw new Error("cannot be added")
+ },
+
+ stroke: function (items) {
+ var self = this, o = this.options;
+ items = BI.compact(items);
+ BI.each(items, function (i, item) {
+ if (!self.hasWidget(self.getName() + i + "")) {
+ var w = BI.createWidget(item);
+ self.addWidget(self.getName() + i + "", w);
+ } else {
+ w = self.getWidgetByName(self.getName() + i + "");
+ }
+ w.element.css({"position": "absolute", left: o.hgap + o.lgap + "px", right: o.hgap + o.rgap + "px"});
+ });
+
+ var top = {}, bottom = {};
+ top[0] = 0;
+ bottom[items.length - 1] = 0;
+
+ BI.any(items, function (i, item) {
+ var w = self.getWidgetByName(self.getName() + i + "");
+ if (BI.isNull(top[i])) {
+ top[i] = top[i - 1] + items[i - 1].height + 2 * o.vgap + o.tgap + o.bgap;
+ }
+ if (item.height < 1 && item.height >= 0) {
+ w.element.css({"top": top[i] * 100 + "%", height: item.height * 100 + "%"})
+ } else {
+ w.element.css({
+ "top": top[i] + o.vgap + o.tgap + "px",
+ height: BI.isNumber(item.height) ? item.height : ""
+ });
+ }
+ if (!BI.isNumber(item.height)) {
+ return true;
+ }
+ });
+ BI.backAny(items, function (i, item) {
+ var w = self.getWidgetByName(self.getName() + i + "");
+ if (BI.isNull(bottom[i])) {
+ bottom[i] = bottom[i + 1] + items[i + 1].height + 2 * o.vgap + o.tgap + o.bgap;
+ }
+ if (item.height < 1 && item.height >= 0) {
+ w.element.css({"bottom": bottom[i] * 100 + "%", height: item.height * 100 + "%"})
+ } else {
+ w.element.css({
+ "bottom": bottom[i] + o.vgap + o.bgap + "px",
+ height: BI.isNumber(item.height) ? item.height : ""
+ });
+ }
+ if (!BI.isNumber(item.height)) {
+ return true;
+ }
+ })
+ },
+
+ populate: function (items) {
+ BI.VTapeLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.vtape', BI.VTapeLayout);/**
+ * td布局
+ * @class BI.TdLayout
+ * @extends BI.Layout
+ */
+BI.TdLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.TdLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-td-layout",
+ columnSize: [200, 200, 200],
+ hgap: 0,
+ vgap: 0,
+ items: [[
+ {
+ el: {text: 'label1'}
+ },
+ {
+ el: {text: 'label2'}
+ },
+ {
+ el: {text: 'label3'}
+ }
+ ]]
+ });
+ },
+ render: function () {
+ BI.TdLayout.superclass.render.apply(this, arguments);
+ this.$table = $("").attr({"cellspacing": 0, "cellpadding": 0}).css({
+ "position": "relative",
+ "width": "100%",
+ "height": "100%",
+ "border-spacing": "0px",
+ "border": "none",
+ "border-collapse": "separate"
+ });
+ this.rows = 0;
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (idx, arr) {
+ var o = this.options;
+
+ function firstElement(item, row, col) {
+ if (row === 0) {
+ item.addClass("first-row")
+ }
+ if (col === 0) {
+ item.addClass("first-col");
+ }
+ item.addClass(BI.isOdd(row + 1) ? "odd-row" : "even-row");
+ item.addClass(BI.isOdd(col + 1) ? "odd-col" : "even-col");
+ item.addClass("center-element");
+ }
+
+ function firstObject(item, row, col) {
+ var cls = "";
+ if (row === 0) {
+ cls += " first-row";
+ }
+ if (col === 0) {
+ cls += " first-col";
+ }
+ BI.isOdd(row + 1) ? (cls += " odd-row") : (cls += " even-row");
+ BI.isOdd(col + 1) ? (cls += " odd-col") : (cls += " even-col");
+ item.cls = (item.cls || "") + cls + " center-element";
+ }
+
+ function first(item, row, col) {
+ if (item instanceof BI.Widget) {
+ firstElement(item.element, row, col);
+ } else if (item.el instanceof BI.Widget) {
+ firstElement(item.el.element, row, col);
+ } else if (item.el) {
+ firstObject(item.el, row, col)
+ } else {
+ firstObject(item, row, col);
+ }
+ }
+
+ var tr = BI.createWidget({
+ type: "bi.default",
+ tagName: "tr"
+ });
+
+ for (var i = 0; i < arr.length; i++) {
+ var w = BI.createWidget(arr[i]);
+ w.element.css({"position": "relative", "top": "0", "left": "0", "margin": "0px auto"});
+ first(w, this.rows++, i);
+ var td = BI.createWidget({
+ type: 'bi.default',
+ attributes: {
+ width: o.columnSize[i] <= 1 ? (o.columnSize[i] * 100 + "%") : o.columnSize[i]
+ },
+ tagName: 'td',
+ items: [w]
+ });
+ td.element.css({
+ "position": "relative",
+ "vertical-align": "middle",
+ "margin": "0",
+ "padding": "0",
+ "border": "none"
+ });
+ tr.addItem(td);
+ }
+ this.addWidget(this.getName() + idx, tr);
+ return tr;
+ },
+
+ _mountChildren: function(){
+ var self = this;
+ var frag = document.createDocumentFragment();
+ var hasChild = false;
+ BI.each(this._children, function (i, widget) {
+ if (widget.element !== self.element) {
+ frag.appendChild(widget.element[0]);
+ hasChild = true;
+ }
+ });
+ if (hasChild === true) {
+ this.$table.append(frag);
+ this.element.append(this.$table);
+ }
+ },
+
+ resize: function () {
+ // console.log("td布局不需要resize");
+ },
+
+ addItem: function (arr) {
+ if (!BI.isArray(arr)) {
+ throw new Error("item must be array");
+ }
+ return BI.TdLayout.superclass.addItem.apply(this, arguments);
+ },
+
+ populate: function (items) {
+ BI.TdLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.td', BI.TdLayout);/**
+ * 垂直布局
+ * @class BI.VerticalLayout
+ * @extends BI.Layout
+ */
+BI.VerticalLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.VerticalLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-vertical-layout",
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0,
+ scrolly: true
+ });
+ },
+ render: function () {
+ BI.VerticalLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ _addElement: function (i, item) {
+ var o = this.options;
+ var w = BI.VerticalLayout.superclass._addElement.apply(this, arguments);
+ w.element.css({
+ "position": "relative"
+ });
+ if (o.vgap + o.tgap + (item.tgap || 0) !== 0) {
+ w.element.css({
+ "margin-top": o.vgap + o.tgap + (item.tgap || 0) + "px"
+ })
+ }
+ if (o.hgap + o.lgap + (item.lgap || 0) !== 0) {
+ w.element.css({
+ "margin-left": o.hgap + o.lgap + (item.lgap || 0) + "px"
+ })
+ }
+ if (o.hgap + o.rgap + (item.rgap || 0) !== 0) {
+ w.element.css({
+ "margin-right": o.hgap + o.rgap + (item.rgap || 0) + "px"
+ })
+ }
+ if (o.vgap + o.bgap + (item.bgap || 0) !== 0) {
+ w.element.css({
+ "margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + "px"
+ })
+ }
+ return w;
+ },
+
+ resize: function () {
+ this.stroke(this.options.items);
+ },
+
+ populate: function (items) {
+ BI.VerticalLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.vertical', BI.VerticalLayout);/**
+ *
+ * @class BI.WindowLayout
+ * @extends BI.Layout
+ */
+BI.WindowLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.WindowLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-window-layout",
+ columns: 3,
+ rows: 2,
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0,
+ columnSize: [100, "fill", 200],
+ rowSize: [100, "fill"],
+ items: [[
+ {
+ el: {type: 'bi.button', text: 'button1'}
+ },
+ {
+ el: {type: 'bi.button', text: 'button2'}
+ },
+ {
+ el: {type: 'bi.button', text: 'button3'}
+ }
+ ]]
+ });
+ },
+ render: function () {
+ BI.WindowLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ resize: function () {
+ this.stroke(this.options.items);
+ },
+
+ addItem: function (item) {
+ // do nothing
+ throw new Error("cannot be added")
+ },
+
+ stroke: function (items) {
+ var o = this.options;
+ if (BI.isNumber(o.rowSize)) {
+ o.rowSize = BI.makeArray(o.items.length, 1 / o.items.length);
+ }
+ if (BI.isNumber(o.columnSize)) {
+ o.columnSize = BI.makeArray(o.items[0].length, 1 / o.items[0].length);
+ }
+ function firstElement(item, row, col) {
+ if (row === 0) {
+ item.addClass("first-row")
+ }
+ if (col === 0) {
+ item.addClass("first-col");
+ }
+ item.addClass(BI.isOdd(row + 1) ? "odd-row" : "even-row");
+ item.addClass(BI.isOdd(col + 1) ? "odd-col" : "even-col");
+ item.addClass("center-element");
+ }
+
+ function firstObject(item, row, col) {
+ var cls = "";
+ if (row === 0) {
+ cls += " first-row";
+ }
+ if (col === 0) {
+ cls += " first-col";
+ }
+ BI.isOdd(row + 1) ? (cls += " odd-row") : (cls += " even-row");
+ BI.isOdd(col + 1) ? (cls += " odd-col") : (cls += " even-col");
+ item.cls = (item.cls || "") + cls + " center-element";
+ }
+
+ function first(item, row, col) {
+ if (item instanceof BI.Widget) {
+ firstElement(item.element, row, col);
+ } else if (item.el instanceof BI.Widget) {
+ firstElement(item.el.element, row, col);
+ } else if (item.el) {
+ firstObject(item.el, row, col)
+ } else {
+ firstObject(item, row, col);
+ }
+ }
+
+ for (var i = 0; i < o.rows; i++) {
+ for (var j = 0; j < o.columns; j++) {
+ if (!o.items[i][j]) {
+ throw new Error("item be required");
+ }
+ if (!this.hasWidget(this.getName() + i + "_" + j)) {
+ var w = BI.createWidget(o.items[i][j]);
+ w.element.css({"position": "absolute"});
+ this.addWidget(this.getName() + i + "_" + j, w);
+ }
+ }
+ }
+ var left = {}, right = {}, top = {}, bottom = {};
+ left[0] = 0;
+ top[0] = 0;
+ right[o.columns - 1] = 0;
+ bottom[o.rows - 1] = 0;
+ //从上到下
+ for (var i = 0; i < o.rows; i++) {
+ for (var j = 0; j < o.columns; j++) {
+ var wi = this.getWidgetByName(this.getName() + i + "_" + j);
+ if (BI.isNull(top[i])) {
+ top[i] = top[i - 1] + (o.rowSize[i - 1] < 1 ? o.rowSize[i - 1] : o.rowSize[i - 1] + o.vgap + o.bgap);
+ }
+ var t = top[i] <= 1 ? top[i] * 100 + "%" : top[i] + o.vgap + o.tgap + "px", h = "";
+ if (BI.isNumber(o.rowSize[i])) {
+ h = o.rowSize[i] <= 1 ? o.rowSize[i] * 100 + "%" : o.rowSize[i] + "px";
+ }
+ wi.element.css({"top": t, height: h});
+ first(wi, i, j);
+ }
+ if (!BI.isNumber(o.rowSize[i])) {
+ break;
+ }
+ }
+ //从下到上
+ for (var i = o.rows - 1; i >= 0; i--) {
+ for (var j = 0; j < o.columns; j++) {
+ var wi = this.getWidgetByName(this.getName() + i + "_" + j);
+ if (BI.isNull(bottom[i])) {
+ bottom[i] = bottom[i + 1] + (o.rowSize[i + 1] < 1 ? o.rowSize[i + 1] : o.rowSize[i + 1] + o.vgap + o.tgap);
+ }
+ var b = bottom[i] <= 1 ? bottom[i] * 100 + "%" : bottom[i] + o.vgap + o.bgap + "px", h = "";
+ if (BI.isNumber(o.rowSize[i])) {
+ h = o.rowSize[i] <= 1 ? o.rowSize[i] * 100 + "%" : o.rowSize[i] + "px";
+ }
+ wi.element.css({"bottom": b, height: h});
+ first(wi, i, j);
+ }
+ if (!BI.isNumber(o.rowSize[i])) {
+ break;
+ }
+ }
+ //从左到右
+ for (var j = 0; j < o.columns; j++) {
+ for (var i = 0; i < o.rows; i++) {
+ var wi = this.getWidgetByName(this.getName() + i + "_" + j);
+ if (BI.isNull(left[j])) {
+ left[j] = left[j - 1] + (o.columnSize[j - 1] < 1 ? o.columnSize[j - 1] : o.columnSize[j - 1] + o.hgap + o.rgap);
+ }
+ var l = left[j] <= 1 ? left[j] * 100 + "%" : left[j] + o.hgap + o.lgap + "px", w = "";
+ if (BI.isNumber(o.columnSize[j])) {
+ w = o.columnSize[j] <= 1 ? o.columnSize[j] * 100 + "%" : o.columnSize[j] + "px";
+ }
+ wi.element.css({"left": l, width: w});
+ first(wi, i, j);
+ }
+ if (!BI.isNumber(o.columnSize[j])) {
+ break;
+ }
+ }
+ //从右到左
+ for (var j = o.columns - 1; j >= 0; j--) {
+ for (var i = 0; i < o.rows; i++) {
+ var wi = this.getWidgetByName(this.getName() + i + "_" + j);
+ if (BI.isNull(right[j])) {
+ right[j] = right[j + 1] + (o.columnSize[j + 1] < 1 ? o.columnSize[j + 1] : o.columnSize[j + 1] + o.hgap + o.lgap)
+ }
+ var r = right[j] <= 1 ? right[j] * 100 + "%" : right[j] + o.hgap + o.rgap + "px", w = "";
+ if (BI.isNumber(o.columnSize[j])) {
+ w = o.columnSize[j] <= 1 ? o.columnSize[j] * 100 + "%" : o.columnSize[j] + "px";
+ }
+ wi.element.css({"right": r, width: w});
+ first(wi, i, j);
+ }
+ if (!BI.isNumber(o.columnSize[j])) {
+ break;
+ }
+ }
+ },
+
+ populate: function (items) {
+ BI.WindowLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.window', BI.WindowLayout);/**
+ * 水平和垂直方向都居中容器, 非自适应,用于宽度高度固定的面板
+ * @class BI.CenterLayout
+ * @extends BI.Layout
+ */
+BI.CenterLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.CenterLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-center-layout",
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+
+ render: function () {
+ BI.CenterLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ resize: function () {
+ // console.log("center布局不需要resize");
+ },
+
+ addItem: function (item) {
+ //do nothing
+ throw new Error("cannot be added");
+ },
+
+ stroke: function (items) {
+ var self = this, o = this.options;
+ var list = [];
+ BI.each(items, function (i) {
+ list.push({
+ column: i,
+ row: 0,
+ el: BI.createWidget({
+ type: "bi.default",
+ cls: "center-element " + (i === 0 ? "first-element " : "") + (i === items.length - 1 ? "last-element" : "")
+ })
+ });
+ });
+ BI.each(items, function (i, item) {
+ if (!!item) {
+ var w = BI.createWidget(item);
+ w.element.css({
+ position: "absolute",
+ left: o.hgap + o.lgap,
+ right: o.hgap + o.rgap,
+ top: o.vgap + o.tgap,
+ bottom: o.vgap + o.bgap,
+ width: "auto",
+ height: "auto"
+ });
+ list[i].el.addItem(w);
+ }
+ });
+ BI.createWidget({
+ type: "bi.grid",
+ element: this,
+ columns: list.length,
+ rows: 1,
+ items: list
+ });
+ },
+
+ populate: function (items) {
+ BI.CenterLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.center', BI.CenterLayout);/**
+ * 浮动布局实现的居中容器
+ * @class BI.FloatCenterLayout
+ * @extends BI.Layout
+ */
+BI.FloatCenterLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.FloatCenterLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-float-center-layout",
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+ render: function () {
+ BI.FloatCenterLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ resize: function () {
+ // console.log("floatcenter布局不需要resize");
+ },
+
+ addItem: function (item) {
+ //do nothing
+ throw new Error("cannot be added")
+ },
+
+ stroke: function (items) {
+ var self = this, o = this.options;
+ var list = [], width = 100 / items.length;
+ BI.each(items, function (i) {
+ var widget = BI.createWidget({
+ type: "bi.default"
+ });
+ widget.element.addClass("center-element " + (i === 0 ? "first-element " : "") + (i === items.length - 1 ? "last-element" : "")).css({
+ width: width + "%",
+ height: "100%"
+ });
+ list.push({
+ el: widget
+ });
+ });
+ BI.each(items, function (i, item) {
+ if (!!item) {
+ var w = BI.createWidget(item);
+ w.element.css({
+ position: "absolute",
+ left: o.hgap + o.lgap,
+ right: o.hgap + o.rgap,
+ top: o.vgap + o.tgap,
+ bottom: o.vgap + o.bgap,
+ width: "auto",
+ height: "auto"
+ });
+ list[i].el.addItem(w);
+ }
+ });
+ BI.createWidget({
+ type: "bi.left",
+ element: this,
+ items: list
+ });
+ },
+
+ populate: function (items) {
+ BI.FloatCenterLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.float_center', BI.FloatCenterLayout);/**
+ * 水平和垂直方向都居中容器, 非自适应,用于宽度高度固定的面板
+ * @class BI.HorizontalCenterLayout
+ * @extends BI.Layout
+ */
+BI.HorizontalCenterLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.HorizontalCenterLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-horizontal-center-layout",
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+ render: function () {
+ BI.HorizontalCenterLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ resize: function () {
+ // console.log("horizontal_center布局不需要resize");
+ },
+
+ addItem: function (item) {
+ //do nothing
+ throw new Error("cannot be added")
+ },
+
+ stroke: function (items) {
+ var o = this.options;
+ var list = [];
+ BI.each(items, function (i) {
+ list.push({
+ column: i,
+ row: 0,
+ el: BI.createWidget({
+ type: "bi.default",
+ cls: "center-element " + (i === 0 ? "first-element " : "") + (i === items.length - 1 ? "last-element" : "")
+ })
+ });
+ });
+ BI.each(items, function (i, item) {
+ if (!!item) {
+ var w = BI.createWidget(item);
+ w.element.css({
+ position: "absolute",
+ left: o.hgap + o.lgap,
+ right: o.hgap + o.rgap,
+ top: o.vgap + o.tgap,
+ bottom: o.vgap + o.bgap,
+ width: "auto"
+ });
+ list[i].el.addItem(w);
+ }
+ });
+ BI.createWidget({
+ type: "bi.grid",
+ element: this,
+ columns: list.length,
+ rows: 1,
+ items: list
+ });
+ },
+
+ populate: function (items) {
+ BI.HorizontalCenterLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.horizontal_center', BI.HorizontalCenterLayout);/**
+ * 垂直方向都居中容器, 非自适应,用于高度不固定的面板
+ * @class BI.VerticalCenterLayout
+ * @extends BI.Layout
+ */
+BI.VerticalCenterLayout = BI.inherit(BI.Layout, {
+ props: function () {
+ return BI.extend(BI.VerticalCenterLayout.superclass.props.apply(this, arguments), {
+ baseCls: "bi-vertical-center-layout",
+ hgap: 0,
+ vgap: 0,
+ lgap: 0,
+ rgap: 0,
+ tgap: 0,
+ bgap: 0
+ });
+ },
+ render: function () {
+ BI.VerticalCenterLayout.superclass.render.apply(this, arguments);
+ this.populate(this.options.items);
+ },
+
+ resize: function () {
+ // console.log("vertical_center布局不需要resize");
+ },
+
+ addItem: function (item) {
+ //do nothing
+ throw new Error("cannot be added")
+ },
+
+ stroke: function (items) {
+ var self = this, o = this.options;
+ var list = [];
+ BI.each(items, function (i) {
+ list.push({
+ column: 0,
+ row: i,
+ el: BI.createWidget({
+ type: "bi.default",
+ cls: "center-element " + (i === 0 ? "first-element " : "") + (i === items.length - 1 ? "last-element" : "")
+ })
+ });
+ });
+ BI.each(items, function (i, item) {
+ if (!!item) {
+ var w = BI.createWidget(item);
+ w.element.css({
+ position: "absolute",
+ left: o.hgap + o.lgap,
+ right: o.hgap + o.rgap,
+ top: o.vgap + o.tgap,
+ bottom: o.vgap + o.bgap,
+ height: "auto"
+ });
+ list[i].el.addItem(w);
+ }
+ });
+ BI.createWidget({
+ type: "bi.grid",
+ element: this,
+ columns: 1,
+ rows: list.length,
+ items: list
+ });
+ },
+
+ populate: function (items) {
+ BI.VerticalCenterLayout.superclass.populate.apply(this, arguments);
+ this._mount();
+ }
+});
+BI.shortcut('bi.vertical_center', BI.VerticalCenterLayout);/**
+ * 保存数据,将js里面用到的常量数据都分离
+ *
+ */
+BI.Data = Data = {};
+
+/**
+ * 存放bi里面通用的一些常量
+ * @type {{}}
+ */
+Data.Constant = BI.Constant = BICst = {};
+/**
+ * 缓冲池
+ * @type {{Buffer: {}}}
+ */
+;
+(function () {
+ var Buffer = {};
+ var MODE = false;//设置缓存模式为关闭
+
+ Data.BufferPool = {
+ put: function (name, cache) {
+ if (BI.isNotNull(Buffer[name])) {
+ throw new Error("Buffer Pool has the key already!");
+ }
+ Buffer[name] = cache;
+ },
+
+ get: function (name) {
+ return Buffer[name];
+ },
+ };
+})();/**
+ * 共享池
+ * @type {{Shared: {}}}
+ */
+;
+(function () {
+ var _Shared = {};
+ Data.SharingPool = {
+ _Shared: _Shared,
+ put: function (name, shared) {
+ _Shared[name] = shared;
+ },
+
+ cat: function () {
+ var args = Array.prototype.slice.call(arguments, 0),
+ copy = _Shared;
+ for (var i = 0; i < args.length; i++) {
+ copy = copy[args[i]];
+ }
+ return copy;
+ },
+
+ get: function () {
+ return BI.deepClone(this.cat.apply(this, arguments));
+ },
+
+ remove: function (key) {
+ delete _Shared[key];
+ }
+ };
+})();Data.Req = {
+
+};
+Data.Source = BISource = {
+
+};//工程配置
+$(function () {
+ //注册布局
+ var isSupportFlex = BI.isSupportCss3("flex");
+ BI.Plugin.registerWidget("bi.horizontal", function (ob) {
+ if (isSupportFlex) {
+ return BI.extend(ob, {type: "bi.flex_horizontal"});
+ } else {
+ return ob;
+ }
+ });
+ BI.Plugin.registerWidget("bi.center_adapt", function (ob) {
+ if (isSupportFlex && ob.items && ob.items.length <= 1) {
+ //有滚动条的情况下需要用到flex_wrapper_center布局
+ if (ob.scrollable === true || ob.scrollx === true || ob.scrolly === true) {
+ //不是IE用flex_wrapper_center布局
+ if (!BI.isIE()) {
+ return BI.extend(ob, {type: "bi.flex_wrapper_center"});
+ }
+ return ob;
+ }
+ return BI.extend(ob, {type: "bi.flex_center"});
+ } else {
+ return ob;
+ }
+ });
+ BI.Plugin.registerWidget("bi.vertical_adapt", function (ob) {
+ if (isSupportFlex) {
+ //有滚动条的情况下需要用到flex_wrapper_center布局
+ if (ob.scrollable === true || ob.scrollx === true || ob.scrolly === true) {
+ //不是IE用flex_wrapper_center布局
+ if (!BI.isIE()) {
+ return BI.extend({}, ob, {type: "bi.flex_wrapper_vertical_center"});
+ }
+ return ob;
+ }
+ return BI.extend(ob, {type: "bi.flex_vertical_center"});
+ } else {
+ return ob;
+ }
+ });
+ BI.Plugin.registerWidget("bi.float_center_adapt", function (ob) {
+ if (isSupportFlex) {
+ //有滚动条的情况下需要用到flex_wrapper_center布局
+ if (ob.scrollable === true || ob.scrollx === true || ob.scrolly === true) {
+ //不是IE用flex_wrapper_center布局
+ if (!BI.isIE()) {
+ return BI.extend({}, ob, {type: "bi.flex_wrapper_center"});
+ }
+ return ob;
+ }
+ return BI.extend(ob, {type: "bi.flex_center"});
+ } else {
+ return ob;
+ }
+ });
+ //注册滚动条
+ BI.Plugin.registerWidget("bi.grid_table_scrollbar", function (ob) {
+ if (BI.isIE9Below()) {
+ return BI.extend(ob, {type: "bi.native_table_scrollbar"});
+ } else {
+ return ob;
+ }
+ });
+ BI.Plugin.registerWidget("bi.grid_table_horizontal_scrollbar", function (ob) {
+ if (BI.isIE9Below()) {
+ return BI.extend(ob, {type: "bi.native_table_horizontal_scrollbar"});
+ } else {
+ return ob;
+ }
+ });
+
+ //注册控件
+ BI.Plugin.registerWidget("bi.grid_table", function (ob) {
+ //非chrome下滚动条滑动效果不好,禁止掉
+ if (!(BI.isChrome() && BI.isWindows() && !BI.isEdge())) {
+ return BI.extend(ob, {type: "bi.quick_grid_table"});
+ } else {
+ return ob;
+ }
+ });
+ BI.Plugin.registerWidget("bi.collection_table", function (ob) {
+ //非chrome下滚动条滑动效果不好,禁止掉
+ if (!(BI.isChrome() && BI.isWindows() && !BI.isEdge())) {
+ return BI.extend(ob, {type: "bi.quick_collection_table"});
+ } else {
+ return ob;
+ }
+ });
+ //IE8下滚动条用原生的
+ if (BI.isIE9Below()) {
+ BI.GridTableScrollbar.SIZE = 18;
+ }
+>>>>>>> f7ab8fadf8581f5a532908fdb0283047312fd570
});
\ No newline at end of file
diff --git a/src/base/single/editor/editor.textarea.js b/src/base/single/editor/editor.textarea.js
index 5efc3fae5..7b424bab1 100644
--- a/src/base/single/editor/editor.textarea.js
+++ b/src/base/single/editor/editor.textarea.js
@@ -19,7 +19,7 @@ BI.TextAreaEditor = BI.inherit(BI.Single, {
tagName: "textarea",
width: "100%",
height: "100%",
- cls: "textarea-editor-content display-block"
+ cls: "bi-textarea textarea-editor-content display-block"
});
this.content.element.css({"resize": "none"});
BI.createWidget({
diff --git a/src/base/single/iframe/iframe.js b/src/base/single/iframe/iframe.js
index 77230d4a3..141be9b13 100644
--- a/src/base/single/iframe/iframe.js
+++ b/src/base/single/iframe/iframe.js
@@ -30,6 +30,15 @@ BI.Iframe = BI.inherit(BI.Single, {
return this.options.src;
},
+ setName: function (name) {
+ this.options.name = name;
+ this.element.attr("name", name);
+ },
+
+ getName: function () {
+ return this.options.name;
+ },
+
getWidth: function () {
return this.options.width
},
diff --git a/src/core/func/dom.js b/src/core/func/dom.js
index 979b7a64b..59ce4fa6b 100644
--- a/src/core/func/dom.js
+++ b/src/core/func/dom.js
@@ -19,7 +19,7 @@ BI.extend(jQuery.fn, {
* @private
*/
__textKeywordMarked__: function (text, keyword, py) {
- if (!BI.isKey(keyword)) {
+ if (!BI.isKey(keyword) || (text + "").length > 100) {
return this.text((text + "").replaceAll(" ", " "));
}
keyword = keyword + "";
diff --git a/src/core/model.js b/src/core/model.js
index a45cfb5e1..fa7b2613b 100644
--- a/src/core/model.js
+++ b/src/core/model.js
@@ -203,6 +203,10 @@ BI.Model = BI.inherit(BI.M, {
var copy = BI.UUID(), newKeys = BI.clone(keys);
keys.length > 1 ? newKeys.unshift(BI.deepClone(p[keys[keys.length - 1]])) : newKeys.unshift(BI.deepClone(g));
var backup = self.similar.apply(self, newKeys);
+ if (BI.isKey(backup.id)) {
+ copy = backup.id;
+ delete backup.id;
+ }
keys.length > 1 ? (p[copy] = backup, self[sset](keys[0], g, {silent: true})) : self[sset](copy, backup, {silent: true});
keys.unshift(copy);
!BI.has(self._tmp, keys[0]) && self.parent && self.parent._change(self);
diff --git a/src/core/wrapper/layout/adapt/float.center.js b/src/core/wrapper/layout/adapt/float.center.js
index 78f963094..b359f19e2 100644
--- a/src/core/wrapper/layout/adapt/float.center.js
+++ b/src/core/wrapper/layout/adapt/float.center.js
@@ -29,15 +29,20 @@ BI.FloatCenterAdaptLayout = BI.inherit(BI.Layout, {
},
mounted: function () {
+ var self = this;
var width = this.left.element.outerWidth(),
height = this.left.element.outerHeight();
this.left.element.width(width).height(height).css("float", "none");
+ BI.remove(this._children, function (i, wi) {
+ if (wi === self.container) {
+ delete self._children[i];
+ }
+ });
BI.createWidget({
type: "bi.center_adapt",
element: this,
items: [this.left]
});
- this.removeWidget(this.container);
},
stroke: function (items) {
diff --git a/src/core/wrapper/layout/adapt/float.horizontal.js b/src/core/wrapper/layout/adapt/float.horizontal.js
index 8fd043e21..5f4cfed3a 100644
--- a/src/core/wrapper/layout/adapt/float.horizontal.js
+++ b/src/core/wrapper/layout/adapt/float.horizontal.js
@@ -24,15 +24,20 @@ BI.FloatHorizontalLayout = BI.inherit(BI.Layout, {
},
mounted: function () {
+ var self = this;
var width = this.left.element.width(),
height = this.left.element.height();
this.left.element.width(width).height(height).css("float", "none");
+ BI.remove(this._children, function (i, wi) {
+ if (wi === self.container) {
+ delete self._children[i];
+ }
+ });
BI.createWidget({
type: "bi.horizontal_auto",
element: this,
items: [this.left]
});
- this.removeWidget(this.container);
},
_addElement: function (i, item) {
diff --git a/src/css/core/utils/common.css b/src/css/core/utils/common.css
index 0d10234d9..f362b482d 100644
--- a/src/css/core/utils/common.css
+++ b/src/css/core/utils/common.css
@@ -5,6 +5,9 @@
.base-disabled .bi-input {
color: #cccccc !important;
}
+.base-disabled .bi-textarea {
+ color: #cccccc !important;
+}
.base-disabled .b-font:before {
color: #cccccc !important;
}
@@ -14,6 +17,9 @@
.bi-theme-dark .base-disabled .bi-input {
color: #666666 !important;
}
+.bi-theme-dark .base-disabled .bi-textarea {
+ color: #666666 !important;
+}
.bi-theme-dark .base-disabled .b-font:before {
color: #666666 !important;
}
@@ -39,6 +45,9 @@
.bi-background .bi-input {
color: #666666;
}
+.bi-background .bi-textarea {
+ color: #666666;
+}
.bi-theme-dark .bi-background {
background-color: #191b2b;
color: #cccccc;
@@ -46,6 +55,9 @@
.bi-theme-dark .bi-background .bi-input {
color: #cccccc;
}
+.bi-theme-dark .bi-background .bi-textarea {
+ color: #cccccc;
+}
.bi-card {
background-color: #ffffff;
color: #666666;
@@ -53,6 +65,9 @@
.bi-card .bi-input {
color: #666666;
}
+.bi-card .bi-textarea {
+ color: #666666;
+}
.bi-theme-dark .bi-card {
background-color: #242640;
color: #cccccc;
@@ -60,24 +75,36 @@
.bi-theme-dark .bi-card .bi-input {
color: #cccccc;
}
+.bi-theme-dark .bi-card .bi-textarea {
+ color: #cccccc;
+}
.bi-disabled {
color: #cccccc;
}
.bi-disabled .bi-input {
color: #cccccc;
}
+.bi-disabled .bi-textarea {
+ color: #cccccc;
+}
.bi-theme-dark .bi-disabled {
color: #666666;
}
.bi-theme-dark .bi-disabled .bi-input {
color: #666666;
}
+.bi-theme-dark .bi-disabled .bi-textarea {
+ color: #666666;
+}
.bi-tips {
color: #999999;
}
.bi-tips .bi-input {
color: #999999;
}
+.bi-tips .bi-textarea {
+ color: #999999;
+}
.bi-border {
border: 1px solid #d4dadd;
}
@@ -114,12 +141,18 @@
.bi-keyword-red-mark .bi-input {
color: #f07d0a;
}
+.bi-keyword-red-mark .bi-textarea {
+ color: #f07d0a;
+}
.bi-high-light {
color: #3f8ce8;
}
.bi-high-light .bi-input {
color: #3f8ce8;
}
+.bi-high-light .bi-textarea {
+ color: #3f8ce8;
+}
.bi-high-light-background {
background-color: #3f8ce8;
color: #ffffff;
@@ -127,6 +160,9 @@
.bi-high-light-background .bi-input {
color: #ffffff;
}
+.bi-high-light-background .bi-textarea {
+ color: #ffffff;
+}
.bi-high-light-border {
border-color: #178cdf;
}
@@ -137,12 +173,18 @@
.bi-water-mark .bi-input {
color: #cccccc;
}
+.bi-water-mark .bi-textarea {
+ color: #cccccc;
+}
.bi-theme-dark .bi-water-mark {
color: #666666;
}
.bi-theme-dark .bi-water-mark .bi-input {
color: #666666;
}
+.bi-theme-dark .bi-water-mark .bi-textarea {
+ color: #666666;
+}
.bi-resizer {
background: #1a1a1a;
opacity: 0.2;
@@ -160,6 +202,9 @@
.bi-mask .bi-input {
color: #ffffff;
}
+.bi-mask .bi-textarea {
+ color: #ffffff;
+}
.bi-theme-dark .bi-mask {
color: #242640;
background-color: rgba(255, 255, 255, 0.2);
@@ -168,6 +213,9 @@
.bi-theme-dark .bi-mask .bi-input {
color: #242640;
}
+.bi-theme-dark .bi-mask .bi-textarea {
+ color: #242640;
+}
.bi-z-index-mask {
color: #ffffff;
background-color: rgba(26, 26, 26, 0.5);
@@ -176,6 +224,9 @@
.bi-z-index-mask .bi-input {
color: #ffffff;
}
+.bi-z-index-mask .bi-textarea {
+ color: #ffffff;
+}
.bi-list-item:hover,
.bi-list-item.hover {
color: #1a1a1a;
@@ -186,6 +237,10 @@
.bi-list-item.hover .bi-input {
color: #1a1a1a;
}
+.bi-list-item:hover .bi-textarea,
+.bi-list-item.hover .bi-textarea {
+ color: #1a1a1a;
+}
.bi-list-item.disabled,
.bi-list-item.disabled:hover,
.bi-list-item.disabled:active {
@@ -197,6 +252,11 @@
.bi-list-item.disabled:active .bi-input {
color: #cccccc !important;
}
+.bi-list-item.disabled .bi-textarea,
+.bi-list-item.disabled:hover .bi-textarea,
+.bi-list-item.disabled:active .bi-textarea {
+ color: #cccccc !important;
+}
.bi-list-item.disabled .bi-high-light,
.bi-list-item.disabled:hover .bi-high-light,
.bi-list-item.disabled:active .bi-high-light {
@@ -212,6 +272,10 @@
.bi-theme-dark .bi-list-item.hover .bi-input {
color: #ffffff;
}
+.bi-theme-dark .bi-list-item:hover .bi-textarea,
+.bi-theme-dark .bi-list-item.hover .bi-textarea {
+ color: #ffffff;
+}
.bi-theme-dark .bi-list-item.disabled,
.bi-theme-dark .bi-list-item.disabled:hover,
.bi-theme-dark .bi-list-item.disabled:active {
@@ -223,6 +287,11 @@
.bi-theme-dark .bi-list-item.disabled:active .bi-input {
color: #666666 !important;
}
+.bi-theme-dark .bi-list-item.disabled .bi-textarea,
+.bi-theme-dark .bi-list-item.disabled:hover .bi-textarea,
+.bi-theme-dark .bi-list-item.disabled:active .bi-textarea {
+ color: #666666 !important;
+}
.bi-theme-dark .bi-list-item.disabled .bi-high-light,
.bi-theme-dark .bi-list-item.disabled:hover .bi-high-light,
.bi-theme-dark .bi-list-item.disabled:active .bi-high-light {
@@ -238,6 +307,9 @@
.bi-list-item-simple .bi-input {
color: #999999;
}
+.bi-list-item-simple .bi-textarea {
+ color: #999999;
+}
.bi-list-item-simple:hover,
.bi-list-item-simple.hover {
color: #3f8ce8;
@@ -246,6 +318,10 @@
.bi-list-item-simple.hover .bi-input {
color: #3f8ce8;
}
+.bi-list-item-simple:hover .bi-textarea,
+.bi-list-item-simple.hover .bi-textarea {
+ color: #3f8ce8;
+}
.bi-list-item-simple.disabled,
.bi-list-item-simple.disabled:hover,
.bi-list-item-simple.disabled:active {
@@ -256,6 +332,11 @@
.bi-list-item-simple.disabled:active .bi-input {
color: #cccccc !important;
}
+.bi-list-item-simple.disabled .bi-textarea,
+.bi-list-item-simple.disabled:hover .bi-textarea,
+.bi-list-item-simple.disabled:active .bi-textarea {
+ color: #cccccc !important;
+}
.bi-list-item-simple.disabled .bi-high-light,
.bi-list-item-simple.disabled:hover .bi-high-light,
.bi-list-item-simple.disabled:active .bi-high-light {
@@ -267,6 +348,9 @@
.bi-list-item-effect:hover .bi-input {
color: #1a1a1a;
}
+.bi-list-item-effect:hover .bi-textarea {
+ color: #1a1a1a;
+}
.bi-list-item-effect.active,
.bi-list-item-effect:active {
color: #3f8ce8;
@@ -275,6 +359,10 @@
.bi-list-item-effect:active .bi-input {
color: #3f8ce8;
}
+.bi-list-item-effect.active .bi-textarea,
+.bi-list-item-effect:active .bi-textarea {
+ color: #3f8ce8;
+}
.bi-list-item-effect.disabled,
.bi-list-item-effect.disabled:hover,
.bi-list-item-effect.disabled:active {
@@ -285,6 +373,11 @@
.bi-list-item-effect.disabled:active .bi-input {
color: #cccccc !important;
}
+.bi-list-item-effect.disabled .bi-textarea,
+.bi-list-item-effect.disabled:hover .bi-textarea,
+.bi-list-item-effect.disabled:active .bi-textarea {
+ color: #cccccc !important;
+}
.bi-list-item-effect.disabled .bi-high-light,
.bi-list-item-effect.disabled:hover .bi-high-light,
.bi-list-item-effect.disabled:active .bi-high-light {
@@ -296,6 +389,9 @@
.bi-theme-dark .bi-list-item-effect:hover .bi-input {
color: #ffffff;
}
+.bi-theme-dark .bi-list-item-effect:hover .bi-textarea {
+ color: #ffffff;
+}
.bi-theme-dark .bi-list-item-effect.active,
.bi-theme-dark .bi-list-item-effect:active {
color: #3f8ce8;
@@ -304,6 +400,10 @@
.bi-theme-dark .bi-list-item-effect:active .bi-input {
color: #3f8ce8;
}
+.bi-theme-dark .bi-list-item-effect.active .bi-textarea,
+.bi-theme-dark .bi-list-item-effect:active .bi-textarea {
+ color: #3f8ce8;
+}
.bi-theme-dark .bi-list-item-effect.disabled,
.bi-theme-dark .bi-list-item-effect.disabled:hover,
.bi-theme-dark .bi-list-item-effect.disabled:active {
@@ -315,6 +415,11 @@
.bi-theme-dark .bi-list-item-effect.disabled:active .bi-input {
color: #666666 !important;
}
+.bi-theme-dark .bi-list-item-effect.disabled .bi-textarea,
+.bi-theme-dark .bi-list-item-effect.disabled:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-effect.disabled:active .bi-textarea {
+ color: #666666 !important;
+}
.bi-theme-dark .bi-list-item-effect.disabled .bi-high-light,
.bi-theme-dark .bi-list-item-effect.disabled:hover .bi-high-light,
.bi-theme-dark .bi-list-item-effect.disabled:active .bi-high-light {
@@ -330,6 +435,10 @@
.bi-list-item-active.hover .bi-input {
color: #1a1a1a;
}
+.bi-list-item-active:hover .bi-textarea,
+.bi-list-item-active.hover .bi-textarea {
+ color: #1a1a1a;
+}
.bi-list-item-active.active,
.bi-list-item-active:active {
color: #3f8ce8;
@@ -340,6 +449,10 @@
.bi-list-item-active:active .bi-input {
color: #3f8ce8;
}
+.bi-list-item-active.active .bi-textarea,
+.bi-list-item-active:active .bi-textarea {
+ color: #3f8ce8;
+}
.bi-list-item-active.disabled,
.bi-list-item-active.disabled:hover,
.bi-list-item-active.disabled:active {
@@ -351,6 +464,11 @@
.bi-list-item-active.disabled:active .bi-input {
color: #cccccc !important;
}
+.bi-list-item-active.disabled .bi-textarea,
+.bi-list-item-active.disabled:hover .bi-textarea,
+.bi-list-item-active.disabled:active .bi-textarea {
+ color: #cccccc !important;
+}
.bi-list-item-active.disabled .bi-high-light,
.bi-list-item-active.disabled:hover .bi-high-light,
.bi-list-item-active.disabled:active .bi-high-light {
@@ -366,6 +484,10 @@
.bi-theme-dark .bi-list-item-active.hover .bi-input {
color: #ffffff;
}
+.bi-theme-dark .bi-list-item-active:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-active.hover .bi-textarea {
+ color: #ffffff;
+}
.bi-theme-dark .bi-list-item-active.active,
.bi-theme-dark .bi-list-item-active:active {
color: #3f8ce8;
@@ -376,6 +498,10 @@
.bi-theme-dark .bi-list-item-active:active .bi-input {
color: #3f8ce8;
}
+.bi-theme-dark .bi-list-item-active.active .bi-textarea,
+.bi-theme-dark .bi-list-item-active:active .bi-textarea {
+ color: #3f8ce8;
+}
.bi-theme-dark .bi-list-item-active.disabled,
.bi-theme-dark .bi-list-item-active.disabled:hover,
.bi-theme-dark .bi-list-item-active.disabled:active {
@@ -387,6 +513,11 @@
.bi-theme-dark .bi-list-item-active.disabled:active .bi-input {
color: #666666 !important;
}
+.bi-theme-dark .bi-list-item-active.disabled .bi-textarea,
+.bi-theme-dark .bi-list-item-active.disabled:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-active.disabled:active .bi-textarea {
+ color: #666666 !important;
+}
.bi-theme-dark .bi-list-item-active.disabled .bi-high-light,
.bi-theme-dark .bi-list-item-active.disabled:hover .bi-high-light,
.bi-theme-dark .bi-list-item-active.disabled:active .bi-high-light {
@@ -401,6 +532,10 @@
.bi-list-item-active2.hover .bi-input {
color: #1a1a1a;
}
+.bi-list-item-active2:hover .bi-textarea,
+.bi-list-item-active2.hover .bi-textarea {
+ color: #1a1a1a;
+}
.bi-list-item-active2.active,
.bi-list-item-active2:active {
color: #3f8ce8;
@@ -410,6 +545,10 @@
.bi-list-item-active2:active .bi-input {
color: #3f8ce8;
}
+.bi-list-item-active2.active .bi-textarea,
+.bi-list-item-active2:active .bi-textarea {
+ color: #3f8ce8;
+}
.bi-list-item-active2.disabled,
.bi-list-item-active2.disabled:hover,
.bi-list-item-active2.disabled:active {
@@ -421,6 +560,11 @@
.bi-list-item-active2.disabled:active .bi-input {
color: #cccccc !important;
}
+.bi-list-item-active2.disabled .bi-textarea,
+.bi-list-item-active2.disabled:hover .bi-textarea,
+.bi-list-item-active2.disabled:active .bi-textarea {
+ color: #cccccc !important;
+}
.bi-list-item-active2.disabled .bi-high-light,
.bi-list-item-active2.disabled:hover .bi-high-light,
.bi-list-item-active2.disabled:active .bi-high-light {
@@ -435,6 +579,10 @@
.bi-theme-dark .bi-list-item-active2.hover .bi-input {
color: #ffffff;
}
+.bi-theme-dark .bi-list-item-active2:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-active2.hover .bi-textarea {
+ color: #ffffff;
+}
.bi-theme-dark .bi-list-item-active2.active,
.bi-theme-dark .bi-list-item-active2:active {
color: #3f8ce8;
@@ -444,6 +592,10 @@
.bi-theme-dark .bi-list-item-active2:active .bi-input {
color: #3f8ce8;
}
+.bi-theme-dark .bi-list-item-active2.active .bi-textarea,
+.bi-theme-dark .bi-list-item-active2:active .bi-textarea {
+ color: #3f8ce8;
+}
.bi-theme-dark .bi-list-item-active2.disabled,
.bi-theme-dark .bi-list-item-active2.disabled:hover,
.bi-theme-dark .bi-list-item-active2.disabled:active {
@@ -455,6 +607,11 @@
.bi-theme-dark .bi-list-item-active2.disabled:active .bi-input {
color: #666666 !important;
}
+.bi-theme-dark .bi-list-item-active2.disabled .bi-textarea,
+.bi-theme-dark .bi-list-item-active2.disabled:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-active2.disabled:active .bi-textarea {
+ color: #666666 !important;
+}
.bi-theme-dark .bi-list-item-active2.disabled .bi-high-light,
.bi-theme-dark .bi-list-item-active2.disabled:hover .bi-high-light,
.bi-theme-dark .bi-list-item-active2.disabled:active .bi-high-light {
@@ -470,6 +627,10 @@
.bi-list-item-select.hover .bi-input {
color: #1a1a1a;
}
+.bi-list-item-select:hover .bi-textarea,
+.bi-list-item-select.hover .bi-textarea {
+ color: #1a1a1a;
+}
.bi-list-item-select:active,
.bi-list-item-select.active {
color: #ffffff;
@@ -479,6 +640,10 @@
.bi-list-item-select.active .bi-input {
color: #ffffff;
}
+.bi-list-item-select:active .bi-textarea,
+.bi-list-item-select.active .bi-textarea {
+ color: #ffffff;
+}
.bi-list-item-select:active .bi-high-light,
.bi-list-item-select.active .bi-high-light {
color: #ffffff;
@@ -494,6 +659,11 @@
.bi-list-item-select.disabled:active .bi-input {
color: #cccccc !important;
}
+.bi-list-item-select.disabled .bi-textarea,
+.bi-list-item-select.disabled:hover .bi-textarea,
+.bi-list-item-select.disabled:active .bi-textarea {
+ color: #cccccc !important;
+}
.bi-list-item-select.disabled .bi-high-light,
.bi-list-item-select.disabled:hover .bi-high-light,
.bi-list-item-select.disabled:active .bi-high-light {
@@ -509,6 +679,10 @@
.bi-theme-dark .bi-list-item-select.hover .bi-input {
color: #ffffff;
}
+.bi-theme-dark .bi-list-item-select:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-select.hover .bi-textarea {
+ color: #ffffff;
+}
.bi-theme-dark .bi-list-item-select:active,
.bi-theme-dark .bi-list-item-select.active {
color: #ffffff;
@@ -518,6 +692,10 @@
.bi-theme-dark .bi-list-item-select.active .bi-input {
color: #ffffff;
}
+.bi-theme-dark .bi-list-item-select:active .bi-textarea,
+.bi-theme-dark .bi-list-item-select.active .bi-textarea {
+ color: #ffffff;
+}
.bi-theme-dark .bi-list-item-select:active .bi-high-light,
.bi-theme-dark .bi-list-item-select.active .bi-high-light {
color: #ffffff;
@@ -533,6 +711,11 @@
.bi-theme-dark .bi-list-item-select.disabled:active .bi-input {
color: #666666 !important;
}
+.bi-theme-dark .bi-list-item-select.disabled .bi-textarea,
+.bi-theme-dark .bi-list-item-select.disabled:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-select.disabled:active .bi-textarea {
+ color: #666666 !important;
+}
.bi-theme-dark .bi-list-item-select.disabled .bi-high-light,
.bi-theme-dark .bi-list-item-select.disabled:hover .bi-high-light,
.bi-theme-dark .bi-list-item-select.disabled:active .bi-high-light {
@@ -547,6 +730,10 @@
.bi-list-item-none.hover .bi-input {
color: inherit;
}
+.bi-list-item-none:hover .bi-textarea,
+.bi-list-item-none.hover .bi-textarea {
+ color: inherit;
+}
.bi-list-item-none:active,
.bi-list-item-none.active {
color: inherit;
@@ -556,6 +743,10 @@
.bi-list-item-none.active .bi-input {
color: inherit;
}
+.bi-list-item-none:active .bi-textarea,
+.bi-list-item-none.active .bi-textarea {
+ color: inherit;
+}
.bi-list-item-none:active .bi-high-light,
.bi-list-item-none.active .bi-high-light {
color: inherit;
@@ -571,6 +762,11 @@
.bi-list-item-none.disabled:active .bi-input {
color: #cccccc !important;
}
+.bi-list-item-none.disabled .bi-textarea,
+.bi-list-item-none.disabled:hover .bi-textarea,
+.bi-list-item-none.disabled:active .bi-textarea {
+ color: #cccccc !important;
+}
.bi-list-item-none.disabled .bi-high-light,
.bi-list-item-none.disabled:hover .bi-high-light,
.bi-list-item-none.disabled:active .bi-high-light {
@@ -585,6 +781,10 @@
.bi-theme-dark .bi-list-item-none.hover .bi-input {
color: inherit;
}
+.bi-theme-dark .bi-list-item-none:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-none.hover .bi-textarea {
+ color: inherit;
+}
.bi-theme-dark .bi-list-item-none:active,
.bi-theme-dark .bi-list-item-none.active {
color: inherit;
@@ -594,6 +794,10 @@
.bi-theme-dark .bi-list-item-none.active .bi-input {
color: inherit;
}
+.bi-theme-dark .bi-list-item-none:active .bi-textarea,
+.bi-theme-dark .bi-list-item-none.active .bi-textarea {
+ color: inherit;
+}
.bi-theme-dark .bi-list-item-none:active .bi-high-light,
.bi-theme-dark .bi-list-item-none.active .bi-high-light {
color: inherit;
@@ -609,6 +813,11 @@
.bi-theme-dark .bi-list-item-none.disabled:active .bi-input {
color: #666666 !important;
}
+.bi-theme-dark .bi-list-item-none.disabled .bi-textarea,
+.bi-theme-dark .bi-list-item-none.disabled:hover .bi-textarea,
+.bi-theme-dark .bi-list-item-none.disabled:active .bi-textarea {
+ color: #666666 !important;
+}
.bi-theme-dark .bi-list-item-none.disabled .bi-high-light,
.bi-theme-dark .bi-list-item-none.disabled:hover .bi-high-light,
.bi-theme-dark .bi-list-item-none.disabled:active .bi-high-light {
diff --git a/src/less/core/utils/common.less b/src/less/core/utils/common.less
index 2dd6dcc1a..a81b98d5b 100644
--- a/src/less/core/utils/common.less
+++ b/src/less/core/utils/common.less
@@ -6,6 +6,9 @@
& .bi-input {
color: @color-bi-text-disabled !important;
}
+ & .bi-textarea {
+ color: @color-bi-text-disabled !important;
+ }
& .b-font:before {
color: @color-bi-text-disabled !important;
}
@@ -17,6 +20,9 @@
& .bi-input {
color: @color-bi-text-disabled-theme-dark !important;
}
+ & .bi-textarea {
+ color: @color-bi-text-disabled-theme-dark !important;
+ }
& .b-font:before {
color: @color-bi-text-disabled-theme-dark !important;
}
@@ -38,6 +44,9 @@
& .bi-input {
color: @color-bi-text-normal;
}
+ & .bi-textarea {
+ color: @color-bi-text-normal;
+ }
}
.bi-theme-dark {
@@ -47,6 +56,9 @@
& .bi-input {
color: @color-bi-text-theme-dark;
}
+ & .bi-textarea {
+ color: @color-bi-text-theme-dark;
+ }
}
}
@@ -57,6 +69,9 @@
& .bi-input {
color: @color-bi-text-normal;
}
+ & .bi-textarea {
+ color: @color-bi-text-normal;
+ }
}
.bi-theme-dark {
@@ -66,6 +81,9 @@
& .bi-input {
color: @color-bi-text-theme-dark;
}
+ & .bi-textarea {
+ color: @color-bi-text-theme-dark;
+ }
}
}
@@ -74,6 +92,9 @@
& .bi-input {
color: @color-bi-text-disabled;
}
+ & .bi-textarea {
+ color: @color-bi-text-disabled;
+ }
}
.bi-theme-dark {
@@ -82,6 +103,9 @@
& .bi-input {
color: @color-bi-text-disabled-theme-dark;
}
+ & .bi-textarea {
+ color: @color-bi-text-disabled-theme-dark;
+ }
}
}
@@ -91,6 +115,9 @@
& .bi-input {
color: @color-bi-text-tips;
}
+ & .bi-textarea {
+ color: @color-bi-text-tips;
+ }
}
//边框
@@ -150,6 +177,9 @@
& .bi-input {
color: @color-bi-text-redmark;
}
+ & .bi-textarea {
+ color: @color-bi-text-redmark;
+ }
}
//高亮
@@ -158,6 +188,9 @@
& .bi-input {
color: @color-bi-text-highlight;
}
+ & .bi-textarea {
+ color: @color-bi-text-highlight;
+ }
}
.bi-high-light-background {
@@ -166,6 +199,9 @@
& .bi-input {
color: @color-bi-text;
}
+ & .bi-textarea {
+ color: @color-bi-text;
+ }
}
.bi-high-light-border {
@@ -179,6 +215,9 @@
& .bi-input {
color: @water-mark-color;
}
+ & .bi-textarea {
+ color: @water-mark-color;
+ }
}
.bi-theme-dark {
@@ -187,6 +226,9 @@
& .bi-input {
color: @water-mark-color-theme-dark;
}
+ & .bi-textarea {
+ color: @water-mark-color-theme-dark;
+ }
}
}
@@ -208,6 +250,9 @@
& .bi-input {
color: @color-bi-background-default;
}
+ & .bi-textarea {
+ color: @color-bi-background-default;
+ }
.background-color(@color-bi-background-black, 20%);
}
@@ -217,6 +262,9 @@
& .bi-input {
color: @color-bi-background-default-theme-dark;
}
+ & .bi-textarea {
+ color: @color-bi-background-default-theme-dark;
+ }
.background-color(@color-bi-background-default, 20%);
}
}
@@ -226,6 +274,9 @@
& .bi-input {
color: @color-bi-background-default;
}
+ & .bi-textarea {
+ color: @color-bi-background-default;
+ }
.background-color(@color-bi-background-black, 50%);
}
@@ -236,6 +287,9 @@
& .bi-input {
color: @color-bi-text-black;
}
+ & .bi-textarea {
+ color: @color-bi-text-black;
+ }
.background-color(@color-bi-background-black, 5%);
}
&.disabled {
@@ -245,6 +299,9 @@
& .bi-input {
color: @color-bi-text-disabled !important;
}
+ & .bi-textarea {
+ color: @color-bi-text-disabled !important;
+ }
& .bi-high-light {
color: @color-bi-text-disabled !important;
}
@@ -259,6 +316,9 @@
& .bi-input {
color: @color-bi-text;
}
+ & .bi-textarea {
+ color: @color-bi-text;
+ }
.background-color(@color-bi-background-default, 5%);
}
&.disabled {
@@ -268,6 +328,9 @@
& .bi-input {
color: @color-bi-text-disabled-theme-dark !important;
}
+ & .bi-textarea {
+ color: @color-bi-text-disabled-theme-dark !important;
+ }
& .bi-high-light {
color: @color-bi-text-disabled-theme-dark !important;
}
@@ -288,11 +351,17 @@
& .bi-input {
color: @color-bi-text-tips;
}
+ & .bi-textarea {
+ color: @color-bi-text-tips;
+ }
&:hover, &.hover {
color: @color-bi-text-highlight;
& .bi-input {
color: @color-bi-text-highlight;
}
+ & .bi-textarea {
+ color: @color-bi-text-highlight;
+ }
}
&.disabled {
&, &:hover, &:active {
@@ -300,6 +369,9 @@
& .bi-input {
color: @color-bi-text-disabled !important;
}
+ & .bi-textarea {
+ color: @color-bi-text-disabled !important;
+ }
& .bi-high-light {
color: @color-bi-text-disabled !important;
}
@@ -314,12 +386,18 @@
& .bi-input {
color: @color-bi-text-black;
}
+ & .bi-textarea {
+ color: @color-bi-text-black;
+ }
}
&.active, &:active {
color: @color-bi-text-highlight;
& .bi-input {
color: @color-bi-text-highlight;
}
+ & .bi-textarea {
+ color: @color-bi-text-highlight;
+ }
}
&.disabled {
&, &:hover, &:active {
@@ -327,6 +405,9 @@
& .bi-input {
color: @color-bi-text-disabled !important;
}
+ & .bi-textarea {
+ color: @color-bi-text-disabled !important;
+ }
& .bi-high-light {
color: @color-bi-text-disabled !important;
}
@@ -341,12 +422,18 @@
& .bi-input {
color: @color-bi-text;
}
+ & .bi-textarea {
+ color: @color-bi-text;
+ }
}
&.active, &:active {
color: @color-bi-text-highlight;
& .bi-input {
color: @color-bi-text-highlight;
}
+ & .bi-textarea {
+ color: @color-bi-text-highlight;
+ }
}
&.disabled {
&, &:hover, &:active {
@@ -355,6 +442,9 @@
& .bi-input {
color: @color-bi-text-disabled-theme-dark !important;
}
+ & .bi-textarea {
+ color: @color-bi-text-disabled-theme-dark !important;
+ }
& .bi-high-light {
color: @color-bi-text-disabled-theme-dark !important;
}
@@ -370,6 +460,9 @@
& .bi-input {
color: @color-bi-text-black;
}
+ & .bi-textarea {
+ color: @color-bi-text-black;
+ }
.background-color(@color-bi-background-black, 5%);
}
&.active, &:active {
@@ -377,6 +470,9 @@
& .bi-input {
color: @color-bi-text-highlight;
}
+ & .bi-textarea {
+ color: @color-bi-text-highlight;
+ }
.background-color(@color-bi-background-black, 5%);
}
&.disabled {
@@ -386,6 +482,9 @@
& .bi-input {
color: @color-bi-text-disabled !important;
}
+ & .bi-textarea {
+ color: @color-bi-text-disabled !important;
+ }
& .bi-high-light {
color: @color-bi-text-disabled !important;
}
@@ -400,6 +499,9 @@
& .bi-input {
color: @color-bi-text;
}
+ & .bi-textarea {
+ color: @color-bi-text;
+ }
.background-color(@color-bi-background-default, 5%);
}
&.active, &:active {
@@ -407,6 +509,9 @@
& .bi-input {
color: @color-bi-text-highlight;
}
+ & .bi-textarea {
+ color: @color-bi-text-highlight;
+ }
.background-color(@color-bi-background-default, 5%);
}
&.disabled {
@@ -416,6 +521,9 @@
& .bi-input {
color: @color-bi-text-disabled-theme-dark !important;
}
+ & .bi-textarea {
+ color: @color-bi-text-disabled-theme-dark !important;
+ }
& .bi-high-light {
color: @color-bi-text-disabled-theme-dark !important;
}
@@ -431,6 +539,9 @@
& .bi-input {
color: @color-bi-text-black;
}
+ & .bi-textarea {
+ color: @color-bi-text-black;
+ }
background-color: @color-bi-background-default;
}
&.active, &:active {
@@ -438,6 +549,9 @@
& .bi-input {
color: @color-bi-text-highlight;
}
+ & .bi-textarea {
+ color: @color-bi-text-highlight;
+ }
background-color: @color-bi-background-default;
}
&.disabled {
@@ -447,6 +561,9 @@
& .bi-input {
color: @color-bi-text-disabled !important;
}
+ & .bi-textarea {
+ color: @color-bi-text-disabled !important;
+ }
& .bi-high-light {
color: @color-bi-text-disabled !important;
}
@@ -461,6 +578,9 @@
& .bi-input {
color: @color-bi-text;
}
+ & .bi-textarea {
+ color: @color-bi-text;
+ }
background-color: @color-bi-background-default-theme-dark;
}
&.active, &:active {
@@ -468,6 +588,9 @@
& .bi-input {
color: @color-bi-text-highlight;
}
+ & .bi-textarea {
+ color: @color-bi-text-highlight;
+ }
background-color: @color-bi-background-default-theme-dark;
}
&.disabled {
@@ -477,6 +600,9 @@
& .bi-input {
color: @color-bi-text-disabled-theme-dark !important;
}
+ & .bi-textarea {
+ color: @color-bi-text-disabled-theme-dark !important;
+ }
& .bi-high-light {
color: @color-bi-text-disabled-theme-dark !important;
}
@@ -492,6 +618,9 @@
& .bi-input {
color: @color-bi-text-black;
}
+ & .bi-textarea {
+ color: @color-bi-text-black;
+ }
.background-color(@color-bi-background-black, 5%);
}
&:active, &.active {
@@ -499,6 +628,9 @@
& .bi-input {
color: @color-bi-text;
}
+ & .bi-textarea {
+ color: @color-bi-text;
+ }
background-color: @color-bi-background-highlight;
& .bi-high-light {
color: @color-bi-text;
@@ -510,6 +642,9 @@
& .bi-input {
color: @color-bi-text-disabled !important;
}
+ & .bi-textarea {
+ color: @color-bi-text-disabled !important;
+ }
background-color: transparent !important;
& .bi-high-light {
color: @color-bi-text-disabled !important;
@@ -525,6 +660,9 @@
& .bi-input {
color: @color-bi-text;
}
+ & .bi-textarea {
+ color: @color-bi-text;
+ }
.background-color(@color-bi-background-default, 5%);
}
&:active, &.active {
@@ -532,6 +670,9 @@
& .bi-input {
color: @color-bi-text;
}
+ & .bi-textarea {
+ color: @color-bi-text;
+ }
background-color: @color-bi-background-highlight;
& .bi-high-light {
color: @color-bi-text;
@@ -544,6 +685,9 @@
& .bi-input {
color: @color-bi-text-disabled-theme-dark !important;
}
+ & .bi-textarea {
+ color: @color-bi-text-disabled-theme-dark !important;
+ }
& .bi-high-light {
color: @color-bi-text-disabled-theme-dark !important;
}
@@ -559,6 +703,9 @@
& .bi-input {
color: inherit;
}
+ & .bi-textarea {
+ color: inherit;
+ }
background-color: inherit;
}
&:active, &.active {
@@ -566,6 +713,9 @@
& .bi-input {
color: inherit;
}
+ & .bi-textarea {
+ color: inherit;
+ }
background-color: inherit;
& .bi-high-light {
color: inherit;
@@ -577,6 +727,9 @@
& .bi-input {
color: @color-bi-text-disabled !important;
}
+ & .bi-textarea {
+ color: @color-bi-text-disabled !important;
+ }
background-color: transparent !important;
& .bi-high-light {
color: @color-bi-text-disabled !important;
@@ -592,6 +745,9 @@
& .bi-input {
color: inherit;
}
+ & .bi-textarea {
+ color: inherit;
+ }
background-color: inherit;
}
&:active, &.active {
@@ -599,6 +755,9 @@
& .bi-input {
color: inherit;
}
+ & .bi-textarea {
+ color: inherit;
+ }
background-color: inherit;
& .bi-high-light {
color: inherit;
@@ -611,6 +770,9 @@
& .bi-input {
color: @color-bi-text-disabled-theme-dark !important;
}
+ & .bi-textarea {
+ color: @color-bi-text-disabled-theme-dark !important;
+ }
& .bi-high-light {
color: @color-bi-text-disabled-theme-dark !important;
}
diff --git a/src/widget/downlist/combo.downlist.js b/src/widget/downlist/combo.downlist.js
index 5f6a6b854..303395341 100644
--- a/src/widget/downlist/combo.downlist.js
+++ b/src/widget/downlist/combo.downlist.js
@@ -10,6 +10,7 @@ BI.DownListCombo = BI.inherit(BI.Widget, {
items: [],
adjustLength: 0,
direction: "bottom",
+ trigger: "click",
el: {}
})
},
@@ -37,6 +38,7 @@ BI.DownListCombo = BI.inherit(BI.Widget, {
this.downlistcombo = BI.createWidget({
element: this,
type: 'bi.combo',
+ trigger: o.trigger,
isNeedAdjustWidth: false,
adjustLength: o.adjustLength,
direction: o.direction,