").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 0d58f4cd4..d07adc5bf 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/bi/widget.js b/bi/widget.js
index 8061cc712..9799dd01a 100644
--- a/bi/widget.js
+++ b/bi/widget.js
@@ -629,7 +629,12 @@ BI.AdaptiveArrangement = BI.inherit(BI.Widget, {
clearInterval(self._scrollInterval);
self._scrollInterval = null;
}
+ var count = 0;
self._scrollInterval = setInterval(function () {
+ count++;
+ if (count <= 3) {
+ return;
+ }
var offset = self._getScrollOffset();
var t = offset.top + map[direction][0] * 40;
var l = offset.left + map[direction][1] * 40;
@@ -2613,22 +2618,23 @@ BI.DateCalendarPopup = BI.inherit(BI.Widget, {
month: date.month,
day: this.selectedTime.day
});
- return calendar;
+ return calendar
},
_init: function () {
BI.DateCalendarPopup.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
+ var self = this,
+ o = this.options;
this.today = new Date();
this._year = this.today.getFullYear();
this._month = this.today.getMonth();
this._day = this.today.getDate();
this.selectedTime = o.selectedTime || {
- year: this._year,
- month: this._month,
- day: this._day
- };
+ year: this._year,
+ month: this._month,
+ day: this._day
+ };
this.datePicker = BI.createWidget({
type: "bi.date_picker",
min: o.min,
@@ -2764,7 +2770,8 @@ BI.DateCombo = BI.inherit(BI.Widget, {
},
_init: function () {
BI.DateCombo.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
+ var self = this,
+ o = this.options;
this.trigger = BI.createWidget({
type: "bi.date_trigger"
@@ -5292,7 +5299,7 @@ BI.FileManagerNavButton = BI.inherit(BI.Widget, {
_const: {
normal_color: "#ffffff",
- select_color: "#f4f4f4"
+ select_color: "#eff1f4"
},
_defaultConfig: function () {
return BI.extend(BI.FileManagerNavButton.superclass._defaultConfig.apply(this, arguments), {
diff --git a/demo/css/main.css b/demo/css/main.css
index 60476fa50..c1f015137 100644
--- a/demo/css/main.css
+++ b/demo/css/main.css
@@ -48,3 +48,30 @@ body {
.demo-editor {
border: 1px solid #cccccc;
}
+.demo-clolor {
+ color: #1a1a1a;
+}
+.bi-progress-bar-processor {
+ transition: all 0.5s ease;
+ -webkit-transition: all 0.5s ease;
+ -moz-transition: all 0.5s ease;
+ -o-transition: all 0.5s ease;
+ background: #3f8ce8;
+ -webkit-border-radius: 20px;
+ -moz-border-radius: 20px;
+ border-radius: 20px;
+ overflow: hidden;
+ overflow-x: hidden;
+ overflow-y: hidden;
+}
+.bi-progress-text-bar-processor {
+ transition: all 0.5s ease;
+ -webkit-transition: all 0.5s ease;
+ -moz-transition: all 0.5s ease;
+ -o-transition: all 0.5s ease;
+}
+.bi-progress-bar-bar {
+ -webkit-border-radius: 20px;
+ -moz-border-radius: 20px;
+ border-radius: 20px;
+}
diff --git a/demo/js/widget/editor/demo.shelter_editor.js b/demo/js/case/editor/demo.shelter_editor.js
similarity index 100%
rename from demo/js/widget/editor/demo.shelter_editor.js
rename to demo/js/case/editor/demo.shelter_editor.js
diff --git a/demo/js/widget/editor/demo.sign_editor.js b/demo/js/case/editor/demo.sign_editor.js
similarity index 100%
rename from demo/js/widget/editor/demo.sign_editor.js
rename to demo/js/case/editor/demo.sign_editor.js
diff --git a/demo/js/widget/editor/demo.sign_initial_editor.js b/demo/js/case/editor/demo.sign_initial_editor.js
similarity index 55%
rename from demo/js/widget/editor/demo.sign_initial_editor.js
rename to demo/js/case/editor/demo.sign_initial_editor.js
index 480d4d498..49bc5a5d0 100644
--- a/demo/js/widget/editor/demo.sign_initial_editor.js
+++ b/demo/js/case/editor/demo.sign_initial_editor.js
@@ -5,17 +5,26 @@ Demo.SignInitialEditor = BI.inherit(BI.Widget, {
props: {
baseCls: ""
},
+ mounted: function () {
+ this.editor.setValue({
+ value: "123",
+ text: "sdga"
+ })
+ },
render: function () {
+ var self = this;
return {
type: "bi.horizontal_adapt",
items: [{
type: "bi.sign_initial_editor",
- cls:"layout-bg5",
- value:"123",
- text:"456",
+ ref: function () {
+ self.editor = this;
+ },
+ cls: "layout-bg5",
+ text: "原始值",
width: 300
}],
- vgap:20
+ vgap: 20
}
}
diff --git a/demo/js/widget/editor/demo.state_editor.js b/demo/js/case/editor/demo.state_editor.js
similarity index 67%
rename from demo/js/widget/editor/demo.state_editor.js
rename to demo/js/case/editor/demo.state_editor.js
index dedc7d024..c4dbb83f3 100644
--- a/demo/js/widget/editor/demo.state_editor.js
+++ b/demo/js/case/editor/demo.state_editor.js
@@ -10,12 +10,11 @@ Demo.StateEditor = BI.inherit(BI.Widget, {
type: "bi.horizontal_adapt",
items: [{
type: "bi.state_editor",
- cls:"bi-border",
- value:"123",
- text:"456",
+ value: "123",
+ text: "456",
width: 300
}],
- vgap:20
+ vgap: 20
}
}
diff --git a/demo/js/config/case.js b/demo/js/config/case.js
index 3b477402b..9988901a8 100644
--- a/demo/js/config/case.js
+++ b/demo/js/config/case.js
@@ -6,10 +6,6 @@ Demo.CASE_CONFIG = [{
pId: 3,
id: 301,
text: "editors"
-}, {
- pId: 301,
- text: "bi.record_editor",
- value: "demo.record_editor"
}, {
pId: 301,
text: "bi.shelter_editor",
@@ -18,6 +14,10 @@ Demo.CASE_CONFIG = [{
pId: 301,
text: "bi.sign_editor",
value: "demo.sign_editor"
+}, {
+ pId: 301,
+ text: "bi.sign_initial_editor",
+ value: "demo.sign_initial_editor"
}, {
pId: 301,
text: "bi.state_editor",
diff --git a/demo/js/config/component.js b/demo/js/config/component.js
index 755a60f95..41e76b6fe 100644
--- a/demo/js/config/component.js
+++ b/demo/js/config/component.js
@@ -3,7 +3,7 @@
*/
Demo.COMPONENT_CONFIG = [{
id: 5,
- text: "部件"
+ text: "部件+服务"
}, {
pId: 5,
text: "bi.value_chooser_combo",
diff --git a/demo/js/config/widget.js b/demo/js/config/widget.js
index fa15cb2fb..9c1533740 100644
--- a/demo/js/config/widget.js
+++ b/demo/js/config/widget.js
@@ -1,257 +1,256 @@
Demo.WIDGET_CONFIG = [{
- id: 4,
- text: "详细控件",
- open: true
- }, {
- id: 400,
- pId: 4,
- text: "tree"
- }, {
- pId: 400,
- text: "bi.multi_tree_combo",
- value: "demo.multi_tree_combo"
- }, {
- id: 401,
- pId: 4,
- text: "table"
- }, {
- pId: 401,
- text: "bi.preview_table",
- value: "demo.preview_table"
- }, {
- pId: 401,
- text: "bi.responsive_table",
- value: "demo.responsive_table"
- }, {
- pId: 401,
- text: "bi.excel_table",
- value: "demo.excel_table"
- }, {
- pId: 4,
- id: 402,
- text: "年份控件",
- open: false
- }, {
- pId: 402,
- text: "bi.year_combo",
- value: "demo.year"
- }, {
- pId: 4,
- id: 403,
- text: "月份控件",
- open: false
- }, {
- pId: 403,
- text: "bi.month_combo",
- value: "demo.month"
- }, {
- pId: 4,
- id: 404,
- text: "季度控件",
- open: false
- }, {
- pId: 404,
- text: "bi.quarter_combo",
- value: "demo.quarter"
- }, {
- pId: 4,
- id: 405,
- text: "下拉列表",
- open: false
- }, {
- pId: 405,
- text: "bi.down_list_combo",
- value: "demo.down_list"
- }, {
- pId: 4,
- id: 406,
- text: "文本框控件",
- open: false
- }, {
- pId: 406,
- text: "bi.text_editor",
- value: "demo.text_editor"
- }, {
- pId: 406,
- text: "bi.search_editor",
- value: "demo.search_editor"
- }, {
- pId: 406,
- text: "bi.sign_editor",
- value: "demo.sign_editor"
- }, {
- pId: 406,
- text: "bi.sign_initial_editor",
- value: "demo.sign_initial_editor"
- }, {
- pId: 406,
- text: "bi.sign_style_editor",
- value: "demo.sign_style_editor"
- }, {
- pId: 406,
- text: "bi.state_editor",
- value: "demo.state_editor"
- }, {
- pId: 406,
- text: "bi.clear_editor",
- value: "demo.clear_editor"
- }, {
- pId: 406,
- text: "bi.record_editor",
- value: "demo.record_editor"
- }, {
- pId: 406,
- text: "bi.shelter_editor",
- value: "demo.shelter_editor"
- },
- {
- pId: 4,
- id: 407,
- text: "下拉框控件",
- open: false
- }, {
- pId: 407,
- text: "bi.text_value_combo",
- value: "demo.text_value_combo"
- }, {
- pId: 407,
- text: "bi.text_value_check_combo",
- value: "demo.text_value_check_combo"
- }, {
- pId: 407,
- text: "bi.text_value_down_list_combo",
- value: "demo.text_value_down_list_combo"
- }, {
- pId: 407,
- text: "bi.static_combo",
- value: "demo.static_combo"
- }, {
- pId: 407,
- text: "bi.icon_combo",
- value: "demo.icon_combo"
- }, {
- pId: 407,
- text: "bi.formula_combo",
- value: "demo.formula_combo"
- }, {
- pId: 4,
- id: 408,
- text: "选择字段列表",
- open: false
- }, {
- pId: 408,
- text: "bi.placeholder"
- }, {
- pId: 4,
- id: 409,
- text: "公式编辑器",
- open: false
- }, {
- pId: 409,
- text: "bi.placeholder"
- }, {
- pId: 4,
- id: 410,
- text: "数值区间控件"
- }, {
- pId: 410,
- text: "bi.numerical_interval",
- value: "demo.numberical_interval"
- }, {
- pId: 4,
- id: 411,
- text: "下拉复选框有确定按钮"
- }, {
- pId: 411,
- text: "bi.multi_select_combo",
- value: "demo.multi_select_combo"
- }, {
- pId: 4,
- id: 412,
- text: "简单日期控件"
- }, {
- pId: 412,
- text: "bi.date_combo",
- value: "demo.date"
- }, {
- pId: 412,
- text: "bi.date_pane_widget",
- value: "demo.date_pane_widget"
- }, {
- pId: 412,
- text: "bi.year_month_combo",
- value: "demo.year_month_combo"
- },{
- pId: 412,
- text: "bi.year_quarter_combo",
- value: "demo.year_quarter_combo"
- },{
- pId: 412,
- text: "bi.custom_date_time",
- value: "demo.custom_date_time"
- },{
- pId: 4,
- id: 413,
- text: "简单下拉树"
- }, {
- pId: 413,
- text: "bi.single_tree_combo",
- value: "demo.single_tree_combo"
- }, {
- pId: 413,
- text: "bi.multilayer_single_tree_combo",
- value: "demo.multilayer_single_tree_combo"
- }, {
- pId: 4,
- id: 414,
- text: "可选下拉树"
- }, {
- pId: 414,
- text: "bi.select_tree_combo",
- value: "demo.select_tree_combo"
- }, {
- pId: 414,
- text: "bi.multilayer_select_tree_combo",
- value: "demo.multilayer_select_tree_combo"
- }, {
- pId: 4,
- id: 415,
- text: "路径选择"
- }, {
- pId: 415,
- text: "bi.path_chooser",
- value: "demo.path_chooser"
- }, {
- pId: 415,
- text: "bi.direction_path_chooser",
- value: "demo.direction_path_chooser"
- }, {
- pId: 4,
- id: 416,
- text: "关联视图"
- }, {
- pId: 416,
- text: "bi.relation_view",
- value: "demo.relation_view"
- }, {
- pId: 4,
- id: 417,
- text: "布局"
- }, {
- pId: 417,
- text: "bi.adaptive_arrangement",
- value: "demo.adaptive_arrangement"
- }, {
- pId: 417,
- text: "bi.interactive_arrangement",
- value: "demo.interactive_arrangement"
- }, {
- pId: 4,
- id: 418,
- text: "提示对话框"
- }, {
- pId: 418,
- text: "bi.dialog",
- value: "demo.dialog"
- }
-];
+ id: 4,
+ text: "详细控件",
+ open: true
+}, {
+ pId: 4,
+ id: 420,
+ text: '各种小控件',
+}, {
+ pId: 420,
+ text: "各种通用按钮",
+ value: "demo.buttons"
+}, {
+ pId: 420,
+ text: "各种提示性信息",
+ value: "demo.tips"
+}, {
+ pId: 420,
+ text: "各种items",
+ value: "demo.items"
+}, {
+ pId: 420,
+ text: "各种节点node",
+ value: "demo.nodes"
+}, {
+ pId: 420,
+ text: "各种segment",
+ value: "demo.segments"
+}, {
+ pId: 420,
+ text: "可以切换的树",
+ value: "demo.switch_tree"
+}, {
+ id: 400,
+ pId: 4,
+ text: "tree"
+}, {
+ pId: 400,
+ text: "bi.multi_tree_combo",
+ value: "demo.multi_tree_combo"
+}, {
+ pId: 400,
+ text: "bi.switch_tree",
+ value: "demo.switch_tree"
+}, {
+ id: 401,
+ pId: 4,
+ text: "table"
+}, {
+ pId: 401,
+ text: "bi.preview_table",
+ value: "demo.preview_table"
+}, {
+ pId: 401,
+ text: "bi.responsive_table",
+ value: "demo.responsive_table"
+}, {
+ pId: 401,
+ text: "bi.excel_table",
+ value: "demo.excel_table"
+}, {
+ pId: 4,
+ id: 402,
+ text: "年份控件",
+ open: false
+}, {
+ pId: 402,
+ text: "bi.year_combo",
+ value: "demo.year"
+}, {
+ pId: 4,
+ id: 403,
+ text: "月份控件",
+ open: false
+}, {
+ pId: 403,
+ text: "bi.month_combo",
+ value: "demo.month"
+}, {
+ pId: 4,
+ id: 404,
+ text: "季度控件",
+ open: false
+}, {
+ pId: 404,
+ text: "bi.quarter_combo",
+ value: "demo.quarter"
+}, {
+ pId: 4,
+ id: 405,
+ text: "下拉列表",
+ open: false
+}, {
+ pId: 405,
+ text: "bi.down_list_combo",
+ value: "demo.down_list"
+}, {
+ pId: 4,
+ id: 406,
+ text: "文本框控件",
+ open: false
+}, {
+ pId: 406,
+ text: "bi.text_editor",
+ value: "demo.text_editor"
+}, {
+ pId: 406,
+ text: "bi.search_editor",
+ value: "demo.search_editor"
+}, {
+ pId: 406,
+ text: "bi.clear_editor",
+ value: "demo.clear_editor"
+}, {
+ pId: 4,
+ id: 407,
+ text: "下拉框控件",
+ open: false
+}, {
+ pId: 407,
+ text: "bi.text_value_combo",
+ value: "demo.text_value_combo"
+}, {
+ pId: 407,
+ text: "bi.text_value_check_combo",
+ value: "demo.text_value_check_combo"
+}, {
+ pId: 407,
+ text: "bi.text_value_down_list_combo",
+ value: "demo.text_value_down_list_combo"
+}, {
+ pId: 407,
+ text: "bi.static_combo",
+ value: "demo.static_combo"
+}, {
+ pId: 407,
+ text: "bi.icon_combo",
+ value: "demo.icon_combo"
+}, {
+ pId: 407,
+ text: "bi.formula_combo",
+ value: "demo.formula_combo"
+}, {
+ pId: 4,
+ id: 410,
+ text: "数值区间控件"
+}, {
+ pId: 410,
+ text: "bi.numerical_interval",
+ value: "demo.numberical_interval"
+}, {
+ pId: 4,
+ id: 411,
+ text: "下拉复选框有确定按钮"
+}, {
+ pId: 411,
+ text: "bi.multi_select_combo",
+ value: "demo.multi_select_combo"
+}, {
+ pId: 4,
+ id: 412,
+ text: "简单日期控件"
+}, {
+ pId: 412,
+ text: "bi.date_combo",
+ value: "demo.date"
+}, {
+ pId: 412,
+ text: "bi.date_pane_widget",
+ value: "demo.date_pane_widget"
+}, {
+ pId: 412,
+ text: "bi.year_month_combo",
+ value: "demo.year_month_combo"
+}, {
+ pId: 412,
+ text: "bi.year_quarter_combo",
+ value: "demo.year_quarter_combo"
+}, {
+ pId: 412,
+ text: "bi.custom_date_time",
+ value: "demo.custom_date_time"
+}, {
+ pId: 4,
+ id: 413,
+ text: "简单下拉树"
+}, {
+ pId: 413,
+ text: "bi.single_tree_combo",
+ value: "demo.single_tree_combo"
+}, {
+ pId: 413,
+ text: "bi.multilayer_single_tree_combo",
+ value: "demo.multilayer_single_tree_combo"
+}, {
+ pId: 4,
+ id: 414,
+ text: "可选下拉树"
+}, {
+ pId: 414,
+ text: "bi.select_tree_combo",
+ value: "demo.select_tree_combo"
+}, {
+ pId: 414,
+ text: "bi.multilayer_select_tree_combo",
+ value: "demo.multilayer_select_tree_combo"
+}, {
+ pId: 4,
+ id: 415,
+ text: "路径选择"
+}, {
+ pId: 415,
+ text: "bi.path_chooser",
+ value: "demo.path_chooser"
+}, {
+ pId: 415,
+ text: "bi.direction_path_chooser",
+ value: "demo.direction_path_chooser"
+}, {
+ pId: 4,
+ id: 416,
+ text: "关联视图"
+}, {
+ pId: 416,
+ text: "bi.relation_view",
+ value: "demo.relation_view"
+}, {
+ pId: 4,
+ id: 417,
+ text: "布局"
+}, {
+ pId: 417,
+ text: "bi.adaptive_arrangement",
+ value: "demo.adaptive_arrangement"
+}, {
+ pId: 417,
+ text: "bi.interactive_arrangement",
+ value: "demo.interactive_arrangement"
+}, {
+ pId: 4,
+ id: 418,
+ text: "提示对话框"
+}, {
+ pId: 418,
+ text: "bi.dialog",
+ value: "demo.dialog"
+}, {
+ pId: 4,
+ id: 419,
+ text: "文件管理"
+}, {
+ pId: 419,
+ text: "bi.file_manager",
+ value: "demo.file_manager"
+}
+];
\ No newline at end of file
diff --git a/demo/js/widget/basewidget/demo.buttons.js b/demo/js/widget/basewidget/demo.buttons.js
new file mode 100644
index 000000000..dbddc3b0e
--- /dev/null
+++ b/demo/js/widget/basewidget/demo.buttons.js
@@ -0,0 +1,205 @@
+/**
+ * Created by Dailer on 2017/7/25.
+ */
+
+
+Demo.Buttons = BI.inherit(BI.Widget, {
+ props: {
+ baseCls: "demo-button"
+ },
+ render: function () {
+ var items = [{
+ el: {
+ type: 'bi.button',
+ text: '一般按钮',
+ level: 'common',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '表示成功状态按钮',
+ level: 'success',
+ height: 30
+ }
+ },
+ {
+ el: {
+ type: 'bi.button',
+ text: '表示警告状态的按钮',
+ level: 'warning',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '表示忽略状态的按钮',
+ level: 'ignore',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '普通灰化按钮',
+ disabled: true,
+ level: 'success',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '忽略状态灰化按钮',
+ disabled: true,
+ level: 'ignore',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '带图标的按钮',
+ //level: 'ignore',
+ iconClass: "close-font",
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '一般按钮',
+ block: true,
+ level: 'common',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '表示成功状态按钮',
+ block: true,
+ level: 'success',
+ height: 30
+ }
+ },
+ {
+ el: {
+ type: 'bi.button',
+ text: '表示警告状态的按钮',
+ block: true,
+ level: 'warning',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '表示忽略状态的按钮',
+ block: true,
+ level: 'ignore',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '普通灰化按钮',
+ block: true,
+ disabled: true,
+ level: 'success',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '忽略状态灰化按钮',
+ block: true,
+ disabled: true,
+ level: 'ignore',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '带图标的按钮',
+ block: true,
+ //level: 'ignore',
+ iconClass: "close-font",
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '一般按钮',
+ clear: true,
+ level: 'common',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '表示成功状态按钮',
+ clear: true,
+ level: 'success',
+ height: 30
+ }
+ },
+ {
+ el: {
+ type: 'bi.button',
+ text: '表示警告状态的按钮',
+ clear: true,
+ level: 'warning',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '表示忽略状态的按钮',
+ clear: true,
+ level: 'ignore',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '普通灰化按钮',
+ clear: true,
+ disabled: true,
+ level: 'success',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '忽略状态灰化按钮',
+ clear: true,
+ disabled: true,
+ level: 'ignore',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '带图标的按钮',
+ clear: true,
+ //level: 'ignore',
+ iconClass: "close-font",
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.text_button',
+ text: '文字按钮',
+ height: 30
+ }
+ }
+ ];
+ BI.each(items, function (i, item) {
+ item.el.handler = function () {
+ BI.Msg.alert('按钮', this.options.text);
+ }
+ });
+ return {
+ type: "bi.left",
+ vgap: 100,
+ hgap: 20,
+ items: items
+ }
+ }
+});
+BI.shortcut("demo.buttons", Demo.Buttons);
\ No newline at end of file
diff --git a/demo/js/widget/basewidget/demo.items.js b/demo/js/widget/basewidget/demo.items.js
new file mode 100644
index 000000000..24ccea431
--- /dev/null
+++ b/demo/js/widget/basewidget/demo.items.js
@@ -0,0 +1,32 @@
+/**
+ * Created by Dailer on 2017/7/25.
+ */
+
+Demo.Items = BI.inherit(BI.Widget, {
+
+ render: function () {
+
+ return {
+ type: "bi.vertical",
+ items: [{
+ type: "bi.label",
+ height: 30,
+ text: "单选item"
+ }, {
+ type: "bi.single_select_item",
+ text: "单选项"
+ }, {
+ type: "bi.label",
+ height: 30,
+ text: "复选item"
+ }, {
+ type: "bi.multi_select_item",
+ text: "复选项"
+ }],
+ hgap: 300
+ }
+ }
+});
+
+
+BI.shortcut("demo.items", Demo.Items);
\ No newline at end of file
diff --git a/demo/js/widget/basewidget/demo.mask.loading.js b/demo/js/widget/basewidget/demo.mask.loading.js
new file mode 100644
index 000000000..9b04e7765
--- /dev/null
+++ b/demo/js/widget/basewidget/demo.mask.loading.js
@@ -0,0 +1,56 @@
+/**
+ * Created by Dailer on 2017/7/25.
+ */
+
+Demo.LoadingMask = BI.inherit(BI.Widget, {
+
+ render: function () {
+ var vessel = this;
+ var self = this;
+ var left = BI.createWidget({
+ type: "bi.center_adapt",
+ items: [{
+ type: "bi.button",
+ text: "LoadingMask",
+ height: 30,
+ handler: function () {
+ var mask = BI.createWidget({
+ type: "bi.loading_mask",
+ masker: vessel,
+ text: "加载中...3s后结束"
+ });
+ setTimeout(function () {
+ mask.destroy();
+ }, 3000);
+ }
+ }]
+ });
+ var right = BI.createWidget({
+ type: "bi.center_adapt",
+ items: [{
+ type: "bi.button",
+ text: "CancelLoadingMask",
+ height: 30,
+ handler: function () {
+ var mask = BI.createWidget({
+ type: "bi.loading_cancel_mask",
+ masker: vessel,
+ text: "正在加载数据"
+ });
+ mask.on(BI.LoadingCancelMask.EVENT_VALUE_CANCEL, function () {
+ mask.destroy();
+ BI.Msg.toast("取消加载了...");
+ });
+ }
+ }]
+ });
+ BI.createWidget({
+ type: "bi.center_adapt",
+ element: vessel,
+ items: [left, right],
+ hgap: 20
+ })
+ }
+});
+
+BI.shortcut("demo.loading_mask", Demo.LoadingMask);
\ No newline at end of file
diff --git a/demo/js/widget/basewidget/demo.nodes.js b/demo/js/widget/basewidget/demo.nodes.js
new file mode 100644
index 000000000..9d3a6bdd3
--- /dev/null
+++ b/demo/js/widget/basewidget/demo.nodes.js
@@ -0,0 +1,36 @@
+/**
+ * Created by Dailer on 2017/7/25.
+ */
+
+Demo.Nodes = BI.inherit(BI.Widget, {
+
+ render: function (vessel) {
+ return {
+ type: "bi.vertical",
+ items: [{
+ type: "bi.label",
+ height: 30,
+ text: "十字形的节点"
+ }, {
+ type: "bi.plus_group_node",
+ text: "十字形的节点"
+ }, {
+ type: "bi.label",
+ height: 30,
+ text: "三角形的节点"
+ }, {
+ type: "bi.triangle_group_node",
+ text: "三角形的节点"
+ }, {
+ type: "bi.label",
+ height: 30,
+ text: "箭头节点"
+ }, {
+ type: "bi.arrow_group_node",
+ text: "箭头节点"
+ }]
+ }
+ }
+});
+
+BI.shortcut("demo.nodes", Demo.Nodes);
\ No newline at end of file
diff --git a/demo/js/widget/basewidget/demo.sagments.js b/demo/js/widget/basewidget/demo.sagments.js
new file mode 100644
index 000000000..cab0c30de
--- /dev/null
+++ b/demo/js/widget/basewidget/demo.sagments.js
@@ -0,0 +1,35 @@
+/**
+ * Created by Dailer on 2017/7/25.
+ */
+
+Demo.Segments = BI.inherit(BI.Widget, {
+
+ render: function () {
+ return {
+ type: "bi.vertical",
+ items: [{
+ type: "bi.label",
+ height: 30,
+ text: "默认风格"
+ }, {
+ type: "bi.segment",
+ items: [{
+ text: "tab1",
+ value: 1,
+ selected: true
+ }, {
+ text: "tab2",
+ value: 2
+ }, {
+ text: "tab3 disabled",
+ disabled: true,
+ value: 3
+ }]
+ }],
+ hgap: 50,
+ vgap: 20
+ }
+ }
+});
+
+BI.shortcut("demo.segments", Demo.Segments);
\ No newline at end of file
diff --git a/demo/js/widget/basewidget/demo.tips.js b/demo/js/widget/basewidget/demo.tips.js
new file mode 100644
index 000000000..a81ff883f
--- /dev/null
+++ b/demo/js/widget/basewidget/demo.tips.js
@@ -0,0 +1,146 @@
+/**
+ * Created by Dailer on 2017/7/25.
+ */
+
+Demo.Tips = BI.inherit(BI.Widget, {
+ props: {
+ baseCls: "demo-tips"
+ },
+ render: function () {
+ var btns = [];
+ var bubble = BI.createWidget({
+ type: "bi.left",
+ items: [{
+ el: {
+ type: 'bi.button',
+ text: 'bubble测试',
+ height: 30,
+ handler: function () {
+ BI.Bubbles.show("singleBubble1", "bubble测试", this);
+ btns.push("singleBubble1");
+ }
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: 'bubble测试(居中显示)',
+ height: 30,
+ handler: function () {
+ BI.Bubbles.show("singleBubble2", "bubble测试", this, {
+ offsetStyle: "center"
+ });
+ btns.push("singleBubble2");
+ }
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: 'bubble测试(右边显示)',
+ height: 30,
+ handler: function () {
+ BI.Bubbles.show("singleBubble3", "bubble测试", this, {
+ offsetStyle: "right"
+ });
+ btns.push("singleBubble3");
+ }
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '隐藏所有 bubble',
+ height: 30,
+ cls: "layout-bg2",
+ handler: function () {
+ BI.each(btns, function (index, value) {
+ BI.Bubbles.hide(value);
+ })
+ }
+ }
+ }],
+ hgap: 20
+ });
+
+ var title = BI.createWidget({
+ type: "bi.vertical",
+ items: [{
+ type: "bi.label",
+ cls: "layout-bg1",
+ height: 50,
+ title: "title提示",
+ text: "移上去有title提示",
+ textAlign: "center"
+ }, {
+ type: "bi.label",
+ cls: "layout-bg6",
+ height: 50,
+ disabled: true,
+ warningTitle: "title错误提示",
+ text: "移上去有title错误提示",
+ textAlign: "center"
+ }, {
+ type: "bi.label",
+ cls: "layout-bg2",
+ height: 50,
+ disabled: true,
+ tipType: "success",
+ title: "自定义title提示效果",
+ warningTitle: "自定义title提示效果",
+ text: "自定义title提示效果",
+ textAlign: "center"
+ }],
+ hgap: 20,
+ vgap: 20
+ });
+
+ var toast = BI.createWidget({
+ type: "bi.vertical",
+ items: [{
+ el: {
+ type: 'bi.button',
+ text: '简单Toast测试',
+ height: 30,
+ handler: function () {
+ BI.Msg.toast("这是一条简单的数据");
+ }
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '很长的Toast测试',
+ height: 30,
+ handler: function () {
+ BI.Msg.toast("这是一条很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长的数据")
+ }
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '非常长的Toast测试',
+ height: 30,
+ handler: function () {
+ BI.Msg.toast("这是一条非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长的数据")
+ }
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '错误提示Toast测试',
+ level: "warning",
+ height: 30,
+ handler: function () {
+ BI.Msg.toast("错误提示Toast测试", "warning");
+ }
+ }
+ }],
+ vgap: 20
+ });
+
+ return {
+ type: "bi.horizontal_auto",
+ vgap: 20,
+ hgap: 20,
+ items: [bubble, title, toast]
+ }
+ }
+});
+BI.shortcut("demo.tips", Demo.Tips);
\ No newline at end of file
diff --git a/demo/js/widget/date/demo.date.js b/demo/js/widget/date/demo.date.js
index 8b5665ce6..72d2ea823 100644
--- a/demo/js/widget/date/demo.date.js
+++ b/demo/js/widget/date/demo.date.js
@@ -11,18 +11,34 @@ Demo.Date = BI.inherit(BI.Widget, {
},
render: function () {
-
+ var self = this;
return {
type: "bi.horizontal_auto",
vgap: 10,
items: [{
type: "bi.date_combo",
+ ref: function () {
+ self.datecombo = this;
+ },
width: 300
}, {
type: "bi.button",
text: "getVlaue",
- height: 50,
- width: 300
+ width: 300,
+ handler: function () {
+ BI.Msg.alert("date", JSON.stringify(self.datecombo.getValue()));
+ }
+ }, {
+ type: "bi.button",
+ text: "setVlaue '2017-12-31'",
+ width: 300,
+ handler: function () {
+ self.datecombo.setValue({
+ year: 2017,
+ month: 11,
+ day: 31
+ })
+ }
}]
}
}
diff --git a/demo/js/widget/date/demo.datepane.js b/demo/js/widget/date/demo.datepane.js
index c3ba442fd..f95b6c107 100644
--- a/demo/js/widget/date/demo.datepane.js
+++ b/demo/js/widget/date/demo.datepane.js
@@ -3,7 +3,7 @@ Demo.DatePane = BI.inherit(BI.Widget, {
baseCls: "demo-datepane"
},
render: function () {
-
+ var self = this;
return {
type: "bi.horizontal_auto",
items: [{
@@ -20,13 +20,26 @@ Demo.DatePane = BI.inherit(BI.Widget, {
month: 12,
day: 11
},
- height:300
+ ref: function (_ref) {
+ self.datepane = _ref;
+ },
+ height: 300
},
{
type: "bi.button",
text: "getValue",
handler: function () {
- BI.Msg.toast("date" + JSON.stringify(datepane.getValue()));
+ BI.Msg.toast("date" + JSON.stringify(self.datepane.getValue()));
+ }
+ }, {
+ type: "bi.button",
+ text: "setVlaue '2017-12-31'",
+ handler: function () {
+ self.datepane.setValue({
+ year: 2017,
+ month: 11,
+ day: 31
+ })
}
}
],
diff --git a/demo/js/widget/editor/demo.record_editor.js b/demo/js/widget/editor/demo.record_editor.js
deleted file mode 100644
index bb7de6923..000000000
--- a/demo/js/widget/editor/demo.record_editor.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * Created by Dailer on 2017/7/11.
- */
-Demo.RecordEditor = BI.inherit(BI.Widget, {
- props: {
- baseCls: ""
- },
- render: function () {
- return {
- type: "bi.horizontal_auto",
- items: [{
- type: "bi.record_editor",
- cls: "bi-border",
- width: 300,
- watermark: "这个是可以记录输入的"
- }],
- vgap: 20
- }
- }
-})
-
-BI.shortcut("demo.record_editor", Demo.RecordEditor);
\ No newline at end of file
diff --git a/demo/js/widget/editor/demo.sign_style_editor.js b/demo/js/widget/editor/demo.sign_style_editor.js
deleted file mode 100644
index 81f66c0e2..000000000
--- a/demo/js/widget/editor/demo.sign_style_editor.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * Created by Dailer on 2017/7/11.
- */
-Demo.SignStyleEditor = BI.inherit(BI.Widget, {
- props: {
- baseCls: "demo-exceltable"
- },
- render: function () {
- return {
- type: "bi.horizontal_adapt",
- items: [{
- type: "bi.sign_style_editor",
- cls:"layout-bg5",
- value:"12313",
- width: 300
- }],
- vgap:20
- }
- }
-})
-
-BI.shortcut("demo.sign_style_editor", Demo.SignStyleEditor);
\ No newline at end of file
diff --git a/demo/js/widget/filemanager/demo.file.manager.js b/demo/js/widget/filemanager/demo.file.manager.js
new file mode 100644
index 000000000..7b45abf59
--- /dev/null
+++ b/demo/js/widget/filemanager/demo.file.manager.js
@@ -0,0 +1,68 @@
+/* 文件管理导航
+ Created by dailer on 2017 / 7 / 21.
+ */
+Demo.FileManager = BI.inherit(BI.Widget, {
+ props: {
+ baseCls: ""
+ },
+
+ render: function () {
+ var items = [{
+ id: "1",
+ value: "1",
+ text: "根目录",
+ lastModify: 1454316355142
+ }, {
+ id: "11",
+ pId: "1",
+ value: "11",
+ text: "第一级子目录1",
+ lastModify: 1454316355142
+ }, {
+ id: "12",
+ pId: "1",
+ value: "12",
+ text: "第一级子目录2",
+ lastModify: 1454316355142
+ }, {
+ id: "111",
+ pId: "11",
+ value: "111",
+ text: "第二级子目录",
+ lastModify: 1454316355142
+ }, {
+ id: "121",
+ pId: "111",
+ buildUrl: "www.baidu.com",
+ value: "121",
+ text: "文件1",
+ lastModify: 1454316355142
+ }, {
+ id: "122",
+ pId: "111",
+ buildUrl: "www.baidu.com",
+ value: "122",
+ text: "文件2",
+ lastModify: 1454316355142
+ }];
+ var filemanager = BI.createWidget({
+ type: "bi.file_manager",
+ items: items
+ });
+ return {
+ type: "bi.vtape",
+ items: [{
+ el: filemanager,
+ height: "fill"
+ }, {
+ type: "bi.button",
+ text: "getValue",
+ handler: function () {
+ BI.Msg.alert("", JSON.stringify(filemanager.getValue()));
+ },
+ height: 25
+ }]
+ }
+ }
+});
+BI.shortcut("demo.file_manager", Demo.FileManager);
\ No newline at end of file
diff --git a/demo/js/widget/month/demo.month.js b/demo/js/widget/month/demo.month.js
index c40ccdad9..7dd060d2f 100644
--- a/demo/js/widget/month/demo.month.js
+++ b/demo/js/widget/month/demo.month.js
@@ -6,13 +6,35 @@ Demo.Month = BI.inherit(BI.Widget, {
baseCls: "demo-exceltable"
},
render: function () {
+ var self = this;
return {
- type: "bi.horizontal_adapt",
+ type: "bi.horizontal_auto",
items: [{
type: "bi.month_combo",
+ width: 300,
+ ref: function () {
+ self.monthcombo = this;
+ }
+ }, {
+ type: "bi.button",
+ text: "getValue",
+ handler: function () {
+ BI.Msg.toast(JSON.stringify(self.monthcombo.getValue()));
+ },
width: 300
- }]
-
+ }, {
+ type: "bi.button",
+ text: "setValue : 11",
+ handler: function () {
+ self.monthcombo.setValue(11);
+ },
+ width: 300
+ }, {
+ type: "bi.label",
+ text: "月份value 范围为0-11,显示范围为1-12",
+ width: 300
+ }],
+ vgap: 10
}
}
})
diff --git a/demo/js/widget/quarter/demo.quarter.js b/demo/js/widget/quarter/demo.quarter.js
index bad058e63..0cadac2fb 100644
--- a/demo/js/widget/quarter/demo.quarter.js
+++ b/demo/js/widget/quarter/demo.quarter.js
@@ -6,13 +6,31 @@ Demo.Quarter = BI.inherit(BI.Widget, {
baseCls: "demo-exceltable"
},
render: function () {
+ var self = this;
return {
- type: "bi.horizontal_adapt",
+ type: "bi.horizontal_auto",
items: [{
type: "bi.quarter_combo",
+ width: 300,
+ ref: function () {
+ self.quartercombo = this;
+ }
+ }, {
+ type: "bi.button",
+ text: "getValue",
+ handler: function () {
+ BI.Msg.toast(JSON.stringify(self.quartercombo.getValue()));
+ },
width: 300
- }]
-
+ }, {
+ type: "bi.button",
+ text: "setValue : 3",
+ handler: function () {
+ self.quartercombo.setValue(3);
+ },
+ width: 300
+ }],
+ vgap: 10
}
}
})
diff --git a/demo/js/widget/selecttree/demo.multilayer_select_tree_combo.js b/demo/js/widget/selecttree/demo.multilayer_select_tree_combo.js
index a50862225..50f6a88a0 100644
--- a/demo/js/widget/selecttree/demo.multilayer_select_tree_combo.js
+++ b/demo/js/widget/selecttree/demo.multilayer_select_tree_combo.js
@@ -26,6 +26,13 @@ Demo.MultiLayerSelectTreeCombo = BI.inherit(BI.Widget, {
BI.Msg.toast(self.tree.getValue()[0]);
},
width: 300
+ }, {
+ type: "bi.button",
+ text: "setVlaue (第二级文件1)",
+ handler: function () {
+ self.tree.setValue(["第二级文件1"]);
+ },
+ width: 300
}],
vgap: 20
}
diff --git a/demo/js/widget/selecttree/demo.select_tree_combo.js b/demo/js/widget/selecttree/demo.select_tree_combo.js
index 5eeac55a3..2f45d492a 100644
--- a/demo/js/widget/selecttree/demo.select_tree_combo.js
+++ b/demo/js/widget/selecttree/demo.select_tree_combo.js
@@ -8,154 +8,7 @@ Demo.SelectTreeCombo = BI.inherit(BI.Widget, {
render: function () {
var self = this;
- var items = [{
- id: 1,
- text: "第一项",
- value: 1,
- isParent: true,
- title: "第一项"
- }, {
- id: 2,
- text: "第二项",
- value: 2,
- isParent: true,
- title: "第二项"
- }, {
- id: 3,
- text: "第三项",
- value: 3,
- isParent: true,
- open: true,
- title: "第三项"
- }, {
- id: 4,
- text: "第四项",
- value: 4,
- isParent: true,
- title: "第四项"
- }, {
- id: 5,
- text: "第五项",
- value: 5,
- isParent: true,
- title: "第五项"
- }, {
- id: 6,
- text: "第六项",
- value: 6,
- isParent: true,
- open: true,
- title: "第六项"
- }, {
- id: 7,
- text: "第七项",
- value: 7,
- isParent: true,
- open: true,
- title: "第七项"
- }, {
- id: 11,
- pId: 1,
- text: "子项1",
- value: 11,
- title: "子项1"
- }, {
- id: 12,
- pId: 1,
- text: "子项2",
- value: 12,
- title: "子项2"
- }, {
- id: 13,
- pId: 1,
- text: "子项3",
- value: 13,
- title: "子项3"
- }, {
- id: 21,
- pId: 2,
- text: "子项1",
- value: 21,
- title: "子项1"
- }, {
- id: 22,
- pId: 2,
- text: "子项2",
- value: 22,
- title: "子项2"
- }, {
- id: 31,
- pId: 3,
- text: "子项1",
- value: 31,
- title: "子项1"
- }, {
- id: 32,
- pId: 3,
- text: "子项2",
- value: 32,
- title: "子项2"
- }, {
- id: 33,
- pId: 3,
- text: "子项3",
- value: 33,
- title: "子项3"
- }, {
- id: 41,
- pId: 4,
- text: "子项1",
- value: 41,
- title: "子项1"
- }, {
- id: 42,
- pId: 4,
- text: "子项2",
- value: 42,
- title: "子项2"
- }, {
- id: 43,
- pId: 4,
- text: "子项3",
- value: 43,
- title: "子项3"
- }, {
- id: 51,
- pId: 5,
- text: "子项1",
- value: 51,
- title: "子项1"
- }, {
- id: 52,
- pId: 5,
- text: "子项2",
- value: 52,
- title: "子项2"
- }, {
- id: 61,
- pId: 6,
- text: "子项1",
- value: 61,
- title: "子项1"
- }, {
- id: 62,
- pId: 6,
- text: "子项2",
- value: 62,
- title: "子项2"
- }, {
- id: 71,
- pId: 7,
- text: "子项1",
- value: 71,
- title: "子项1"
- }, {
- id: 72,
- pId: 7,
- text: "子项2",
- value: 72,
- title: "子项2"
- }];
+ var items = BI.deepClone(Demo.CONSTANTS.TREE);
return {
type: "bi.horizontal_auto",
items: [{
@@ -173,6 +26,13 @@ Demo.SelectTreeCombo = BI.inherit(BI.Widget, {
BI.Msg.toast(self.tree.getValue()[0]);
},
width: 300
+ }, {
+ type: "bi.button",
+ text: "setVlaue (第二级文件1)",
+ handler: function () {
+ self.tree.setValue(["第二级文件1"]);
+ },
+ width: 300
}],
vgap: 20
}
diff --git a/demo/js/widget/singletree/demo.multilayer_single_tree_combo.js b/demo/js/widget/singletree/demo.multilayer_single_tree_combo.js
index 42f06052b..c18aa3598 100644
--- a/demo/js/widget/singletree/demo.multilayer_single_tree_combo.js
+++ b/demo/js/widget/singletree/demo.multilayer_single_tree_combo.js
@@ -26,6 +26,13 @@ Demo.MultiLayerSingleTreeCombo = BI.inherit(BI.Widget, {
BI.Msg.toast(self.tree.getValue()[0]);
},
width: 300
+ }, {
+ type: "bi.button",
+ text: "setVlaue (第二级文件1)",
+ handler: function () {
+ self.tree.setValue(["第二级文件1"]);
+ },
+ width: 300
}],
vgap: 20
}
diff --git a/demo/js/widget/singletree/demo.single_tree_combo.js b/demo/js/widget/singletree/demo.single_tree_combo.js
index 208dec66d..b683b64ee 100644
--- a/demo/js/widget/singletree/demo.single_tree_combo.js
+++ b/demo/js/widget/singletree/demo.single_tree_combo.js
@@ -8,6 +8,7 @@ Demo.SingleTreeCombo = BI.inherit(BI.Widget, {
render: function () {
var self = this;
+ var items = BI.deepClone(Demo.CONSTANTS.TREE);
return {
type: "bi.horizontal_auto",
items: [{
@@ -16,154 +17,7 @@ Demo.SingleTreeCombo = BI.inherit(BI.Widget, {
self.tree = _ref;
},
text: "默认值",
- items: [{
- id: 1,
- text: "第一项",
- value: 1,
- isParent: true,
- title: "第一项"
- }, {
- id: 2,
- text: "第二项",
- value: 1,
- isParent: true,
- title: "第二项"
- }, {
- id: 3,
- text: "第三项",
- value: 1,
- isParent: true,
- open: true,
- title: "第三项"
- }, {
- id: 4,
- text: "第四项",
- value: 1,
- isParent: true,
- title: "第四项"
- }, {
- id: 5,
- text: "第五项",
- value: 1,
- isParent: true,
- title: "第五项"
- }, {
- id: 6,
- text: "第六项",
- value: 1,
- isParent: true,
- open: true,
- title: "第六项"
- }, {
- id: 7,
- text: "第七项",
- value: 1,
- isParent: true,
- open: true,
- title: "第七项"
- }, {
- id: 11,
- pId: 1,
- text: "子项1",
- value: 11,
- title: "子项1"
- }, {
- id: 12,
- pId: 1,
- text: "子项2",
- value: 12,
- title: "子项2"
- }, {
- id: 13,
- pId: 1,
- text: "子项3",
- value: 13,
- title: "子项3"
- }, {
- id: 21,
- pId: 2,
- text: "子项1",
- value: 21,
- title: "子项1"
- }, {
- id: 22,
- pId: 2,
- text: "子项2",
- value: 22,
- title: "子项2"
- }, {
- id: 31,
- pId: 3,
- text: "子项1",
- value: 31,
- title: "子项1"
- }, {
- id: 32,
- pId: 3,
- text: "子项2",
- value: 32,
- title: "子项2"
- }, {
- id: 33,
- pId: 3,
- text: "子项3",
- value: 33,
- title: "子项3"
- }, {
- id: 41,
- pId: 4,
- text: "子项1",
- value: 41,
- title: "子项1"
- }, {
- id: 42,
- pId: 4,
- text: "子项2",
- value: 42,
- title: "子项2"
- }, {
- id: 43,
- pId: 4,
- text: "子项3",
- value: 43,
- title: "子项3"
- }, {
- id: 51,
- pId: 5,
- text: "子项1",
- value: 51,
- title: "子项1"
- }, {
- id: 52,
- pId: 5,
- text: "子项2",
- value: 52,
- title: "子项2"
- }, {
- id: 61,
- pId: 6,
- text: "子项1",
- value: 61,
- title: "子项1"
- }, {
- id: 62,
- pId: 6,
- text: "子项2",
- value: 62,
- title: "子项2"
- }, {
- id: 71,
- pId: 7,
- text: "子项1",
- value: 71,
- title: "子项1"
- }, {
- id: 72,
- pId: 7,
- text: "子项2",
- value: 72,
- title: "子项2"
- }],
+ items: items,
width: 300
}, {
type: "bi.button",
@@ -172,6 +26,13 @@ Demo.SingleTreeCombo = BI.inherit(BI.Widget, {
BI.Msg.toast(self.tree.getValue()[0]);
},
width: 300
+ }, {
+ type: "bi.button",
+ text: "setVlaue (第二级文件1)",
+ handler: function () {
+ self.tree.setValue(["第二级文件1"]);
+ },
+ width: 300
}],
vgap: 20
}
diff --git a/demo/js/widget/tree/demo.switch_tree.js b/demo/js/widget/tree/demo.switch_tree.js
deleted file mode 100644
index 0e7a1788d..000000000
--- a/demo/js/widget/tree/demo.switch_tree.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Created by Dailer on 2017/7/13.
- */
-Demo.SwitchTree = BI.inherit(BI.Widget, {
- props: {
- baseCls: ""
- },
- render: function () {
-
- var items = BI.deepClone(Demo.CONSTANTS.TREE);
- return {
- type: "bi.horizontal_auto",
- items: [{
- type: "bi.switch_tree",
- items: items
- },{
- type:"bi.button",
- text:"getValue"
- }]
- }
- }
-})
-
-BI.shortcut("demo.switch_tree", Demo.SwitchTree);
\ No newline at end of file
diff --git a/demo/js/widget/tree/demo.switchtree.js b/demo/js/widget/tree/demo.switchtree.js
new file mode 100644
index 000000000..11ef12e91
--- /dev/null
+++ b/demo/js/widget/tree/demo.switchtree.js
@@ -0,0 +1,56 @@
+/**
+ * Created by Dailer on 2017/7/26.
+ */
+
+
+Demo.SwitchTree = BI.inherit(BI.Widget, {
+
+ render: function () {
+ var self = this;
+ var tree = BI.createWidget({
+ type: "bi.switch_tree",
+ items: BI.deepClone(Demo.CONSTANTS.TREE)
+ });
+
+ return {
+ type: "bi.vtape",
+ items: [{
+ el: tree
+ }, {
+ el: {
+ type: "bi.button",
+ height: 25,
+ text: "点击切换",
+ handler: function () {
+ tree.switchSelect();
+ }
+ },
+ height: 25
+ }, {
+ el: {
+ type: "bi.button",
+ height: 25,
+ text: "getValue",
+ handler: function () {
+ BI.Msg.alert("", JSON.stringify(tree.getValue()));
+ }
+ },
+ height: 25
+ }, {
+ el: {
+ type: "bi.button",
+ height: 25,
+ text: "setValue (第二级文件1)",
+ handler: function () {
+ tree.setValue(["第二级文件1"]);
+ }
+ },
+ height: 25
+ }],
+ width: 500,
+ hgap: 300
+ }
+ }
+});
+
+BI.shortcut("demo.switch_tree", Demo.SwitchTree);
\ No newline at end of file
diff --git a/demo/js/widget/year/demo.year.js b/demo/js/widget/year/demo.year.js
index 810b224b9..b67ec216f 100644
--- a/demo/js/widget/year/demo.year.js
+++ b/demo/js/widget/year/demo.year.js
@@ -6,12 +6,31 @@ Demo.Year = BI.inherit(BI.Widget, {
baseCls: "demo-exceltable"
},
render: function () {
+ var self = this;
return {
- type: "bi.horizontal_adapt",
+ type: "bi.horizontal_auto",
items: [{
type: "bi.year_combo",
+ width: 300,
+ ref: function () {
+ self.yearcombo = this;
+ }
+ }, {
+ type: "bi.button",
+ text: "getValue",
+ handler: function () {
+ BI.Msg.toast(JSON.stringify(self.yearcombo.getValue()));
+ },
width: 300
- }]
+ }, {
+ type: "bi.button",
+ text: "setValue : 2018",
+ handler: function () {
+ self.yearcombo.setValue(2018);
+ },
+ width: 300
+ }],
+ vgap: 10
}
}
})
diff --git a/demo/js/widget/yearmonth/demo.year_month_combo.js b/demo/js/widget/yearmonth/demo.year_month_combo.js
index 02ab8af65..2f864c74c 100644
--- a/demo/js/widget/yearmonth/demo.year_month_combo.js
+++ b/demo/js/widget/yearmonth/demo.year_month_combo.js
@@ -23,6 +23,16 @@ Demo.YearMonthCombo = BI.inherit(BI.Widget, {
BI.Msg.toast(JSON.stringify(self.widget.getValue()))
},
width: 300
+ }, {
+ type: "bi.button",
+ text: "setVlaue '2017-12'",
+ width: 300,
+ handler: function () {
+ self.widget.setValue({
+ year: 2017,
+ month: 11
+ })
+ }
}],
vgap: 20
}
diff --git a/demo/js/widget/yearquarter/demo.year_quarter_combo.js b/demo/js/widget/yearquarter/demo.year_quarter_combo.js
index ddd9cccf2..f57acce27 100644
--- a/demo/js/widget/yearquarter/demo.year_quarter_combo.js
+++ b/demo/js/widget/yearquarter/demo.year_quarter_combo.js
@@ -6,24 +6,34 @@ Demo.YearQuarterCombo = BI.inherit(BI.Widget, {
baseCls: ""
},
render: function () {
- var self=this;
+ var self = this;
return {
type: "bi.horizontal_auto",
items: [{
type: "bi.year_quarter_combo",
width: 300,
- ref:function(_ref){
- self.widget=_ref;
+ ref: function (_ref) {
+ self.widget = _ref;
},
yearBehaviors: {},
quarterBehaviors: {},
}, {
type: "bi.button",
text: "getValue",
- handler:function(){
+ handler: function () {
BI.Msg.toast(JSON.stringify(self.widget.getValue()))
},
width: 300
+ }, {
+ type: "bi.button",
+ text: "setVlaue '2017 季度3'",
+ width: 300,
+ handler: function () {
+ self.widget.setValue({
+ year: 2017,
+ quarter: 3
+ })
+ }
}],
vgap: 20
}
diff --git a/demo/less/main.less b/demo/less/main.less
index 132ee48f1..e209e803e 100644
--- a/demo/less/main.less
+++ b/demo/less/main.less
@@ -64,3 +64,34 @@ body {
.demo-editor {
border: 1px solid rgb(204, 204, 204);
}
+
+.demo-clolor {
+ color: #1a1a1a;
+}
+
+.bi-progress-bar-processor {
+ transition: all 0.5s ease;
+ -webkit-transition: all 0.5s ease;
+ -moz-transition: all 0.5s ease;
+ -o-transition: all 0.5s ease;
+ background: #3f8ce8;
+ -webkit-border-radius: 20px;
+ -moz-border-radius: 20px;
+ border-radius: 20px;
+ overflow: hidden;
+ overflow-x: hidden;
+ overflow-y: hidden;
+}
+
+.bi-progress-text-bar-processor {
+ transition: all 0.5s ease;
+ -webkit-transition: all 0.5s ease;
+ -moz-transition: all 0.5s ease;
+ -o-transition: all 0.5s ease;
+}
+
+.bi-progress-bar-bar {
+ -webkit-border-radius: 20px;
+ -moz-border-radius: 20px;
+ border-radius: 20px;
+}
\ No newline at end of file
diff --git a/docs/background/auto-color.png b/docs/background/auto-color.png
new file mode 100644
index 000000000..63b3edf95
Binary files /dev/null and b/docs/background/auto-color.png differ
diff --git a/docs/background/trans-color.png b/docs/background/trans-color.png
new file mode 100644
index 000000000..8fa44929c
Binary files /dev/null and b/docs/background/trans-color.png differ
diff --git a/docs/base.js b/docs/base.js
index e478a6fa4..7e2f494d7 100644
--- a/docs/base.js
+++ b/docs/base.js
@@ -14351,15 +14351,15 @@ BI.FormulaEditor = BI.inherit(BI.Single, {
_checkWaterMark: function () {
var o = this.options;
- if (!this.disabledWarterMark && BI.isEmptyString(this.editor.getValue()) && BI.isKey(o.watermark)) {
+ if (!this.disabledWaterMark && BI.isEmptyString(this.editor.getValue()) && BI.isKey(o.watermark)) {
this.watermark && this.watermark.visible();
} else {
this.watermark && this.watermark.invisible();
}
},
- disableWarterMark: function () {
- this.disabledWarterMark = true;
+ disableWaterMark: function () {
+ this.disabledWaterMark = true;
this._checkWaterMark();
},
@@ -18111,7 +18111,7 @@ BI.Editor = BI.inherit(BI.Single, {
_checkWaterMark: function () {
var o = this.options;
- if (!this.disabledWarterMark && this.editor.getValue() === "" && BI.isKey(o.watermark)) {
+ if (!this.disabledWaterMark && this.editor.getValue() === "" && BI.isKey(o.watermark)) {
this.watermark && this.watermark.visible();
} else {
this.watermark && this.watermark.invisible();
@@ -18149,13 +18149,13 @@ BI.Editor = BI.inherit(BI.Single, {
this._checkError();
},
- disableWarterMark: function () {
- this.disabledWarterMark = true;
+ disableWaterMark: function () {
+ this.disabledWaterMark = true;
this._checkWaterMark();
},
- enableWarterMark: function () {
- this.disabledWarterMark = false;
+ enableWaterMark: function () {
+ this.disabledWaterMark = false;
this._checkWaterMark();
},
@@ -18489,6 +18489,9 @@ BI.Icon = BI.inherit(BI.Single, {
},
_init: function () {
BI.Icon.superclass._init.apply(this, arguments);
+ if (BI.isIE9Below()) {
+ this.element.addClass("hack");
+ }
}
});
BI.shortcut("bi.icon", BI.Icon);/**
@@ -30100,6 +30103,41 @@ BI.GridTable = BI.inherit(BI.Widget, {
this.contextLayout.attr("items", items);
this.contextLayout.resize();
+ this.topLeftGrid.attr({
+ overscanColumnCount: 0,
+ overscanRowCount: 0
+ });
+ this.topRightGrid.attr({
+ overscanColumnCount: 0,
+ overscanRowCount: 0
+ });
+ this.bottomLeftGrid.attr({
+ overscanColumnCount: 0,
+ overscanRowCount: 0
+ });
+ this.bottomRightGrid.attr({
+ overscanColumnCount: 0,
+ overscanRowCount: 0
+ });
+
+ function overscan(grid, w, h, rSize, cSize) {
+ var rCount = h / rSize;
+ var cCount = w / cSize;
+ if (cCount * (120 / rSize) >= 60 || rCount * (120 / cSize) >= 60) {
+ grid.attr("overscanRowCount", 100);
+ grid.attr("overscanColumnCount", 100);
+ }
+ }
+
+ if (freezeColLength > 0) {
+ overscan(this.topLeftGrid, tlw, tlh, o.headerRowSize, totalLeftColumnSize / freezeColLength);
+ overscan(this.bottomLeftGrid, blw, blh, o.rowSize, totalLeftColumnSize / freezeColLength);
+ }
+ if (o.columnSize.length - freezeColLength > 0) {
+ overscan(this.topRight, trw, trh, o.headerRowSize, totalRightColumnSize / (o.columnSize.length - freezeColLength));
+ overscan(this.bottomRightGrid, brw, brh, o.rowSize, totalRightColumnSize / (o.columnSize.length - freezeColLength));
+ }
+
this.topLeftGrid._populate(this.header[0]);
this.topRightGrid._populate(this.header[1]);
this.bottomLeftGrid._populate(this.items[0]);
@@ -30326,7 +30364,8 @@ BI.QuickGridTable = BI.inherit(BI.GridTable, {
_populateTable: function () {
var self = this, o = this.options;
- var regionSize = this.getRegionSize(), totalLeftColumnSize = 0, totalRightColumnSize = 0, totalColumnSize = 0, summaryColumnSizeArray = [];
+ var regionSize = this.getRegionSize(), totalLeftColumnSize = 0, totalRightColumnSize = 0, totalColumnSize = 0,
+ summaryColumnSizeArray = [];
var freezeColLength = this._getFreezeColLength();
BI.each(o.columnSize, function (i, size) {
if (o.isNeedFreeze === true && o.freezeCols.contains(i)) {
@@ -30417,6 +30456,42 @@ BI.QuickGridTable = BI.inherit(BI.GridTable, {
}
});
});
+
+ this.topLeftGrid.attr({
+ overscanColumnCount: 0,
+ overscanRowCount: 0
+ });
+ this.topRightGrid.attr({
+ overscanColumnCount: 0,
+ overscanRowCount: 0
+ });
+ this.bottomLeftGrid.attr({
+ overscanColumnCount: 0,
+ overscanRowCount: 0
+ });
+ this.bottomRightGrid.attr({
+ overscanColumnCount: 0,
+ overscanRowCount: 0
+ });
+
+ function overscan(grid, w, h, rSize, cSize) {
+ var rCount = h / rSize;
+ var cCount = w / cSize;
+ if (cCount * (120 / rSize) >= 60 || rCount * (120 / cSize) >= 60) {
+ grid.attr("overscanRowCount", 100);
+ grid.attr("overscanColumnCount", 100);
+ }
+ }
+
+ if (freezeColLength > 0) {
+ overscan(this.topLeftGrid, otlw, otlh, o.headerRowSize, totalLeftColumnSize / freezeColLength);
+ overscan(this.bottomLeftGrid, oblw, oblh, o.rowSize, totalLeftColumnSize / freezeColLength);
+ }
+ if (o.columnSize.length - freezeColLength > 0) {
+ overscan(this.topRight, otrw, otrh, o.headerRowSize, totalRightColumnSize / (o.columnSize.length - freezeColLength));
+ overscan(this.bottomRightGrid, obrw, obrh, o.rowSize, totalRightColumnSize / (o.columnSize.length - freezeColLength));
+ }
+
this.topLeftGrid.populate(leftHeader);
this.topRightGrid.populate(rightHeader);
this.bottomLeftGrid.populate(leftItems);
@@ -31291,8 +31366,8 @@ BI.Table = BI.inherit(BI.Widget, {
var isNeedMergeCol = o.mergeRule(map[i][j], map[i][j - 1]);
if (isNeedMergeCol === true) {
mergeCol(i, j);
- preCol[j] = preRow[j - 1];
- preCW[j] = preRW[j - 1];
+ preCol[j] = preRow[i];
+ preCW[j] = preRW[i];
} else {
createOneEl(i, j);
}
diff --git a/docs/case.js b/docs/case.js
index 1f5a3faf1..136039b30 100644
--- a/docs/case.js
+++ b/docs/case.js
@@ -6903,9 +6903,7 @@ BI.ShelterEditor.EVENT_SPACE = "EVENT_SPACE";
BI.ShelterEditor.EVENT_EMPTY = "EVENT_EMPTY";
BI.shortcut("bi.shelter_editor", BI.ShelterEditor);/**
- * sign是新值(初始value值)形式的自适应宽度的输入框
- * @class BI.SignInitialEditor
- * @extends BI.Single
+ * Created by User on 2017/7/28.
*/
BI.SignInitialEditor = BI.inherit(BI.Widget, {
_defaultConfig: function () {
@@ -6934,8 +6932,7 @@ BI.SignInitialEditor = BI.inherit(BI.Widget, {
BI.SignInitialEditor.superclass._init.apply(this, arguments);
var self = this, o = this.options;
this.editor = BI.createWidget({
- type: "bi.sign_editor",
- element: this,
+ type: "bi.editor",
height: o.height,
hgap: o.hgap,
vgap: o.vgap,
@@ -6943,7 +6940,7 @@ BI.SignInitialEditor = BI.inherit(BI.Widget, {
rgap: o.rgap,
tgap: o.tgap,
bgap: o.bgap,
- value: o.value || o.text,
+ value: o.value,
validationChecker: o.validationChecker,
quitChecker: o.quitChecker,
mouseOut: o.mouseOut,
@@ -6951,67 +6948,163 @@ BI.SignInitialEditor = BI.inherit(BI.Widget, {
watermark: o.watermark,
errorText: o.errorText
});
- if(BI.isNotNull(o.value)){
- this.setState(o.value);
- }
+ this.text = BI.createWidget({
+ type: "bi.text_button",
+ cls: "sign-editor-text",
+ title: o.title,
+ warningTitle: o.warningTitle,
+ tipType: o.tipType,
+ textAlign: "left",
+ height: o.height,
+ hgap: 4,
+ handler: function () {
+ self._showInput();
+ self.editor.focus();
+ self.editor.selectAll();
+ }
+ });
+ this.text.on(BI.TextButton.EVENT_CHANGE, function () {
+ BI.nextTick(function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_CLICK_LABEL)
+ });
+ });
+ BI.createWidget({
+ type: "bi.absolute",
+ element: this,
+ items: [{
+ el: this.text,
+ left: 0,
+ right: 0,
+ top: 0,
+ bottom: 0
+ }]
+ });
this.editor.on(BI.Controller.EVENT_CHANGE, function () {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_FOCUS, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_FOCUS);
+ this.editor.on(BI.Editor.EVENT_FOCUS, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_FOCUS, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_BLUR, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_BLUR);
+ this.editor.on(BI.Editor.EVENT_BLUR, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_BLUR, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_CLICK, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_CLICK);
+ this.editor.on(BI.Editor.EVENT_CLICK, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_CLICK, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_CHANGE, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_CHANGE);
+ this.editor.on(BI.Editor.EVENT_CHANGE, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_CHANGE, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_KEY_DOWN, function (v) {
- self.fireEvent(BI.SignInitialEditor.EVENT_KEY_DOWN);
+ this.editor.on(BI.Editor.EVENT_KEY_DOWN, function (v) {
+ self.fireEvent(BI.SignInitialEditor.EVENT_KEY_DOWN, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_VALID, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_VALID);
+ this.editor.on(BI.Editor.EVENT_VALID, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_VALID, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_CONFIRM, function () {
- self.setState(self.editor.getValue());
- self.fireEvent(BI.SignInitialEditor.EVENT_CONFIRM);
+ this.editor.on(BI.Editor.EVENT_CONFIRM, function () {
+ self._showHint();
+ self._checkText();
+ self.fireEvent(BI.SignInitialEditor.EVENT_CONFIRM, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_START, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_START);
+ this.editor.on(BI.Editor.EVENT_START, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_START, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_PAUSE, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_PAUSE);
+ this.editor.on(BI.Editor.EVENT_PAUSE, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_PAUSE, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_STOP, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_STOP);
+ this.editor.on(BI.Editor.EVENT_STOP, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_STOP, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_SPACE, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_SPACE);
+ this.editor.on(BI.Editor.EVENT_SPACE, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_SPACE, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_ERROR, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_ERROR);
+ this.editor.on(BI.Editor.EVENT_ERROR, function () {
+ self._checkText();
+ self.fireEvent(BI.SignInitialEditor.EVENT_ERROR, arguments);
+ });
+ this.editor.on(BI.Editor.EVENT_ENTER, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_ENTER, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_ENTER, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_ENTER);
+ this.editor.on(BI.Editor.EVENT_RESTRICT, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_RESTRICT, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_RESTRICT, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_RESTRICT);
+ this.editor.on(BI.Editor.EVENT_EMPTY, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_EMPTY, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_EMPTY, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_EMPTY);
+ BI.createWidget({
+ type: "bi.vertical",
+ scrolly: false,
+ element: this,
+ items: [this.editor]
});
+ this._showHint();
+ self._checkText();
+ },
+
+ _checkText: function () {
+ var o = this.options;
+ BI.nextTick(BI.bind(function () {
+ if (this.editor.getValue() === "") {
+ this.text.setValue(o.watermark || "");
+ this.text.element.addClass("bi-water-mark");
+ } else {
+ var v = this.editor.getValue();
+ v = (BI.isEmpty(v) || v == o.text) ? o.text : v + "(" + o.text + ")";
+ this.text.setValue(v);
+ this.text.element.removeClass("bi-water-mark");
+ }
+ }, this));
+ },
+
+ _showInput: function () {
+ this.editor.visible();
+ this.text.invisible();
+ },
+
+ _showHint: function () {
+ this.editor.invisible();
+ this.text.visible();
+ },
+
+ setTitle: function (title) {
+ this.text.setTitle(title);
+ },
+
+ setWarningTitle: function (title) {
+ this.text.setWarningTitle(title);
},
focus: function () {
+ this._showInput();
this.editor.focus();
},
blur: function () {
this.editor.blur();
+ this._showHint();
+ this._checkText();
+ },
+
+ doRedMark: function () {
+ if (this.editor.getValue() === "" && BI.isKey(this.options.watermark)) {
+ return;
+ }
+ this.text.doRedMark.apply(this.text, arguments);
+ },
+
+ unRedMark: function () {
+ this.text.unRedMark.apply(this.text, arguments);
+ },
+
+ doHighLight: function () {
+ if (this.editor.getValue() === "" && BI.isKey(this.options.watermark)) {
+ return;
+ }
+ this.text.doHighLight.apply(this.text, arguments);
+ },
+
+ unHighLight: function () {
+ this.text.unHighLight.apply(this.text, arguments);
},
isValid: function () {
@@ -7026,9 +7119,19 @@ BI.SignInitialEditor = BI.inherit(BI.Widget, {
return this.editor.getErrorText();
},
+ isEditing: function () {
+ return this.editor.isEditing();
+ },
+
+ getLastValidValue: function () {
+ return this.editor.getLastValidValue();
+ },
+
setValue: function (v) {
+ var o = this.options;
this.editor.setValue(v.value);
- this.setState(v.value);
+ o.text = v.text || o.text;
+ this._checkText();
},
getValue: function () {
@@ -7039,13 +7142,14 @@ BI.SignInitialEditor = BI.inherit(BI.Widget, {
},
getState: function () {
- return this.editor.getState();
+ return this.text.getValue();
},
setState: function (v) {
var o = this.options;
+ this._showHint();
v = (BI.isEmpty(v) || v == o.text) ? o.text : v + "(" + o.text + ")";
- this.editor.setState(v);
+ this.text.setValue(v);
}
});
BI.SignInitialEditor.EVENT_CHANGE = "EVENT_CHANGE";
@@ -8687,6 +8791,11 @@ BI.SelectList = BI.inherit(BI.Widget, {
this._checkAllSelected();
},
+ _setEnable: function (enable) {
+ BI.SelectList.superclass._setEnable.apply(this, arguments);
+ this.toolbar.setEnable(enable);
+ },
+
resetHeight: function (h) {
var toolHeight = ( this.toolbar.element.outerHeight() || 25) * ( this.toolbar.isVisible() ? 1 : 0);
this.list.resetHeight ? this.list.resetHeight(h - toolHeight) :
diff --git a/docs/chart.js b/docs/chart.js
index ad0ce9696..b095fe2bb 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.js b/docs/core.js
index 398c89578..6fe5dd752 100644
--- a/docs/core.js
+++ b/docs/core.js
@@ -1,28693 +1,28708 @@
-/*!
- * 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;
- }
+/*!
+ * 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());
+ },
+
+ getIEVersion: function () {
+ 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;
+ },
+
+ isIE9Below: function () {
+ if (!BI.isIE()) {
+ return false;
+ }
+ return this.getIEVersion() < 9;
+ },
+
+ isIE9: function () {
+ return this.getIEVersion() === 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) {
+ var self = this;
+ if (BI.isPlainObject(key)) {
+ BI.each(key, function (k, v) {
+ self.attr(k, v);
+ })
+ return;
+ }
+ 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;
+ }
});
\ No newline at end of file
diff --git a/docs/core.js.orig b/docs/core.js.orig
new file mode 100644
index 000000000..1658c3c94
--- /dev/null
+++ b/docs/core.js.orig
@@ -0,0 +1,57374 @@
+<<<<<<< HEAD
+/*!
+ * 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);
+ 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)) {
+ 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 width = this.left.element.outerWidth(),
+ height = this.left.element.outerHeight();
+ this.left.element.width(width).height(height).css("float", "none");
+ BI.createWidget({
+ type: "bi.center_adapt",
+ element: this,
+ items: [this.left]
+ });
+ this.removeWidget(this.container);
+ },
+
+ 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 width = this.left.element.width(),
+ height = this.left.element.height();
+ this.left.element.width(width).height(height).css("float", "none");
+ BI.createWidget({
+ type: "bi.horizontal_auto",
+ element: this,
+ items: [this.left]
+ });
+ this.removeWidget(this.container);
+ },
+
+ _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;
+ }
+=======
+/*!
+ * 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/docs/demo.css b/docs/demo.css
index 71b16e78d..51204de07 100644
--- a/docs/demo.css
+++ b/docs/demo.css
@@ -51,6 +51,33 @@ body {
.demo-editor {
border: 1px solid #cccccc;
}
+.demo-clolor {
+ color: #1a1a1a;
+}
+.bi-progress-bar-processor {
+ transition: all 0.5s ease;
+ -webkit-transition: all 0.5s ease;
+ -moz-transition: all 0.5s ease;
+ -o-transition: all 0.5s ease;
+ background: #3f8ce8;
+ -webkit-border-radius: 20px;
+ -moz-border-radius: 20px;
+ border-radius: 20px;
+ overflow: hidden;
+ overflow-x: hidden;
+ overflow-y: hidden;
+}
+.bi-progress-text-bar-processor {
+ transition: all 0.5s ease;
+ -webkit-transition: all 0.5s ease;
+ -moz-transition: all 0.5s ease;
+ -o-transition: all 0.5s ease;
+}
+.bi-progress-bar-bar {
+ -webkit-border-radius: 20px;
+ -moz-border-radius: 20px;
+ border-radius: 20px;
+}
.demo-north {
background-color: #3c8dbc;
}
diff --git a/docs/demo.js b/docs/demo.js
index 9232a05dc..d43000bf5 100644
--- a/docs/demo.js
+++ b/docs/demo.js
@@ -1838,7 +1838,124 @@ BI.shortcut("demo.color_chooser", Demo.Func);Demo.Func = BI.inherit(BI.Widget, {
})
}
});
-BI.shortcut("demo.complex_canvas", Demo.Func);Demo.Func = BI.inherit(BI.Widget, {
+BI.shortcut("demo.complex_canvas", Demo.Func);/**
+ * Created by Dailer on 2017/7/11.
+ */
+Demo.ClearEditor = BI.inherit(BI.Widget, {
+ props: {
+ baseCls: ""
+ },
+ render: function () {
+ var editor;
+ return {
+ type: "bi.horizontal_auto",
+ items: [{
+ type: "bi.shelter_editor",
+ cls: "bi-border",
+ ref:function(_ref){
+ editor=_ref;
+ },
+ width: 300,
+ watermark: "这个是带标记的"
+ },{
+ type:"bi.button",
+ text:"setValue",
+ width:300,
+ handler:function(){
+ editor.setValue("凛冬将至");
+ }
+ },{
+ type:"bi.button",
+ text:"doHighLight",
+ width:300,
+ handler:function(){
+ editor.doHighLight();
+ console.log(editor.getState());
+ }
+ }],
+ vgap: 20
+ }
+ }
+})
+
+BI.shortcut("demo.shelter_editor", Demo.ClearEditor);/**
+ * Created by Dailer on 2017/7/14.
+ */
+Demo.SignEditor = BI.inherit(BI.Widget, {
+ props: {
+ baseCls: ""
+ },
+ render: function () {
+ return {
+ type: "bi.horizontal_adapt",
+ items: [{
+ type: "bi.sign_editor",
+ // cls:"layout-bg5",
+ value: "123",
+ text: "456",
+ width: 300
+ }],
+ vgap: 20
+
+ }
+ }
+})
+
+BI.shortcut("demo.sign_editor", Demo.SignEditor);/**
+ * Created by Dailer on 2017/7/11.
+ */
+Demo.SignInitialEditor = BI.inherit(BI.Widget, {
+ props: {
+ baseCls: ""
+ },
+ mounted: function () {
+ this.editor.setValue({
+ value: "123",
+ text: "sdga"
+ })
+ },
+ render: function () {
+ var self = this;
+ return {
+ type: "bi.horizontal_adapt",
+ items: [{
+ type: "bi.sign_initial_editor",
+ ref: function () {
+ self.editor = this;
+ },
+ cls: "layout-bg5",
+ text: "原始值",
+ width: 300
+ }],
+ vgap: 20
+
+ }
+ }
+})
+
+BI.shortcut("demo.sign_initial_editor", Demo.SignInitialEditor);/**
+ * Created by Dailer on 2017/7/11.
+ */
+Demo.StateEditor = BI.inherit(BI.Widget, {
+ props: {
+ baseCls: ""
+ },
+ render: function () {
+ return {
+ type: "bi.horizontal_adapt",
+ items: [{
+ type: "bi.state_editor",
+ value: "123",
+ text: "456",
+ width: 300
+ }],
+ vgap: 20
+
+ }
+ }
+})
+
+BI.shortcut("demo.state_editor", Demo.StateEditor);Demo.Func = BI.inherit(BI.Widget, {
props: {
baseCls: "demo-func"
},
@@ -3038,10 +3155,6 @@ BI.shortcut("demo.value_chooser_pane", Demo.ValueChooserPane);Demo.BASE_CONFIG =
pId: 3,
id: 301,
text: "editors"
-}, {
- pId: 301,
- text: "bi.record_editor",
- value: "demo.record_editor"
}, {
pId: 301,
text: "bi.shelter_editor",
@@ -3050,6 +3163,10 @@ BI.shortcut("demo.value_chooser_pane", Demo.ValueChooserPane);Demo.BASE_CONFIG =
pId: 301,
text: "bi.sign_editor",
value: "demo.sign_editor"
+}, {
+ pId: 301,
+ text: "bi.sign_initial_editor",
+ value: "demo.sign_initial_editor"
}, {
pId: 301,
text: "bi.state_editor",
@@ -3138,7 +3255,7 @@ BI.shortcut("demo.value_chooser_pane", Demo.ValueChooserPane);Demo.BASE_CONFIG =
*/
Demo.COMPONENT_CONFIG = [{
id: 5,
- text: "部件"
+ text: "部件+服务"
}, {
pId: 5,
text: "bi.value_chooser_combo",
@@ -3347,263 +3464,261 @@ Demo.COMPONENT_CONFIG = [{
text: "pane",
value: "demo.pane"
}];Demo.WIDGET_CONFIG = [{
- id: 4,
- text: "详细控件",
- open: true
- }, {
- id: 400,
- pId: 4,
- text: "tree"
- }, {
- pId: 400,
- text: "bi.multi_tree_combo",
- value: "demo.multi_tree_combo"
- }, {
- id: 401,
- pId: 4,
- text: "table"
- }, {
- pId: 401,
- text: "bi.preview_table",
- value: "demo.preview_table"
- }, {
- pId: 401,
- text: "bi.responsive_table",
- value: "demo.responsive_table"
- }, {
- pId: 401,
- text: "bi.excel_table",
- value: "demo.excel_table"
- }, {
- pId: 4,
- id: 402,
- text: "年份控件",
- open: false
- }, {
- pId: 402,
- text: "bi.year_combo",
- value: "demo.year"
- }, {
- pId: 4,
- id: 403,
- text: "月份控件",
- open: false
- }, {
- pId: 403,
- text: "bi.month_combo",
- value: "demo.month"
- }, {
- pId: 4,
- id: 404,
- text: "季度控件",
- open: false
- }, {
- pId: 404,
- text: "bi.quarter_combo",
- value: "demo.quarter"
- }, {
- pId: 4,
- id: 405,
- text: "下拉列表",
- open: false
- }, {
- pId: 405,
- text: "bi.down_list_combo",
- value: "demo.down_list"
- }, {
- pId: 4,
- id: 406,
- text: "文本框控件",
- open: false
- }, {
- pId: 406,
- text: "bi.text_editor",
- value: "demo.text_editor"
- }, {
- pId: 406,
- text: "bi.search_editor",
- value: "demo.search_editor"
- }, {
- pId: 406,
- text: "bi.sign_editor",
- value: "demo.sign_editor"
- }, {
- pId: 406,
- text: "bi.sign_initial_editor",
- value: "demo.sign_initial_editor"
- }, {
- pId: 406,
- text: "bi.sign_style_editor",
- value: "demo.sign_style_editor"
- }, {
- pId: 406,
- text: "bi.state_editor",
- value: "demo.state_editor"
- }, {
- pId: 406,
- text: "bi.clear_editor",
- value: "demo.clear_editor"
- }, {
- pId: 406,
- text: "bi.record_editor",
- value: "demo.record_editor"
- }, {
- pId: 406,
- text: "bi.shelter_editor",
- value: "demo.shelter_editor"
- },
- {
- pId: 4,
- id: 407,
- text: "下拉框控件",
- open: false
- }, {
- pId: 407,
- text: "bi.text_value_combo",
- value: "demo.text_value_combo"
- }, {
- pId: 407,
- text: "bi.text_value_check_combo",
- value: "demo.text_value_check_combo"
- }, {
- pId: 407,
- text: "bi.text_value_down_list_combo",
- value: "demo.text_value_down_list_combo"
- }, {
- pId: 407,
- text: "bi.static_combo",
- value: "demo.static_combo"
- }, {
- pId: 407,
- text: "bi.icon_combo",
- value: "demo.icon_combo"
- }, {
- pId: 407,
- text: "bi.formula_combo",
- value: "demo.formula_combo"
- }, {
- pId: 4,
- id: 408,
- text: "选择字段列表",
- open: false
- }, {
- pId: 408,
- text: "bi.placeholder"
- }, {
- pId: 4,
- id: 409,
- text: "公式编辑器",
- open: false
- }, {
- pId: 409,
- text: "bi.placeholder"
- }, {
- pId: 4,
- id: 410,
- text: "数值区间控件"
- }, {
- pId: 410,
- text: "bi.numerical_interval",
- value: "demo.numberical_interval"
- }, {
- pId: 4,
- id: 411,
- text: "下拉复选框有确定按钮"
- }, {
- pId: 411,
- text: "bi.multi_select_combo",
- value: "demo.multi_select_combo"
- }, {
- pId: 4,
- id: 412,
- text: "简单日期控件"
- }, {
- pId: 412,
- text: "bi.date_combo",
- value: "demo.date"
- }, {
- pId: 412,
- text: "bi.date_pane_widget",
- value: "demo.date_pane_widget"
- }, {
- pId: 412,
- text: "bi.year_month_combo",
- value: "demo.year_month_combo"
- },{
- pId: 412,
- text: "bi.year_quarter_combo",
- value: "demo.year_quarter_combo"
- },{
- pId: 412,
- text: "bi.custom_date_time",
- value: "demo.custom_date_time"
- },{
- pId: 4,
- id: 413,
- text: "简单下拉树"
- }, {
- pId: 413,
- text: "bi.single_tree_combo",
- value: "demo.single_tree_combo"
- }, {
- pId: 413,
- text: "bi.multilayer_single_tree_combo",
- value: "demo.multilayer_single_tree_combo"
- }, {
- pId: 4,
- id: 414,
- text: "可选下拉树"
- }, {
- pId: 414,
- text: "bi.select_tree_combo",
- value: "demo.select_tree_combo"
- }, {
- pId: 414,
- text: "bi.multilayer_select_tree_combo",
- value: "demo.multilayer_select_tree_combo"
- }, {
- pId: 4,
- id: 415,
- text: "路径选择"
- }, {
- pId: 415,
- text: "bi.path_chooser",
- value: "demo.path_chooser"
- }, {
- pId: 415,
- text: "bi.direction_path_chooser",
- value: "demo.direction_path_chooser"
- }, {
- pId: 4,
- id: 416,
- text: "关联视图"
- }, {
- pId: 416,
- text: "bi.relation_view",
- value: "demo.relation_view"
- }, {
- pId: 4,
- id: 417,
- text: "布局"
- }, {
- pId: 417,
- text: "bi.adaptive_arrangement",
- value: "demo.adaptive_arrangement"
- }, {
- pId: 417,
- text: "bi.interactive_arrangement",
- value: "demo.interactive_arrangement"
- }, {
- pId: 4,
- id: 418,
- text: "提示对话框"
- }, {
- pId: 418,
- text: "bi.dialog",
- value: "demo.dialog"
- }
-];
-Demo.Func = BI.inherit(BI.Widget, {
+ id: 4,
+ text: "详细控件",
+ open: true
+}, {
+ pId: 4,
+ id: 420,
+ text: '各种小控件',
+}, {
+ pId: 420,
+ text: "各种通用按钮",
+ value: "demo.buttons"
+}, {
+ pId: 420,
+ text: "各种提示性信息",
+ value: "demo.tips"
+}, {
+ pId: 420,
+ text: "各种items",
+ value: "demo.items"
+}, {
+ pId: 420,
+ text: "各种节点node",
+ value: "demo.nodes"
+}, {
+ pId: 420,
+ text: "各种segment",
+ value: "demo.segments"
+}, {
+ pId: 420,
+ text: "可以切换的树",
+ value: "demo.switch_tree"
+}, {
+ id: 400,
+ pId: 4,
+ text: "tree"
+}, {
+ pId: 400,
+ text: "bi.multi_tree_combo",
+ value: "demo.multi_tree_combo"
+}, {
+ pId: 400,
+ text: "bi.switch_tree",
+ value: "demo.switch_tree"
+}, {
+ id: 401,
+ pId: 4,
+ text: "table"
+}, {
+ pId: 401,
+ text: "bi.preview_table",
+ value: "demo.preview_table"
+}, {
+ pId: 401,
+ text: "bi.responsive_table",
+ value: "demo.responsive_table"
+}, {
+ pId: 401,
+ text: "bi.excel_table",
+ value: "demo.excel_table"
+}, {
+ pId: 4,
+ id: 402,
+ text: "年份控件",
+ open: false
+}, {
+ pId: 402,
+ text: "bi.year_combo",
+ value: "demo.year"
+}, {
+ pId: 4,
+ id: 403,
+ text: "月份控件",
+ open: false
+}, {
+ pId: 403,
+ text: "bi.month_combo",
+ value: "demo.month"
+}, {
+ pId: 4,
+ id: 404,
+ text: "季度控件",
+ open: false
+}, {
+ pId: 404,
+ text: "bi.quarter_combo",
+ value: "demo.quarter"
+}, {
+ pId: 4,
+ id: 405,
+ text: "下拉列表",
+ open: false
+}, {
+ pId: 405,
+ text: "bi.down_list_combo",
+ value: "demo.down_list"
+}, {
+ pId: 4,
+ id: 406,
+ text: "文本框控件",
+ open: false
+}, {
+ pId: 406,
+ text: "bi.text_editor",
+ value: "demo.text_editor"
+}, {
+ pId: 406,
+ text: "bi.search_editor",
+ value: "demo.search_editor"
+}, {
+ pId: 406,
+ text: "bi.clear_editor",
+ value: "demo.clear_editor"
+}, {
+ pId: 4,
+ id: 407,
+ text: "下拉框控件",
+ open: false
+}, {
+ pId: 407,
+ text: "bi.text_value_combo",
+ value: "demo.text_value_combo"
+}, {
+ pId: 407,
+ text: "bi.text_value_check_combo",
+ value: "demo.text_value_check_combo"
+}, {
+ pId: 407,
+ text: "bi.text_value_down_list_combo",
+ value: "demo.text_value_down_list_combo"
+}, {
+ pId: 407,
+ text: "bi.static_combo",
+ value: "demo.static_combo"
+}, {
+ pId: 407,
+ text: "bi.icon_combo",
+ value: "demo.icon_combo"
+}, {
+ pId: 407,
+ text: "bi.formula_combo",
+ value: "demo.formula_combo"
+}, {
+ pId: 4,
+ id: 410,
+ text: "数值区间控件"
+}, {
+ pId: 410,
+ text: "bi.numerical_interval",
+ value: "demo.numberical_interval"
+}, {
+ pId: 4,
+ id: 411,
+ text: "下拉复选框有确定按钮"
+}, {
+ pId: 411,
+ text: "bi.multi_select_combo",
+ value: "demo.multi_select_combo"
+}, {
+ pId: 4,
+ id: 412,
+ text: "简单日期控件"
+}, {
+ pId: 412,
+ text: "bi.date_combo",
+ value: "demo.date"
+}, {
+ pId: 412,
+ text: "bi.date_pane_widget",
+ value: "demo.date_pane_widget"
+}, {
+ pId: 412,
+ text: "bi.year_month_combo",
+ value: "demo.year_month_combo"
+}, {
+ pId: 412,
+ text: "bi.year_quarter_combo",
+ value: "demo.year_quarter_combo"
+}, {
+ pId: 412,
+ text: "bi.custom_date_time",
+ value: "demo.custom_date_time"
+}, {
+ pId: 4,
+ id: 413,
+ text: "简单下拉树"
+}, {
+ pId: 413,
+ text: "bi.single_tree_combo",
+ value: "demo.single_tree_combo"
+}, {
+ pId: 413,
+ text: "bi.multilayer_single_tree_combo",
+ value: "demo.multilayer_single_tree_combo"
+}, {
+ pId: 4,
+ id: 414,
+ text: "可选下拉树"
+}, {
+ pId: 414,
+ text: "bi.select_tree_combo",
+ value: "demo.select_tree_combo"
+}, {
+ pId: 414,
+ text: "bi.multilayer_select_tree_combo",
+ value: "demo.multilayer_select_tree_combo"
+}, {
+ pId: 4,
+ id: 415,
+ text: "路径选择"
+}, {
+ pId: 415,
+ text: "bi.path_chooser",
+ value: "demo.path_chooser"
+}, {
+ pId: 415,
+ text: "bi.direction_path_chooser",
+ value: "demo.direction_path_chooser"
+}, {
+ pId: 4,
+ id: 416,
+ text: "关联视图"
+}, {
+ pId: 416,
+ text: "bi.relation_view",
+ value: "demo.relation_view"
+}, {
+ pId: 4,
+ id: 417,
+ text: "布局"
+}, {
+ pId: 417,
+ text: "bi.adaptive_arrangement",
+ value: "demo.adaptive_arrangement"
+}, {
+ pId: 417,
+ text: "bi.interactive_arrangement",
+ value: "demo.interactive_arrangement"
+}, {
+ pId: 4,
+ id: 418,
+ text: "提示对话框"
+}, {
+ pId: 418,
+ text: "bi.dialog",
+ value: "demo.dialog"
+}, {
+ pId: 4,
+ id: 419,
+ text: "文件管理"
+}, {
+ pId: 419,
+ text: "bi.file_manager",
+ value: "demo.file_manager"
+}
+];Demo.Func = BI.inherit(BI.Widget, {
props: {
baseCls: "demo-func"
},
@@ -6299,81 +6414,585 @@ Demo.RelationView = BI.inherit(BI.Widget, {
}
});
BI.shortcut("demo.interactive_arrangement", Demo.RelationView);/**
- * Created by Dailer on 2017/7/12.
+ * Created by Dailer on 2017/7/25.
*/
-Demo.FormulaCombo = BI.inherit(BI.Widget, {
- props: {
- baseCls: ""
- },
-
- render: function () {
-
- var self = this;
-
- return {
- type: "bi.horizontal_auto",
- items: [{
- type: "bi.formula_combo",
- fieldItems: [{
- text: "A",
- value: "A",
- fieldType: 16
- }],
- width: 200,
- height: 30
- }],
- vgap: 20
- }
- }
-})
-BI.shortcut("demo.formula_combo", Demo.FormulaCombo);/**
- * Created by Dailer on 2017/7/12.
- */
-Demo.IconCombo = BI.inherit(BI.Widget, {
+Demo.Buttons = BI.inherit(BI.Widget, {
props: {
- baseCls: ""
+ baseCls: "demo-button"
},
-
render: function () {
-
- var self = this;
-
-
- return {
- type: "bi.horizontal_auto",
- items: [{
- type: "bi.icon_combo",
- ref:function(_ref){
- self.refs=_ref;
- },
- // iconClass: "pull-down-ha-font",
- items: [{
- value: "第一项",
- iconClass: "delete-font"
- }, {
- value: "第二项",
- iconClass: "rename-font"
- }, {
- value: "第三项",
- iconClass: "move-font"
- }]
- }],
- vgap: 20
- }
- }
-})
-
-BI.shortcut("demo.icon_combo", Demo.IconCombo);/**
- * Created by Dailer on 2017/7/11.
- */
-Demo.StaticCombo = BI.inherit(BI.Widget, {
- props: {
- baseCls: ""
- },
-
-
+ var items = [{
+ el: {
+ type: 'bi.button',
+ text: '一般按钮',
+ level: 'common',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '表示成功状态按钮',
+ level: 'success',
+ height: 30
+ }
+ },
+ {
+ el: {
+ type: 'bi.button',
+ text: '表示警告状态的按钮',
+ level: 'warning',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '表示忽略状态的按钮',
+ level: 'ignore',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '普通灰化按钮',
+ disabled: true,
+ level: 'success',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '忽略状态灰化按钮',
+ disabled: true,
+ level: 'ignore',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '带图标的按钮',
+ //level: 'ignore',
+ iconClass: "close-font",
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '一般按钮',
+ block: true,
+ level: 'common',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '表示成功状态按钮',
+ block: true,
+ level: 'success',
+ height: 30
+ }
+ },
+ {
+ el: {
+ type: 'bi.button',
+ text: '表示警告状态的按钮',
+ block: true,
+ level: 'warning',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '表示忽略状态的按钮',
+ block: true,
+ level: 'ignore',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '普通灰化按钮',
+ block: true,
+ disabled: true,
+ level: 'success',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '忽略状态灰化按钮',
+ block: true,
+ disabled: true,
+ level: 'ignore',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '带图标的按钮',
+ block: true,
+ //level: 'ignore',
+ iconClass: "close-font",
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '一般按钮',
+ clear: true,
+ level: 'common',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '表示成功状态按钮',
+ clear: true,
+ level: 'success',
+ height: 30
+ }
+ },
+ {
+ el: {
+ type: 'bi.button',
+ text: '表示警告状态的按钮',
+ clear: true,
+ level: 'warning',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '表示忽略状态的按钮',
+ clear: true,
+ level: 'ignore',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '普通灰化按钮',
+ clear: true,
+ disabled: true,
+ level: 'success',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '忽略状态灰化按钮',
+ clear: true,
+ disabled: true,
+ level: 'ignore',
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '带图标的按钮',
+ clear: true,
+ //level: 'ignore',
+ iconClass: "close-font",
+ height: 30
+ }
+ }, {
+ el: {
+ type: 'bi.text_button',
+ text: '文字按钮',
+ height: 30
+ }
+ }
+ ];
+ BI.each(items, function (i, item) {
+ item.el.handler = function () {
+ BI.Msg.alert('按钮', this.options.text);
+ }
+ });
+ return {
+ type: "bi.left",
+ vgap: 100,
+ hgap: 20,
+ items: items
+ }
+ }
+});
+BI.shortcut("demo.buttons", Demo.Buttons);/**
+ * Created by Dailer on 2017/7/25.
+ */
+
+Demo.Items = BI.inherit(BI.Widget, {
+
+ render: function () {
+
+ return {
+ type: "bi.vertical",
+ items: [{
+ type: "bi.label",
+ height: 30,
+ text: "单选item"
+ }, {
+ type: "bi.single_select_item",
+ text: "单选项"
+ }, {
+ type: "bi.label",
+ height: 30,
+ text: "复选item"
+ }, {
+ type: "bi.multi_select_item",
+ text: "复选项"
+ }],
+ hgap: 300
+ }
+ }
+});
+
+
+BI.shortcut("demo.items", Demo.Items);/**
+ * Created by Dailer on 2017/7/25.
+ */
+
+Demo.LoadingMask = BI.inherit(BI.Widget, {
+
+ render: function () {
+ var vessel = this;
+ var self = this;
+ var left = BI.createWidget({
+ type: "bi.center_adapt",
+ items: [{
+ type: "bi.button",
+ text: "LoadingMask",
+ height: 30,
+ handler: function () {
+ var mask = BI.createWidget({
+ type: "bi.loading_mask",
+ masker: vessel,
+ text: "加载中...3s后结束"
+ });
+ setTimeout(function () {
+ mask.destroy();
+ }, 3000);
+ }
+ }]
+ });
+ var right = BI.createWidget({
+ type: "bi.center_adapt",
+ items: [{
+ type: "bi.button",
+ text: "CancelLoadingMask",
+ height: 30,
+ handler: function () {
+ var mask = BI.createWidget({
+ type: "bi.loading_cancel_mask",
+ masker: vessel,
+ text: "正在加载数据"
+ });
+ mask.on(BI.LoadingCancelMask.EVENT_VALUE_CANCEL, function () {
+ mask.destroy();
+ BI.Msg.toast("取消加载了...");
+ });
+ }
+ }]
+ });
+ BI.createWidget({
+ type: "bi.center_adapt",
+ element: vessel,
+ items: [left, right],
+ hgap: 20
+ })
+ }
+});
+
+BI.shortcut("demo.loading_mask", Demo.LoadingMask);/**
+ * Created by Dailer on 2017/7/25.
+ */
+
+Demo.Nodes = BI.inherit(BI.Widget, {
+
+ render: function (vessel) {
+ return {
+ type: "bi.vertical",
+ items: [{
+ type: "bi.label",
+ height: 30,
+ text: "十字形的节点"
+ }, {
+ type: "bi.plus_group_node",
+ text: "十字形的节点"
+ }, {
+ type: "bi.label",
+ height: 30,
+ text: "三角形的节点"
+ }, {
+ type: "bi.triangle_group_node",
+ text: "三角形的节点"
+ }, {
+ type: "bi.label",
+ height: 30,
+ text: "箭头节点"
+ }, {
+ type: "bi.arrow_group_node",
+ text: "箭头节点"
+ }]
+ }
+ }
+});
+
+BI.shortcut("demo.nodes", Demo.Nodes);/**
+ * Created by Dailer on 2017/7/25.
+ */
+
+Demo.Segments = BI.inherit(BI.Widget, {
+
+ render: function () {
+ return {
+ type: "bi.vertical",
+ items: [{
+ type: "bi.label",
+ height: 30,
+ text: "默认风格"
+ }, {
+ type: "bi.segment",
+ items: [{
+ text: "tab1",
+ value: 1,
+ selected: true
+ }, {
+ text: "tab2",
+ value: 2
+ }, {
+ text: "tab3 disabled",
+ disabled: true,
+ value: 3
+ }]
+ }],
+ hgap: 50,
+ vgap: 20
+ }
+ }
+});
+
+BI.shortcut("demo.segments", Demo.Segments);/**
+ * Created by Dailer on 2017/7/25.
+ */
+
+Demo.Tips = BI.inherit(BI.Widget, {
+ props: {
+ baseCls: "demo-tips"
+ },
+ render: function () {
+ var btns = [];
+ var bubble = BI.createWidget({
+ type: "bi.left",
+ items: [{
+ el: {
+ type: 'bi.button',
+ text: 'bubble测试',
+ height: 30,
+ handler: function () {
+ BI.Bubbles.show("singleBubble1", "bubble测试", this);
+ btns.push("singleBubble1");
+ }
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: 'bubble测试(居中显示)',
+ height: 30,
+ handler: function () {
+ BI.Bubbles.show("singleBubble2", "bubble测试", this, {
+ offsetStyle: "center"
+ });
+ btns.push("singleBubble2");
+ }
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: 'bubble测试(右边显示)',
+ height: 30,
+ handler: function () {
+ BI.Bubbles.show("singleBubble3", "bubble测试", this, {
+ offsetStyle: "right"
+ });
+ btns.push("singleBubble3");
+ }
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '隐藏所有 bubble',
+ height: 30,
+ cls: "layout-bg2",
+ handler: function () {
+ BI.each(btns, function (index, value) {
+ BI.Bubbles.hide(value);
+ })
+ }
+ }
+ }],
+ hgap: 20
+ });
+
+ var title = BI.createWidget({
+ type: "bi.vertical",
+ items: [{
+ type: "bi.label",
+ cls: "layout-bg1",
+ height: 50,
+ title: "title提示",
+ text: "移上去有title提示",
+ textAlign: "center"
+ }, {
+ type: "bi.label",
+ cls: "layout-bg6",
+ height: 50,
+ disabled: true,
+ warningTitle: "title错误提示",
+ text: "移上去有title错误提示",
+ textAlign: "center"
+ }, {
+ type: "bi.label",
+ cls: "layout-bg2",
+ height: 50,
+ disabled: true,
+ tipType: "success",
+ title: "自定义title提示效果",
+ warningTitle: "自定义title提示效果",
+ text: "自定义title提示效果",
+ textAlign: "center"
+ }],
+ hgap: 20,
+ vgap: 20
+ });
+
+ var toast = BI.createWidget({
+ type: "bi.vertical",
+ items: [{
+ el: {
+ type: 'bi.button',
+ text: '简单Toast测试',
+ height: 30,
+ handler: function () {
+ BI.Msg.toast("这是一条简单的数据");
+ }
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '很长的Toast测试',
+ height: 30,
+ handler: function () {
+ BI.Msg.toast("这是一条很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长的数据")
+ }
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '非常长的Toast测试',
+ height: 30,
+ handler: function () {
+ BI.Msg.toast("这是一条非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长的数据")
+ }
+ }
+ }, {
+ el: {
+ type: 'bi.button',
+ text: '错误提示Toast测试',
+ level: "warning",
+ height: 30,
+ handler: function () {
+ BI.Msg.toast("错误提示Toast测试", "warning");
+ }
+ }
+ }],
+ vgap: 20
+ });
+
+ return {
+ type: "bi.horizontal_auto",
+ vgap: 20,
+ hgap: 20,
+ items: [bubble, title, toast]
+ }
+ }
+});
+BI.shortcut("demo.tips", Demo.Tips);/**
+ * Created by Dailer on 2017/7/12.
+ */
+Demo.FormulaCombo = BI.inherit(BI.Widget, {
+ props: {
+ baseCls: ""
+ },
+
+ render: function () {
+
+ var self = this;
+
+
+ return {
+ type: "bi.horizontal_auto",
+ items: [{
+ type: "bi.formula_combo",
+ fieldItems: [{
+ text: "A",
+ value: "A",
+ fieldType: 16
+ }],
+ width: 200,
+ height: 30
+ }],
+ vgap: 20
+ }
+ }
+})
+
+BI.shortcut("demo.formula_combo", Demo.FormulaCombo);/**
+ * Created by Dailer on 2017/7/12.
+ */
+Demo.IconCombo = BI.inherit(BI.Widget, {
+ props: {
+ baseCls: ""
+ },
+
+ render: function () {
+
+ var self = this;
+
+
+ return {
+ type: "bi.horizontal_auto",
+ items: [{
+ type: "bi.icon_combo",
+ ref:function(_ref){
+ self.refs=_ref;
+ },
+ // iconClass: "pull-down-ha-font",
+ items: [{
+ value: "第一项",
+ iconClass: "delete-font"
+ }, {
+ value: "第二项",
+ iconClass: "rename-font"
+ }, {
+ value: "第三项",
+ iconClass: "move-font"
+ }]
+ }],
+ vgap: 20
+ }
+ }
+})
+
+BI.shortcut("demo.icon_combo", Demo.IconCombo);/**
+ * Created by Dailer on 2017/7/11.
+ */
+Demo.StaticCombo = BI.inherit(BI.Widget, {
+ props: {
+ baseCls: ""
+ },
+
+
beforeMounted: function () {
this.refs.setValue(2);
},
@@ -6568,18 +7187,34 @@ Demo.Date = BI.inherit(BI.Widget, {
},
render: function () {
-
+ var self = this;
return {
type: "bi.horizontal_auto",
vgap: 10,
items: [{
type: "bi.date_combo",
+ ref: function () {
+ self.datecombo = this;
+ },
width: 300
}, {
type: "bi.button",
text: "getVlaue",
- height: 50,
- width: 300
+ width: 300,
+ handler: function () {
+ BI.Msg.alert("date", JSON.stringify(self.datecombo.getValue()));
+ }
+ }, {
+ type: "bi.button",
+ text: "setVlaue '2017-12-31'",
+ width: 300,
+ handler: function () {
+ self.datecombo.setValue({
+ year: 2017,
+ month: 11,
+ day: 31
+ })
+ }
}]
}
}
@@ -6590,7 +7225,7 @@ BI.shortcut("demo.date", Demo.Date);Demo.DatePane = BI.inherit(BI.Widget, {
baseCls: "demo-datepane"
},
render: function () {
-
+ var self = this;
return {
type: "bi.horizontal_auto",
items: [{
@@ -6607,13 +7242,26 @@ BI.shortcut("demo.date", Demo.Date);Demo.DatePane = BI.inherit(BI.Widget, {
month: 12,
day: 11
},
- height:300
+ ref: function (_ref) {
+ self.datepane = _ref;
+ },
+ height: 300
},
{
type: "bi.button",
text: "getValue",
handler: function () {
- BI.Msg.toast("date" + JSON.stringify(datepane.getValue()));
+ BI.Msg.toast("date" + JSON.stringify(self.datepane.getValue()));
+ }
+ }, {
+ type: "bi.button",
+ text: "setVlaue '2017-12-31'",
+ handler: function () {
+ self.datepane.setValue({
+ year: 2017,
+ month: 11,
+ day: 31
+ })
}
}
],
@@ -6889,27 +7537,6 @@ Demo.ClearEditor = BI.inherit(BI.Widget, {
BI.shortcut("demo.clear_editor", Demo.ClearEditor);/**
* Created by Dailer on 2017/7/11.
*/
-Demo.RecordEditor = BI.inherit(BI.Widget, {
- props: {
- baseCls: ""
- },
- render: function () {
- return {
- type: "bi.horizontal_auto",
- items: [{
- type: "bi.record_editor",
- cls: "bi-border",
- width: 300,
- watermark: "这个是可以记录输入的"
- }],
- vgap: 20
- }
- }
-})
-
-BI.shortcut("demo.record_editor", Demo.RecordEditor);/**
- * Created by Dailer on 2017/7/11.
- */
Demo.SearchEditor = BI.inherit(BI.Widget, {
props: {
baseCls: "demo-exceltable"
@@ -6938,81 +7565,22 @@ Demo.SearchEditor = BI.inherit(BI.Widget, {
BI.shortcut("demo.search_editor", Demo.SearchEditor);/**
* Created by Dailer on 2017/7/11.
*/
-Demo.ClearEditor = BI.inherit(BI.Widget, {
+Demo.TextEditor = BI.inherit(BI.Widget, {
props: {
- baseCls: ""
+ baseCls: "demo-exceltable"
},
render: function () {
- var editor;
return {
type: "bi.horizontal_auto",
items: [{
- type: "bi.shelter_editor",
- cls: "bi-border",
- ref:function(_ref){
- editor=_ref;
- },
- width: 300,
- watermark: "这个是带标记的"
- },{
- type:"bi.button",
- text:"setValue",
- width:300,
- handler:function(){
- editor.setValue("凛冬将至");
- }
- },{
- type:"bi.button",
- text:"doHighLight",
- width:300,
- handler:function(){
- editor.doHighLight();
- console.log(editor.getState());
- }
- }],
- vgap: 20
- }
- }
-})
-
-BI.shortcut("demo.shelter_editor", Demo.ClearEditor);/**
- * Created by Dailer on 2017/7/14.
- */
-Demo.SignEditor = BI.inherit(BI.Widget, {
- props: {
- baseCls: ""
- },
- render: function () {
- return {
- type: "bi.horizontal_adapt",
- items: [{
- type: "bi.sign_editor",
- // cls:"layout-bg5",
- value: "123",
- text: "456",
+ type: "bi.text_editor",
+ watermark:"这是水印,watermark",
width: 300
- }],
- vgap: 20
-
- }
- }
-})
-
-BI.shortcut("demo.sign_editor", Demo.SignEditor);/**
- * Created by Dailer on 2017/7/11.
- */
-Demo.SignInitialEditor = BI.inherit(BI.Widget, {
- props: {
- baseCls: ""
- },
- render: function () {
- return {
- type: "bi.horizontal_adapt",
- items: [{
- type: "bi.sign_initial_editor",
- cls:"layout-bg5",
- value:"123",
- text:"456",
+ },{
+ type: "bi.text_editor",
+ watermark:"这个不予许空",
+ allowBlank: false,
+ errorText: "非空!",
width: 300
}],
vgap:20
@@ -7021,78 +7589,74 @@ Demo.SignInitialEditor = BI.inherit(BI.Widget, {
}
})
-BI.shortcut("demo.sign_initial_editor", Demo.SignInitialEditor);/**
- * Created by Dailer on 2017/7/11.
- */
-Demo.SignStyleEditor = BI.inherit(BI.Widget, {
- props: {
- baseCls: "demo-exceltable"
- },
- render: function () {
- return {
- type: "bi.horizontal_adapt",
- items: [{
- type: "bi.sign_style_editor",
- cls:"layout-bg5",
- value:"12313",
- width: 300
- }],
- vgap:20
- }
- }
-})
-
-BI.shortcut("demo.sign_style_editor", Demo.SignStyleEditor);/**
- * Created by Dailer on 2017/7/11.
- */
-Demo.StateEditor = BI.inherit(BI.Widget, {
+BI.shortcut("demo.text_editor", Demo.TextEditor);/* 文件管理导航
+ Created by dailer on 2017 / 7 / 21.
+ */
+Demo.FileManager = BI.inherit(BI.Widget, {
props: {
baseCls: ""
},
- render: function () {
- return {
- type: "bi.horizontal_adapt",
- items: [{
- type: "bi.state_editor",
- cls:"bi-border",
- value:"123",
- text:"456",
- width: 300
- }],
- vgap:20
-
- }
- }
-})
-BI.shortcut("demo.state_editor", Demo.StateEditor);/**
- * Created by Dailer on 2017/7/11.
- */
-Demo.TextEditor = BI.inherit(BI.Widget, {
- props: {
- baseCls: "demo-exceltable"
- },
render: function () {
+ var items = [{
+ id: "1",
+ value: "1",
+ text: "根目录",
+ lastModify: 1454316355142
+ }, {
+ id: "11",
+ pId: "1",
+ value: "11",
+ text: "第一级子目录1",
+ lastModify: 1454316355142
+ }, {
+ id: "12",
+ pId: "1",
+ value: "12",
+ text: "第一级子目录2",
+ lastModify: 1454316355142
+ }, {
+ id: "111",
+ pId: "11",
+ value: "111",
+ text: "第二级子目录",
+ lastModify: 1454316355142
+ }, {
+ id: "121",
+ pId: "111",
+ buildUrl: "www.baidu.com",
+ value: "121",
+ text: "文件1",
+ lastModify: 1454316355142
+ }, {
+ id: "122",
+ pId: "111",
+ buildUrl: "www.baidu.com",
+ value: "122",
+ text: "文件2",
+ lastModify: 1454316355142
+ }];
+ var filemanager = BI.createWidget({
+ type: "bi.file_manager",
+ items: items
+ });
return {
- type: "bi.horizontal_auto",
+ type: "bi.vtape",
items: [{
- type: "bi.text_editor",
- watermark:"这是水印,watermark",
- width: 300
- },{
- type: "bi.text_editor",
- watermark:"这个不予许空",
- allowBlank: false,
- errorText: "非空!",
- width: 300
- }],
- vgap:20
-
+ el: filemanager,
+ height: "fill"
+ }, {
+ type: "bi.button",
+ text: "getValue",
+ handler: function () {
+ BI.Msg.alert("", JSON.stringify(filemanager.getValue()));
+ },
+ height: 25
+ }]
}
}
-})
-
-BI.shortcut("demo.text_editor", Demo.TextEditor);/**
+});
+BI.shortcut("demo.file_manager", Demo.FileManager);/**
* Created by Dailer on 2017/7/11.
*/
Demo.Month = BI.inherit(BI.Widget, {
@@ -7100,13 +7664,35 @@ Demo.Month = BI.inherit(BI.Widget, {
baseCls: "demo-exceltable"
},
render: function () {
+ var self = this;
return {
- type: "bi.horizontal_adapt",
+ type: "bi.horizontal_auto",
items: [{
type: "bi.month_combo",
+ width: 300,
+ ref: function () {
+ self.monthcombo = this;
+ }
+ }, {
+ type: "bi.button",
+ text: "getValue",
+ handler: function () {
+ BI.Msg.toast(JSON.stringify(self.monthcombo.getValue()));
+ },
width: 300
- }]
-
+ }, {
+ type: "bi.button",
+ text: "setValue : 11",
+ handler: function () {
+ self.monthcombo.setValue(11);
+ },
+ width: 300
+ }, {
+ type: "bi.label",
+ text: "月份value 范围为0-11,显示范围为1-12",
+ width: 300
+ }],
+ vgap: 10
}
}
})
@@ -7536,13 +8122,31 @@ Demo.Quarter = BI.inherit(BI.Widget, {
baseCls: "demo-exceltable"
},
render: function () {
+ var self = this;
return {
- type: "bi.horizontal_adapt",
+ type: "bi.horizontal_auto",
items: [{
type: "bi.quarter_combo",
+ width: 300,
+ ref: function () {
+ self.quartercombo = this;
+ }
+ }, {
+ type: "bi.button",
+ text: "getValue",
+ handler: function () {
+ BI.Msg.toast(JSON.stringify(self.quartercombo.getValue()));
+ },
width: 300
- }]
-
+ }, {
+ type: "bi.button",
+ text: "setValue : 3",
+ handler: function () {
+ self.quartercombo.setValue(3);
+ },
+ width: 300
+ }],
+ vgap: 10
}
}
})
@@ -7639,6 +8243,13 @@ Demo.MultiLayerSelectTreeCombo = BI.inherit(BI.Widget, {
BI.Msg.toast(self.tree.getValue()[0]);
},
width: 300
+ }, {
+ type: "bi.button",
+ text: "setVlaue (第二级文件1)",
+ handler: function () {
+ self.tree.setValue(["第二级文件1"]);
+ },
+ width: 300
}],
vgap: 20
}
@@ -7655,154 +8266,7 @@ Demo.SelectTreeCombo = BI.inherit(BI.Widget, {
render: function () {
var self = this;
- var items = [{
- id: 1,
- text: "第一项",
- value: 1,
- isParent: true,
- title: "第一项"
- }, {
- id: 2,
- text: "第二项",
- value: 2,
- isParent: true,
- title: "第二项"
- }, {
- id: 3,
- text: "第三项",
- value: 3,
- isParent: true,
- open: true,
- title: "第三项"
- }, {
- id: 4,
- text: "第四项",
- value: 4,
- isParent: true,
- title: "第四项"
- }, {
- id: 5,
- text: "第五项",
- value: 5,
- isParent: true,
- title: "第五项"
- }, {
- id: 6,
- text: "第六项",
- value: 6,
- isParent: true,
- open: true,
- title: "第六项"
- }, {
- id: 7,
- text: "第七项",
- value: 7,
- isParent: true,
- open: true,
- title: "第七项"
- }, {
- id: 11,
- pId: 1,
- text: "子项1",
- value: 11,
- title: "子项1"
- }, {
- id: 12,
- pId: 1,
- text: "子项2",
- value: 12,
- title: "子项2"
- }, {
- id: 13,
- pId: 1,
- text: "子项3",
- value: 13,
- title: "子项3"
- }, {
- id: 21,
- pId: 2,
- text: "子项1",
- value: 21,
- title: "子项1"
- }, {
- id: 22,
- pId: 2,
- text: "子项2",
- value: 22,
- title: "子项2"
- }, {
- id: 31,
- pId: 3,
- text: "子项1",
- value: 31,
- title: "子项1"
- }, {
- id: 32,
- pId: 3,
- text: "子项2",
- value: 32,
- title: "子项2"
- }, {
- id: 33,
- pId: 3,
- text: "子项3",
- value: 33,
- title: "子项3"
- }, {
- id: 41,
- pId: 4,
- text: "子项1",
- value: 41,
- title: "子项1"
- }, {
- id: 42,
- pId: 4,
- text: "子项2",
- value: 42,
- title: "子项2"
- }, {
- id: 43,
- pId: 4,
- text: "子项3",
- value: 43,
- title: "子项3"
- }, {
- id: 51,
- pId: 5,
- text: "子项1",
- value: 51,
- title: "子项1"
- }, {
- id: 52,
- pId: 5,
- text: "子项2",
- value: 52,
- title: "子项2"
- }, {
- id: 61,
- pId: 6,
- text: "子项1",
- value: 61,
- title: "子项1"
- }, {
- id: 62,
- pId: 6,
- text: "子项2",
- value: 62,
- title: "子项2"
- }, {
- id: 71,
- pId: 7,
- text: "子项1",
- value: 71,
- title: "子项1"
- }, {
- id: 72,
- pId: 7,
- text: "子项2",
- value: 72,
- title: "子项2"
- }];
+ var items = BI.deepClone(Demo.CONSTANTS.TREE);
return {
type: "bi.horizontal_auto",
items: [{
@@ -7820,6 +8284,13 @@ Demo.SelectTreeCombo = BI.inherit(BI.Widget, {
BI.Msg.toast(self.tree.getValue()[0]);
},
width: 300
+ }, {
+ type: "bi.button",
+ text: "setVlaue (第二级文件1)",
+ handler: function () {
+ self.tree.setValue(["第二级文件1"]);
+ },
+ width: 300
}],
vgap: 20
}
@@ -7854,6 +8325,13 @@ Demo.MultiLayerSingleTreeCombo = BI.inherit(BI.Widget, {
BI.Msg.toast(self.tree.getValue()[0]);
},
width: 300
+ }, {
+ type: "bi.button",
+ text: "setVlaue (第二级文件1)",
+ handler: function () {
+ self.tree.setValue(["第二级文件1"]);
+ },
+ width: 300
}],
vgap: 20
}
@@ -7870,6 +8348,7 @@ Demo.SingleTreeCombo = BI.inherit(BI.Widget, {
render: function () {
var self = this;
+ var items = BI.deepClone(Demo.CONSTANTS.TREE);
return {
type: "bi.horizontal_auto",
items: [{
@@ -7878,154 +8357,7 @@ Demo.SingleTreeCombo = BI.inherit(BI.Widget, {
self.tree = _ref;
},
text: "默认值",
- items: [{
- id: 1,
- text: "第一项",
- value: 1,
- isParent: true,
- title: "第一项"
- }, {
- id: 2,
- text: "第二项",
- value: 1,
- isParent: true,
- title: "第二项"
- }, {
- id: 3,
- text: "第三项",
- value: 1,
- isParent: true,
- open: true,
- title: "第三项"
- }, {
- id: 4,
- text: "第四项",
- value: 1,
- isParent: true,
- title: "第四项"
- }, {
- id: 5,
- text: "第五项",
- value: 1,
- isParent: true,
- title: "第五项"
- }, {
- id: 6,
- text: "第六项",
- value: 1,
- isParent: true,
- open: true,
- title: "第六项"
- }, {
- id: 7,
- text: "第七项",
- value: 1,
- isParent: true,
- open: true,
- title: "第七项"
- }, {
- id: 11,
- pId: 1,
- text: "子项1",
- value: 11,
- title: "子项1"
- }, {
- id: 12,
- pId: 1,
- text: "子项2",
- value: 12,
- title: "子项2"
- }, {
- id: 13,
- pId: 1,
- text: "子项3",
- value: 13,
- title: "子项3"
- }, {
- id: 21,
- pId: 2,
- text: "子项1",
- value: 21,
- title: "子项1"
- }, {
- id: 22,
- pId: 2,
- text: "子项2",
- value: 22,
- title: "子项2"
- }, {
- id: 31,
- pId: 3,
- text: "子项1",
- value: 31,
- title: "子项1"
- }, {
- id: 32,
- pId: 3,
- text: "子项2",
- value: 32,
- title: "子项2"
- }, {
- id: 33,
- pId: 3,
- text: "子项3",
- value: 33,
- title: "子项3"
- }, {
- id: 41,
- pId: 4,
- text: "子项1",
- value: 41,
- title: "子项1"
- }, {
- id: 42,
- pId: 4,
- text: "子项2",
- value: 42,
- title: "子项2"
- }, {
- id: 43,
- pId: 4,
- text: "子项3",
- value: 43,
- title: "子项3"
- }, {
- id: 51,
- pId: 5,
- text: "子项1",
- value: 51,
- title: "子项1"
- }, {
- id: 52,
- pId: 5,
- text: "子项2",
- value: 52,
- title: "子项2"
- }, {
- id: 61,
- pId: 6,
- text: "子项1",
- value: 61,
- title: "子项1"
- }, {
- id: 62,
- pId: 6,
- text: "子项2",
- value: 62,
- title: "子项2"
- }, {
- id: 71,
- pId: 7,
- text: "子项1",
- value: 71,
- title: "子项1"
- }, {
- id: 72,
- pId: 7,
- text: "子项2",
- value: 72,
- title: "子项2"
- }],
+ items: items,
width: 300
}, {
type: "bi.button",
@@ -8034,6 +8366,13 @@ Demo.SingleTreeCombo = BI.inherit(BI.Widget, {
BI.Msg.toast(self.tree.getValue()[0]);
},
width: 300
+ }, {
+ type: "bi.button",
+ text: "setVlaue (第二级文件1)",
+ handler: function () {
+ self.tree.setValue(["第二级文件1"]);
+ },
+ width: 300
}],
vgap: 20
}
@@ -8872,27 +9211,59 @@ Demo.TimeInterval = BI.inherit(BI.Widget, {
})
BI.shortcut("demo.time_interval", Demo.TimeInterval);/**
- * Created by Dailer on 2017/7/13.
+ * Created by Dailer on 2017/7/26.
*/
+
+
Demo.SwitchTree = BI.inherit(BI.Widget, {
- props: {
- baseCls: ""
- },
+
render: function () {
+ var self = this;
+ var tree = BI.createWidget({
+ type: "bi.switch_tree",
+ items: BI.deepClone(Demo.CONSTANTS.TREE)
+ });
- var items = BI.deepClone(Demo.CONSTANTS.TREE);
return {
- type: "bi.horizontal_auto",
+ type: "bi.vtape",
items: [{
- type: "bi.switch_tree",
- items: items
- },{
- type:"bi.button",
- text:"getValue"
- }]
+ el: tree
+ }, {
+ el: {
+ type: "bi.button",
+ height: 25,
+ text: "点击切换",
+ handler: function () {
+ tree.switchSelect();
+ }
+ },
+ height: 25
+ }, {
+ el: {
+ type: "bi.button",
+ height: 25,
+ text: "getValue",
+ handler: function () {
+ BI.Msg.alert("", JSON.stringify(tree.getValue()));
+ }
+ },
+ height: 25
+ }, {
+ el: {
+ type: "bi.button",
+ height: 25,
+ text: "setValue (第二级文件1)",
+ handler: function () {
+ tree.setValue(["第二级文件1"]);
+ }
+ },
+ height: 25
+ }],
+ width: 500,
+ hgap: 300
}
}
-})
+});
BI.shortcut("demo.switch_tree", Demo.SwitchTree);/**
* Created by Dailer on 2017/7/11.
@@ -8902,12 +9273,31 @@ Demo.Year = BI.inherit(BI.Widget, {
baseCls: "demo-exceltable"
},
render: function () {
+ var self = this;
return {
- type: "bi.horizontal_adapt",
+ type: "bi.horizontal_auto",
items: [{
type: "bi.year_combo",
+ width: 300,
+ ref: function () {
+ self.yearcombo = this;
+ }
+ }, {
+ type: "bi.button",
+ text: "getValue",
+ handler: function () {
+ BI.Msg.toast(JSON.stringify(self.yearcombo.getValue()));
+ },
width: 300
- }]
+ }, {
+ type: "bi.button",
+ text: "setValue : 2018",
+ handler: function () {
+ self.yearcombo.setValue(2018);
+ },
+ width: 300
+ }],
+ vgap: 10
}
}
})
@@ -8937,6 +9327,16 @@ Demo.YearMonthCombo = BI.inherit(BI.Widget, {
BI.Msg.toast(JSON.stringify(self.widget.getValue()))
},
width: 300
+ }, {
+ type: "bi.button",
+ text: "setVlaue '2017-12'",
+ width: 300,
+ handler: function () {
+ self.widget.setValue({
+ year: 2017,
+ month: 11
+ })
+ }
}],
vgap: 20
}
@@ -8951,24 +9351,34 @@ Demo.YearQuarterCombo = BI.inherit(BI.Widget, {
baseCls: ""
},
render: function () {
- var self=this;
+ var self = this;
return {
type: "bi.horizontal_auto",
items: [{
type: "bi.year_quarter_combo",
width: 300,
- ref:function(_ref){
- self.widget=_ref;
+ ref: function (_ref) {
+ self.widget = _ref;
},
yearBehaviors: {},
quarterBehaviors: {},
}, {
type: "bi.button",
text: "getValue",
- handler:function(){
+ handler: function () {
BI.Msg.toast(JSON.stringify(self.widget.getValue()))
},
width: 300
+ }, {
+ type: "bi.button",
+ text: "setVlaue '2017 季度3'",
+ width: 300,
+ handler: function () {
+ self.widget.setValue({
+ year: 2017,
+ quarter: 3
+ })
+ }
}],
vgap: 20
}
diff --git a/docs/resource.css b/docs/resource.css
index 4e785c5f0..082394641 100644
--- a/docs/resource.css
+++ b/docs/resource.css
@@ -146,7 +146,7 @@ textarea::-webkit-scrollbar-thumb:hover {
-moz-osx-font-smoothing: grayscale;
}
.close-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.close-font .b-font:before {
content: "\e600";
@@ -158,7 +158,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.close-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.close-h-font .b-font:before {
content: "\e600";
@@ -176,7 +176,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.close-ha-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.close-ha-font .b-font:before {
content: "\e600";
@@ -199,7 +199,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.search-close-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.search-close-h-font .b-font:before {
content: "\e600";
@@ -217,7 +217,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.pre-page-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.pre-page-h-font .b-font:before {
content: "\e601";
@@ -235,7 +235,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.next-page-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.next-page-h-font .b-font:before {
content: "\e602";
@@ -253,7 +253,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.search-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.search-font .b-font:before {
content: "\e604";
@@ -265,7 +265,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.dot-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.dot-font .b-font:before {
content: "\e606";
@@ -277,7 +277,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: #1a1a1a;
}
.dot-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.dot-h-font .b-font:before {
content: "\e606";
@@ -295,7 +295,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: #1a1a1a;
}
.dot-ha-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.dot-ha-font .b-font:before {
content: "\e606";
@@ -318,7 +318,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: #ffffff;
}
.dot-e-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.dot-e-font .b-font:before {
content: "\e606";
@@ -344,7 +344,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: #ffffff;
}
.pull-right-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.pull-right-font .b-font:before {
content: "\e607";
@@ -356,7 +356,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.pull-right-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.pull-right-h-font .b-font:before {
content: "\e607";
@@ -374,7 +374,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.pull-right-ha-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.pull-right-ha-font .b-font:before {
content: "\e607";
@@ -397,7 +397,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.pull-right-e-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.pull-right-e-font .b-font:before {
content: "\e607";
@@ -423,7 +423,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.copy-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.copy-font .b-font:before {
content: "\e610";
@@ -435,7 +435,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.copy-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.copy-h-font .b-font:before {
content: "\e610";
@@ -453,7 +453,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: #1a1a1a;
}
.copy-ha-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.copy-ha-font .b-font:before {
content: "\e610";
@@ -476,7 +476,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.copy-e-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.copy-e-font .b-font:before {
content: "\e610";
@@ -502,7 +502,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.check-mark-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.check-mark-font .b-font:before {
content: "\e611";
@@ -514,7 +514,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.check-mark-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.check-mark-h-font .b-font:before {
content: "\e611";
@@ -532,7 +532,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.check-mark-ha-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.check-mark-ha-font .b-font:before {
content: "\e611";
@@ -555,7 +555,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.check-mark-e-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.check-mark-e-font .b-font:before {
content: "\e611";
@@ -582,7 +582,7 @@ textarea::-webkit-scrollbar-thumb:hover {
}
/** dashboard组件/控件 下拉列表图标字体 ~end~**/
.tree-node-triangle-expand-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.tree-node-triangle-expand-font .b-font:before {
content: "\e608";
@@ -594,7 +594,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.tree-node-triangle-collapse-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.tree-node-triangle-collapse-font .b-font:before {
content: "\e607";
@@ -606,7 +606,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.row-pre-page-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.row-pre-page-h-font .b-font:before {
content: "\e6be";
@@ -624,7 +624,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.row-next-page-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.row-next-page-h-font .b-font:before {
content: "\e6bd";
@@ -642,7 +642,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.column-pre-page-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.column-pre-page-h-font .b-font:before {
content: "\e6bc";
@@ -660,7 +660,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.column-next-page-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.column-next-page-h-font .b-font:before {
content: "\e6bb";
@@ -678,7 +678,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.trigger-triangle-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.trigger-triangle-font .b-font:before {
content: "\e66a";
@@ -701,7 +701,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: #999999;
}
.pull-down-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.pull-down-font .b-font:before {
content: "\e608";
@@ -713,7 +713,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.pull-down-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.pull-down-h-font .b-font:before {
content: "\e608";
@@ -731,7 +731,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.pull-down-ha-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.pull-down-ha-font .b-font:before {
content: "\e608";
@@ -754,7 +754,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.check-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.check-font .b-font:before {
content: "\e611";
@@ -766,7 +766,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: #3f8ce8;
}
.item-check-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.item-check-font .b-font:before {
content: "\e611";
@@ -789,7 +789,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: #ffffff;
}
.primary-key-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = ';');
}
.primary-key-font .b-font:before {
content: "\e67d;";
@@ -807,7 +807,7 @@ textarea::-webkit-scrollbar-thumb:hover {
color: inherit;
}
.drag-tag-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.drag-tag-font .b-font:before {
content: "\e600";
@@ -818,17 +818,50 @@ textarea::-webkit-scrollbar-thumb:hover {
content: "\e600";
color: #f07d0a;
}
-
-.chart-date-normal-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+.less-font .b-font {
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+}
+.less-font .b-font:before {
+ content: "\e633";
+ color: inherit;
+}
+.less-font:hover .b-font:before,
+.less-font:focus .b-font:before,
+.less-font.hover .b-font:before {
+ content: "\e633";
+ color: inherit;
+}
+.less-font:active .b-font:before,
+.less-font.active .b-font:before {
+ content: "\e633";
+ color: #3f8ce8;
}
-.chart-date-normal-font .b-font:before {
- content: "\e61b";
+.less-font.native .b-font:before,
+.less-font.disabled .b-font:before {
+ content: "\e633";
color: inherit;
}
-.chart-date-normal-font.native .b-font:before,
-.chart-date-normal-font.disabled .b-font:before {
- content: "\e61b";
+.less-equal-font .b-font {
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+}
+.less-equal-font .b-font:before {
+ content: "\e636";
+ color: inherit;
+}
+.less-equal-font:hover .b-font:before,
+.less-equal-font:focus .b-font:before,
+.less-equal-font.hover .b-font:before {
+ content: "\e636";
+ color: inherit;
+}
+.less-equal-font:active .b-font:before,
+.less-equal-font.active .b-font:before {
+ content: "\e636";
+ color: #3f8ce8;
+}
+.less-equal-font.native .b-font:before,
+.less-equal-font.disabled .b-font:before {
+ content: "\e636";
color: inherit;
}
.tree-collapse-icon-type1 .x-icon,
@@ -839,6 +872,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-1.png');
_background: none;
}
+.tree-collapse-icon-type1 .x-icon.hack,
+.tree-collapse-icon-type1:hover .x-icon.hack,
+.tree-collapse-icon-type1:active .x-icon.hack {
+ background: url('icon/tree-collapse-1.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-1.png');
+ _background: none;
+}
.tree-collapse-icon-type1.native .x-icon,
.tree-collapse-icon-type1.disabled .x-icon {
display: block;
@@ -846,6 +886,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-1.png');
_background: none;
}
+.tree-collapse-icon-type1.native .x-icon.hack,
+.tree-collapse-icon-type1.disabled .x-icon.hack {
+ background: url('icon/tree-collapse-1.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-1.png');
+ _background: none;
+}
.tree-collapse-icon-type2 .x-icon,
.tree-collapse-icon-type2:hover .x-icon,
.tree-collapse-icon-type2:active .x-icon {
@@ -854,6 +900,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-2.png');
_background: none;
}
+.tree-collapse-icon-type2 .x-icon.hack,
+.tree-collapse-icon-type2:hover .x-icon.hack,
+.tree-collapse-icon-type2:active .x-icon.hack {
+ background: url('icon/tree-collapse-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-2.png');
+ _background: none;
+}
.tree-collapse-icon-type2.native .x-icon,
.tree-collapse-icon-type2.disabled .x-icon {
display: block;
@@ -861,6 +914,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-2.png');
_background: none;
}
+.tree-collapse-icon-type2.native .x-icon.hack,
+.tree-collapse-icon-type2.disabled .x-icon.hack {
+ background: url('icon/tree-collapse-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-2.png');
+ _background: none;
+}
.tree-collapse-icon-type3 .x-icon,
.tree-collapse-icon-type3:hover .x-icon,
.tree-collapse-icon-type3:active .x-icon {
@@ -869,6 +928,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-3.png');
_background: none;
}
+.tree-collapse-icon-type3 .x-icon.hack,
+.tree-collapse-icon-type3:hover .x-icon.hack,
+.tree-collapse-icon-type3:active .x-icon.hack {
+ background: url('icon/tree-collapse-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-3.png');
+ _background: none;
+}
.tree-collapse-icon-type3.native .x-icon,
.tree-collapse-icon-type3.disabled .x-icon {
display: block;
@@ -876,6 +942,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-3.png');
_background: none;
}
+.tree-collapse-icon-type3.native .x-icon.hack,
+.tree-collapse-icon-type3.disabled .x-icon.hack {
+ background: url('icon/tree-collapse-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-3.png');
+ _background: none;
+}
.tree-collapse-icon-type4 .x-icon,
.tree-collapse-icon-type4:hover .x-icon,
.tree-collapse-icon-type4:active .x-icon {
@@ -884,6 +956,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-4.png');
_background: none;
}
+.tree-collapse-icon-type4 .x-icon.hack,
+.tree-collapse-icon-type4:hover .x-icon.hack,
+.tree-collapse-icon-type4:active .x-icon.hack {
+ background: url('icon/tree-collapse-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-4.png');
+ _background: none;
+}
.tree-collapse-icon-type4.native .x-icon,
.tree-collapse-icon-type4.disabled .x-icon {
display: block;
@@ -891,6 +970,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-4.png');
_background: none;
}
+.tree-collapse-icon-type4.native .x-icon.hack,
+.tree-collapse-icon-type4.disabled .x-icon.hack {
+ background: url('icon/tree-collapse-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-4.png');
+ _background: none;
+}
.tree-expand-icon-type1 .x-icon,
.tree-expand-icon-type1:hover .x-icon,
.tree-expand-icon-type1:active .x-icon {
@@ -899,6 +984,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-1.png');
_background: none;
}
+.tree-expand-icon-type1 .x-icon.hack,
+.tree-expand-icon-type1:hover .x-icon.hack,
+.tree-expand-icon-type1:active .x-icon.hack {
+ background: url('icon/tree-expand-1.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-1.png');
+ _background: none;
+}
.tree-expand-icon-type1.native .x-icon,
.tree-expand-icon-type1.disabled .x-icon {
display: block;
@@ -906,6 +998,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-1.png');
_background: none;
}
+.tree-expand-icon-type1.native .x-icon.hack,
+.tree-expand-icon-type1.disabled .x-icon.hack {
+ background: url('icon/tree-expand-1.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-1.png');
+ _background: none;
+}
.tree-expand-icon-type2 .x-icon,
.tree-expand-icon-type2:hover .x-icon,
.tree-expand-icon-type2:active .x-icon {
@@ -914,6 +1012,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-2.png');
_background: none;
}
+.tree-expand-icon-type2 .x-icon.hack,
+.tree-expand-icon-type2:hover .x-icon.hack,
+.tree-expand-icon-type2:active .x-icon.hack {
+ background: url('icon/tree-expand-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-2.png');
+ _background: none;
+}
.tree-expand-icon-type2.native .x-icon,
.tree-expand-icon-type2.disabled .x-icon {
display: block;
@@ -921,6 +1026,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-2.png');
_background: none;
}
+.tree-expand-icon-type2.native .x-icon.hack,
+.tree-expand-icon-type2.disabled .x-icon.hack {
+ background: url('icon/tree-expand-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-2.png');
+ _background: none;
+}
.tree-expand-icon-type3 .x-icon,
.tree-expand-icon-type3:hover .x-icon,
.tree-expand-icon-type3:active .x-icon {
@@ -929,6 +1040,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-3.png');
_background: none;
}
+.tree-expand-icon-type3 .x-icon.hack,
+.tree-expand-icon-type3:hover .x-icon.hack,
+.tree-expand-icon-type3:active .x-icon.hack {
+ background: url('icon/tree-expand-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-3.png');
+ _background: none;
+}
.tree-expand-icon-type3.native .x-icon,
.tree-expand-icon-type3.disabled .x-icon {
display: block;
@@ -936,6 +1054,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-3.png');
_background: none;
}
+.tree-expand-icon-type3.native .x-icon.hack,
+.tree-expand-icon-type3.disabled .x-icon.hack {
+ background: url('icon/tree-expand-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-3.png');
+ _background: none;
+}
.tree-expand-icon-type4 .x-icon,
.tree-expand-icon-type4:hover .x-icon,
.tree-expand-icon-type4:active .x-icon {
@@ -944,6 +1068,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-4.png');
_background: none;
}
+.tree-expand-icon-type4 .x-icon.hack,
+.tree-expand-icon-type4:hover .x-icon.hack,
+.tree-expand-icon-type4:active .x-icon.hack {
+ background: url('icon/tree-expand-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-4.png');
+ _background: none;
+}
.tree-expand-icon-type4.native .x-icon,
.tree-expand-icon-type4.disabled .x-icon {
display: block;
@@ -951,6 +1082,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-4.png');
_background: none;
}
+.tree-expand-icon-type4.native .x-icon.hack,
+.tree-expand-icon-type4.disabled .x-icon.hack {
+ background: url('icon/tree-expand-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-4.png');
+ _background: none;
+}
.tree-vertical-line-type2 .x-icon,
.tree-vertical-line-type2:hover .x-icon,
.tree-vertical-line-type2:active .x-icon {
@@ -959,6 +1096,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-2.png');
_background: none;
}
+.tree-vertical-line-type2 .x-icon.hack,
+.tree-vertical-line-type2:hover .x-icon.hack,
+.tree-vertical-line-type2:active .x-icon.hack {
+ background: url('icon/tree-vertical-line-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-2.png');
+ _background: none;
+}
.tree-vertical-line-type2.native .x-icon,
.tree-vertical-line-type2.disabled .x-icon {
display: block;
@@ -966,6 +1110,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-2.png');
_background: none;
}
+.tree-vertical-line-type2.native .x-icon.hack,
+.tree-vertical-line-type2.disabled .x-icon.hack {
+ background: url('icon/tree-vertical-line-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-2.png');
+ _background: none;
+}
.tree-vertical-line-type3 .x-icon,
.tree-vertical-line-type3:hover .x-icon,
.tree-vertical-line-type3:active .x-icon {
@@ -974,6 +1124,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-3.png');
_background: none;
}
+.tree-vertical-line-type3 .x-icon.hack,
+.tree-vertical-line-type3:hover .x-icon.hack,
+.tree-vertical-line-type3:active .x-icon.hack {
+ background: url('icon/tree-vertical-line-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-3.png');
+ _background: none;
+}
.tree-vertical-line-type3.native .x-icon,
.tree-vertical-line-type3.disabled .x-icon {
display: block;
@@ -981,6 +1138,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-3.png');
_background: none;
}
+.tree-vertical-line-type3.native .x-icon.hack,
+.tree-vertical-line-type3.disabled .x-icon.hack {
+ background: url('icon/tree-vertical-line-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-3.png');
+ _background: none;
+}
.tree-vertical-line-type4 .x-icon,
.tree-vertical-line-type4:hover .x-icon,
.tree-vertical-line-type4:active .x-icon {
@@ -989,6 +1152,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-4.png');
_background: none;
}
+.tree-vertical-line-type4 .x-icon.hack,
+.tree-vertical-line-type4:hover .x-icon.hack,
+.tree-vertical-line-type4:active .x-icon.hack {
+ background: url('icon/tree-vertical-line-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-4.png');
+ _background: none;
+}
.tree-vertical-line-type4.native .x-icon,
.tree-vertical-line-type4.disabled .x-icon {
display: block;
@@ -996,6 +1166,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-4.png');
_background: none;
}
+.tree-vertical-line-type4.native .x-icon.hack,
+.tree-vertical-line-type4.disabled .x-icon.hack {
+ background: url('icon/tree-vertical-line-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-4.png');
+ _background: none;
+}
.bi-theme-dark .tree-collapse-icon-type1 .x-icon,
.bi-theme-dark .tree-collapse-icon-type1:hover .x-icon,
.bi-theme-dark .tree-collapse-icon-type1:active .x-icon {
@@ -1004,6 +1180,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-1.png');
_background: none;
}
+.bi-theme-dark .tree-collapse-icon-type1 .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type1:hover .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type1:active .x-icon.hack {
+ background: url('icon/dark/tree-collapse-1.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-1.png');
+ _background: none;
+}
.bi-theme-dark .tree-collapse-icon-type1.native .x-icon,
.bi-theme-dark .tree-collapse-icon-type1.disabled .x-icon {
display: block;
@@ -1011,6 +1194,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-1.png');
_background: none;
}
+.bi-theme-dark .tree-collapse-icon-type1.native .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type1.disabled .x-icon.hack {
+ background: url('icon/dark/tree-collapse-1.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-1.png');
+ _background: none;
+}
.bi-theme-dark .tree-collapse-icon-type2 .x-icon,
.bi-theme-dark .tree-collapse-icon-type2:hover .x-icon,
.bi-theme-dark .tree-collapse-icon-type2:active .x-icon {
@@ -1019,6 +1208,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-2.png');
_background: none;
}
+.bi-theme-dark .tree-collapse-icon-type2 .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type2:hover .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type2:active .x-icon.hack {
+ background: url('icon/dark/tree-collapse-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-2.png');
+ _background: none;
+}
.bi-theme-dark .tree-collapse-icon-type2.native .x-icon,
.bi-theme-dark .tree-collapse-icon-type2.disabled .x-icon {
display: block;
@@ -1026,6 +1222,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-2.png');
_background: none;
}
+.bi-theme-dark .tree-collapse-icon-type2.native .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type2.disabled .x-icon.hack {
+ background: url('icon/dark/tree-collapse-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-2.png');
+ _background: none;
+}
.bi-theme-dark .tree-collapse-icon-type3 .x-icon,
.bi-theme-dark .tree-collapse-icon-type3:hover .x-icon,
.bi-theme-dark .tree-collapse-icon-type3:active .x-icon {
@@ -1034,6 +1236,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-3.png');
_background: none;
}
+.bi-theme-dark .tree-collapse-icon-type3 .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type3:hover .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type3:active .x-icon.hack {
+ background: url('icon/dark/tree-collapse-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-3.png');
+ _background: none;
+}
.bi-theme-dark .tree-collapse-icon-type3.native .x-icon,
.bi-theme-dark .tree-collapse-icon-type3.disabled .x-icon {
display: block;
@@ -1041,6 +1250,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-3.png');
_background: none;
}
+.bi-theme-dark .tree-collapse-icon-type3.native .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type3.disabled .x-icon.hack {
+ background: url('icon/dark/tree-collapse-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-3.png');
+ _background: none;
+}
.bi-theme-dark .tree-collapse-icon-type4 .x-icon,
.bi-theme-dark .tree-collapse-icon-type4:hover .x-icon,
.bi-theme-dark .tree-collapse-icon-type4:active .x-icon {
@@ -1049,6 +1264,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-4.png');
_background: none;
}
+.bi-theme-dark .tree-collapse-icon-type4 .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type4:hover .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type4:active .x-icon.hack {
+ background: url('icon/dark/tree-collapse-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-4.png');
+ _background: none;
+}
.bi-theme-dark .tree-collapse-icon-type4.native .x-icon,
.bi-theme-dark .tree-collapse-icon-type4.disabled .x-icon {
display: block;
@@ -1056,6 +1278,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-4.png');
_background: none;
}
+.bi-theme-dark .tree-collapse-icon-type4.native .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type4.disabled .x-icon.hack {
+ background: url('icon/dark/tree-collapse-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-4.png');
+ _background: none;
+}
.bi-theme-dark .tree-expand-icon-type1 .x-icon,
.bi-theme-dark .tree-expand-icon-type1:hover .x-icon,
.bi-theme-dark .tree-expand-icon-type1:active .x-icon {
@@ -1064,6 +1292,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-1.png');
_background: none;
}
+.bi-theme-dark .tree-expand-icon-type1 .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type1:hover .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type1:active .x-icon.hack {
+ background: url('icon/dark/tree-expand-1.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-1.png');
+ _background: none;
+}
.bi-theme-dark .tree-expand-icon-type1.native .x-icon,
.bi-theme-dark .tree-expand-icon-type1.disabled .x-icon {
display: block;
@@ -1071,6 +1306,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-1.png');
_background: none;
}
+.bi-theme-dark .tree-expand-icon-type1.native .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type1.disabled .x-icon.hack {
+ background: url('icon/dark/tree-expand-1.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-1.png');
+ _background: none;
+}
.bi-theme-dark .tree-expand-icon-type2 .x-icon,
.bi-theme-dark .tree-expand-icon-type2:hover .x-icon,
.bi-theme-dark .tree-expand-icon-type2:active .x-icon {
@@ -1079,6 +1320,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-2.png');
_background: none;
}
+.bi-theme-dark .tree-expand-icon-type2 .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type2:hover .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type2:active .x-icon.hack {
+ background: url('icon/dark/tree-expand-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-2.png');
+ _background: none;
+}
.bi-theme-dark .tree-expand-icon-type2.native .x-icon,
.bi-theme-dark .tree-expand-icon-type2.disabled .x-icon {
display: block;
@@ -1086,6 +1334,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-2.png');
_background: none;
}
+.bi-theme-dark .tree-expand-icon-type2.native .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type2.disabled .x-icon.hack {
+ background: url('icon/dark/tree-expand-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-2.png');
+ _background: none;
+}
.bi-theme-dark .tree-expand-icon-type3 .x-icon,
.bi-theme-dark .tree-expand-icon-type3:hover .x-icon,
.bi-theme-dark .tree-expand-icon-type3:active .x-icon {
@@ -1094,6 +1348,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-3.png');
_background: none;
}
+.bi-theme-dark .tree-expand-icon-type3 .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type3:hover .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type3:active .x-icon.hack {
+ background: url('icon/dark/tree-expand-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-3.png');
+ _background: none;
+}
.bi-theme-dark .tree-expand-icon-type3.native .x-icon,
.bi-theme-dark .tree-expand-icon-type3.disabled .x-icon {
display: block;
@@ -1101,6 +1362,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-3.png');
_background: none;
}
+.bi-theme-dark .tree-expand-icon-type3.native .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type3.disabled .x-icon.hack {
+ background: url('icon/dark/tree-expand-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-3.png');
+ _background: none;
+}
.bi-theme-dark .tree-expand-icon-type4 .x-icon,
.bi-theme-dark .tree-expand-icon-type4:hover .x-icon,
.bi-theme-dark .tree-expand-icon-type4:active .x-icon {
@@ -1109,6 +1376,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-4.png');
_background: none;
}
+.bi-theme-dark .tree-expand-icon-type4 .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type4:hover .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type4:active .x-icon.hack {
+ background: url('icon/dark/tree-expand-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-4.png');
+ _background: none;
+}
.bi-theme-dark .tree-expand-icon-type4.native .x-icon,
.bi-theme-dark .tree-expand-icon-type4.disabled .x-icon {
display: block;
@@ -1116,6 +1390,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-4.png');
_background: none;
}
+.bi-theme-dark .tree-expand-icon-type4.native .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type4.disabled .x-icon.hack {
+ background: url('icon/dark/tree-expand-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-4.png');
+ _background: none;
+}
.bi-theme-dark .tree-vertical-line-type2 .x-icon,
.bi-theme-dark .tree-vertical-line-type2:hover .x-icon,
.bi-theme-dark .tree-vertical-line-type2:active .x-icon {
@@ -1124,6 +1404,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-2.png');
_background: none;
}
+.bi-theme-dark .tree-vertical-line-type2 .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type2:hover .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type2:active .x-icon.hack {
+ background: url('icon/dark/tree-vertical-line-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-2.png');
+ _background: none;
+}
.bi-theme-dark .tree-vertical-line-type2.native .x-icon,
.bi-theme-dark .tree-vertical-line-type2.disabled .x-icon {
display: block;
@@ -1131,6 +1418,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-2.png');
_background: none;
}
+.bi-theme-dark .tree-vertical-line-type2.native .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type2.disabled .x-icon.hack {
+ background: url('icon/dark/tree-vertical-line-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-2.png');
+ _background: none;
+}
.bi-theme-dark .tree-vertical-line-type3 .x-icon,
.bi-theme-dark .tree-vertical-line-type3:hover .x-icon,
.bi-theme-dark .tree-vertical-line-type3:active .x-icon {
@@ -1139,6 +1432,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-3.png');
_background: none;
}
+.bi-theme-dark .tree-vertical-line-type3 .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type3:hover .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type3:active .x-icon.hack {
+ background: url('icon/dark/tree-vertical-line-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-3.png');
+ _background: none;
+}
.bi-theme-dark .tree-vertical-line-type3.native .x-icon,
.bi-theme-dark .tree-vertical-line-type3.disabled .x-icon {
display: block;
@@ -1146,6 +1446,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-3.png');
_background: none;
}
+.bi-theme-dark .tree-vertical-line-type3.native .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type3.disabled .x-icon.hack {
+ background: url('icon/dark/tree-vertical-line-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-3.png');
+ _background: none;
+}
.bi-theme-dark .tree-vertical-line-type4 .x-icon,
.bi-theme-dark .tree-vertical-line-type4:hover .x-icon,
.bi-theme-dark .tree-vertical-line-type4:active .x-icon {
@@ -1154,6 +1460,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-4.png');
_background: none;
}
+.bi-theme-dark .tree-vertical-line-type4 .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type4:hover .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type4:active .x-icon.hack {
+ background: url('icon/dark/tree-vertical-line-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-4.png');
+ _background: none;
+}
.bi-theme-dark .tree-vertical-line-type4.native .x-icon,
.bi-theme-dark .tree-vertical-line-type4.disabled .x-icon {
display: block;
@@ -1161,12 +1474,23 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-4.png');
_background: none;
}
+.bi-theme-dark .tree-vertical-line-type4.native .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type4.disabled .x-icon.hack {
+ background: url('icon/dark/tree-vertical-line-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-4.png');
+ _background: none;
+}
.check-box-icon .x-icon {
display: block;
background: url('icon/check-box-normal.png') no-repeat 0 0;
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-normal.png');
_background: none;
}
+.check-box-icon .x-icon.hack {
+ background: url('icon/check-box-normal.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-normal.png');
+ _background: none;
+}
.check-box-icon:hover .x-icon,
.check-box-icon:focus .x-icon,
.check-box-icon.hover .x-icon {
@@ -1175,6 +1499,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-normal.png');
_background: none;
}
+.check-box-icon:hover .x-icon.hack,
+.check-box-icon:focus .x-icon.hack,
+.check-box-icon.hover .x-icon.hack {
+ background: url('icon/check-box-normal.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-normal.png');
+ _background: none;
+}
.check-box-icon:active .x-icon,
.check-box-icon.active .x-icon {
display: block;
@@ -1182,6 +1513,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-active.png');
_background: none;
}
+.check-box-icon:active .x-icon.hack,
+.check-box-icon.active .x-icon.hack {
+ background: url('icon/check-box-active.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-active.png');
+ _background: none;
+}
.check-box-icon.native .x-icon,
.check-box-icon.disabled .x-icon {
display: block;
@@ -1189,6 +1526,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-disable.png');
_background: none;
}
+.check-box-icon.native .x-icon.hack,
+.check-box-icon.disabled .x-icon.hack {
+ background: url('icon/check-box-disable.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-disable.png');
+ _background: none;
+}
.check-box-icon.native .x-icon,
.check-box-icon.disabled.active .x-icon {
display: block;
@@ -1196,12 +1539,23 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-disable2.png');
_background: none;
}
+.check-box-icon.native .x-icon.hack,
+.check-box-icon.disabled.active .x-icon.hack {
+ background: url('icon/check-box-disable2.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-disable2.png');
+ _background: none;
+}
.radio-icon .x-icon {
display: block;
background: url('icon/radio-normal.png') no-repeat 0 0;
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-normal.png');
_background: none;
}
+.radio-icon .x-icon.hack {
+ background: url('icon/radio-normal.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-normal.png');
+ _background: none;
+}
.radio-icon:hover .x-icon,
.radio-icon:focus .x-icon,
.radio-icon.hover .x-icon {
@@ -1210,6 +1564,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-normal.png');
_background: none;
}
+.radio-icon:hover .x-icon.hack,
+.radio-icon:focus .x-icon.hack,
+.radio-icon.hover .x-icon.hack {
+ background: url('icon/radio-normal.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-normal.png');
+ _background: none;
+}
.radio-icon:active .x-icon,
.radio-icon.active .x-icon {
display: block;
@@ -1217,6 +1578,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-active.png');
_background: none;
}
+.radio-icon:active .x-icon.hack,
+.radio-icon.active .x-icon.hack {
+ background: url('icon/radio-active.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-active.png');
+ _background: none;
+}
.radio-icon.native .x-icon,
.radio-icon.disabled .x-icon {
display: block;
@@ -1224,6 +1591,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-disable.png');
_background: none;
}
+.radio-icon.native .x-icon.hack,
+.radio-icon.disabled .x-icon.hack {
+ background: url('icon/radio-disable.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-disable.png');
+ _background: none;
+}
.radio-icon.native .x-icon,
.radio-icon.disabled.active .x-icon {
display: block;
@@ -1231,6 +1604,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-disable2.png');
_background: none;
}
+.radio-icon.native .x-icon.hack,
+.radio-icon.disabled.active .x-icon.hack {
+ background: url('icon/radio-disable2.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-disable2.png');
+ _background: none;
+}
.check-half-select-icon .x-icon,
.check-half-select-icon:hover .x-icon,
.check-half-select-icon:active .x-icon {
@@ -1239,6 +1618,13 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/half_selected.png');
_background: none;
}
+.check-half-select-icon .x-icon.hack,
+.check-half-select-icon:hover .x-icon.hack,
+.check-half-select-icon:active .x-icon.hack {
+ background: url('icon/half_selected.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/half_selected.png');
+ _background: none;
+}
.check-half-select-icon.native .x-icon,
.check-half-select-icon.disabled .x-icon {
display: block;
@@ -1246,6 +1632,12 @@ textarea::-webkit-scrollbar-thumb:hover {
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/half_selected.png');
_background: none;
}
+.check-half-select-icon.native .x-icon.hack,
+.check-half-select-icon.disabled .x-icon.hack {
+ background: url('icon/half_selected.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/half_selected.png');
+ _background: none;
+}
/**
* Farbtastic Color Picker 1.2
* © 2008 Steven Wittens
diff --git a/docs/widget.js b/docs/widget.js
index 8061cc712..9799dd01a 100644
--- a/docs/widget.js
+++ b/docs/widget.js
@@ -629,7 +629,12 @@ BI.AdaptiveArrangement = BI.inherit(BI.Widget, {
clearInterval(self._scrollInterval);
self._scrollInterval = null;
}
+ var count = 0;
self._scrollInterval = setInterval(function () {
+ count++;
+ if (count <= 3) {
+ return;
+ }
var offset = self._getScrollOffset();
var t = offset.top + map[direction][0] * 40;
var l = offset.left + map[direction][1] * 40;
@@ -2613,22 +2618,23 @@ BI.DateCalendarPopup = BI.inherit(BI.Widget, {
month: date.month,
day: this.selectedTime.day
});
- return calendar;
+ return calendar
},
_init: function () {
BI.DateCalendarPopup.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
+ var self = this,
+ o = this.options;
this.today = new Date();
this._year = this.today.getFullYear();
this._month = this.today.getMonth();
this._day = this.today.getDate();
this.selectedTime = o.selectedTime || {
- year: this._year,
- month: this._month,
- day: this._day
- };
+ year: this._year,
+ month: this._month,
+ day: this._day
+ };
this.datePicker = BI.createWidget({
type: "bi.date_picker",
min: o.min,
@@ -2764,7 +2770,8 @@ BI.DateCombo = BI.inherit(BI.Widget, {
},
_init: function () {
BI.DateCombo.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
+ var self = this,
+ o = this.options;
this.trigger = BI.createWidget({
type: "bi.date_trigger"
@@ -5292,7 +5299,7 @@ BI.FileManagerNavButton = BI.inherit(BI.Widget, {
_const: {
normal_color: "#ffffff",
- select_color: "#f4f4f4"
+ select_color: "#eff1f4"
},
_defaultConfig: function () {
return BI.extend(BI.FileManagerNavButton.superclass._defaultConfig.apply(this, arguments), {
diff --git a/src/base/formula/formulaeditor.js b/src/base/formula/formulaeditor.js
index 74da71433..691e8b0e8 100644
--- a/src/base/formula/formulaeditor.js
+++ b/src/base/formula/formulaeditor.js
@@ -90,15 +90,15 @@ BI.FormulaEditor = BI.inherit(BI.Single, {
_checkWaterMark: function () {
var o = this.options;
- if (!this.disabledWarterMark && BI.isEmptyString(this.editor.getValue()) && BI.isKey(o.watermark)) {
+ if (!this.disabledWaterMark && BI.isEmptyString(this.editor.getValue()) && BI.isKey(o.watermark)) {
this.watermark && this.watermark.visible();
} else {
this.watermark && this.watermark.invisible();
}
},
- disableWarterMark: function () {
- this.disabledWarterMark = true;
+ disableWaterMark: function () {
+ this.disabledWaterMark = true;
this._checkWaterMark();
},
diff --git a/src/base/single/editor/editor.js b/src/base/single/editor/editor.js
index a0a684474..c03bd8005 100644
--- a/src/base/single/editor/editor.js
+++ b/src/base/single/editor/editor.js
@@ -204,7 +204,7 @@ BI.Editor = BI.inherit(BI.Single, {
_checkWaterMark: function () {
var o = this.options;
- if (!this.disabledWarterMark && this.editor.getValue() === "" && BI.isKey(o.watermark)) {
+ if (!this.disabledWaterMark && this.editor.getValue() === "" && BI.isKey(o.watermark)) {
this.watermark && this.watermark.visible();
} else {
this.watermark && this.watermark.invisible();
@@ -242,13 +242,13 @@ BI.Editor = BI.inherit(BI.Single, {
this._checkError();
},
- disableWarterMark: function () {
- this.disabledWarterMark = true;
+ disableWaterMark: function () {
+ this.disabledWaterMark = true;
this._checkWaterMark();
},
- enableWarterMark: function () {
- this.disabledWarterMark = false;
+ enableWaterMark: function () {
+ this.disabledWaterMark = false;
this._checkWaterMark();
},
diff --git a/src/base/single/icon/icon.js b/src/base/single/icon/icon.js
index 58810343c..51804c51c 100644
--- a/src/base/single/icon/icon.js
+++ b/src/base/single/icon/icon.js
@@ -13,6 +13,9 @@ BI.Icon = BI.inherit(BI.Single, {
},
_init: function () {
BI.Icon.superclass._init.apply(this, arguments);
+ if (BI.isIE9Below()) {
+ this.element.addClass("hack");
+ }
}
});
BI.shortcut("bi.icon", BI.Icon);
\ No newline at end of file
diff --git a/src/base/table/table.grid.js b/src/base/table/table.grid.js
index 1eae8487b..c18baa2ef 100644
--- a/src/base/table/table.grid.js
+++ b/src/base/table/table.grid.js
@@ -362,6 +362,41 @@ BI.GridTable = BI.inherit(BI.Widget, {
this.contextLayout.attr("items", items);
this.contextLayout.resize();
+ this.topLeftGrid.attr({
+ overscanColumnCount: 0,
+ overscanRowCount: 0
+ });
+ this.topRightGrid.attr({
+ overscanColumnCount: 0,
+ overscanRowCount: 0
+ });
+ this.bottomLeftGrid.attr({
+ overscanColumnCount: 0,
+ overscanRowCount: 0
+ });
+ this.bottomRightGrid.attr({
+ overscanColumnCount: 0,
+ overscanRowCount: 0
+ });
+
+ function overscan(grid, w, h, rSize, cSize) {
+ var rCount = h / rSize;
+ var cCount = w / cSize;
+ if (cCount * (120 / rSize) >= 60 || rCount * (120 / cSize) >= 60) {
+ grid.attr("overscanRowCount", 100);
+ grid.attr("overscanColumnCount", 100);
+ }
+ }
+
+ if (freezeColLength > 0) {
+ overscan(this.topLeftGrid, tlw, tlh, o.headerRowSize, totalLeftColumnSize / freezeColLength);
+ overscan(this.bottomLeftGrid, blw, blh, o.rowSize, totalLeftColumnSize / freezeColLength);
+ }
+ if (o.columnSize.length - freezeColLength > 0) {
+ overscan(this.topRight, trw, trh, o.headerRowSize, totalRightColumnSize / (o.columnSize.length - freezeColLength));
+ overscan(this.bottomRightGrid, brw, brh, o.rowSize, totalRightColumnSize / (o.columnSize.length - freezeColLength));
+ }
+
this.topLeftGrid._populate(this.header[0]);
this.topRightGrid._populate(this.header[1]);
this.bottomLeftGrid._populate(this.items[0]);
diff --git a/src/base/table/table.grid.quick.js b/src/base/table/table.grid.quick.js
index 878f1bcd2..c5c98a337 100644
--- a/src/base/table/table.grid.quick.js
+++ b/src/base/table/table.grid.quick.js
@@ -116,7 +116,8 @@ BI.QuickGridTable = BI.inherit(BI.GridTable, {
_populateTable: function () {
var self = this, o = this.options;
- var regionSize = this.getRegionSize(), totalLeftColumnSize = 0, totalRightColumnSize = 0, totalColumnSize = 0, summaryColumnSizeArray = [];
+ var regionSize = this.getRegionSize(), totalLeftColumnSize = 0, totalRightColumnSize = 0, totalColumnSize = 0,
+ summaryColumnSizeArray = [];
var freezeColLength = this._getFreezeColLength();
BI.each(o.columnSize, function (i, size) {
if (o.isNeedFreeze === true && o.freezeCols.contains(i)) {
@@ -207,6 +208,42 @@ BI.QuickGridTable = BI.inherit(BI.GridTable, {
}
});
});
+
+ this.topLeftGrid.attr({
+ overscanColumnCount: 0,
+ overscanRowCount: 0
+ });
+ this.topRightGrid.attr({
+ overscanColumnCount: 0,
+ overscanRowCount: 0
+ });
+ this.bottomLeftGrid.attr({
+ overscanColumnCount: 0,
+ overscanRowCount: 0
+ });
+ this.bottomRightGrid.attr({
+ overscanColumnCount: 0,
+ overscanRowCount: 0
+ });
+
+ function overscan(grid, w, h, rSize, cSize) {
+ var rCount = h / rSize;
+ var cCount = w / cSize;
+ if (cCount * (120 / rSize) >= 60 || rCount * (120 / cSize) >= 60) {
+ grid.attr("overscanRowCount", 100);
+ grid.attr("overscanColumnCount", 100);
+ }
+ }
+
+ if (freezeColLength > 0) {
+ overscan(this.topLeftGrid, otlw, otlh, o.headerRowSize, totalLeftColumnSize / freezeColLength);
+ overscan(this.bottomLeftGrid, oblw, oblh, o.rowSize, totalLeftColumnSize / freezeColLength);
+ }
+ if (o.columnSize.length - freezeColLength > 0) {
+ overscan(this.topRight, otrw, otrh, o.headerRowSize, totalRightColumnSize / (o.columnSize.length - freezeColLength));
+ overscan(this.bottomRightGrid, obrw, obrh, o.rowSize, totalRightColumnSize / (o.columnSize.length - freezeColLength));
+ }
+
this.topLeftGrid.populate(leftHeader);
this.topRightGrid.populate(rightHeader);
this.bottomLeftGrid.populate(leftItems);
diff --git a/src/base/table/table.js b/src/base/table/table.js
index d112163b8..ed638eb05 100644
--- a/src/base/table/table.js
+++ b/src/base/table/table.js
@@ -418,8 +418,8 @@ BI.Table = BI.inherit(BI.Widget, {
var isNeedMergeCol = o.mergeRule(map[i][j], map[i][j - 1]);
if (isNeedMergeCol === true) {
mergeCol(i, j);
- preCol[j] = preRow[j - 1];
- preCW[j] = preRW[j - 1];
+ preCol[j] = preRow[i];
+ preCW[j] = preRW[i];
} else {
createOneEl(i, j);
}
diff --git a/src/case/editor/editor.sign.initial.js b/src/case/editor/editor.sign.initial.js
index fd73ca179..098fa8877 100644
--- a/src/case/editor/editor.sign.initial.js
+++ b/src/case/editor/editor.sign.initial.js
@@ -1,7 +1,5 @@
/**
- * sign是新值(初始value值)形式的自适应宽度的输入框
- * @class BI.SignInitialEditor
- * @extends BI.Single
+ * Created by User on 2017/7/28.
*/
BI.SignInitialEditor = BI.inherit(BI.Widget, {
_defaultConfig: function () {
@@ -30,8 +28,7 @@ BI.SignInitialEditor = BI.inherit(BI.Widget, {
BI.SignInitialEditor.superclass._init.apply(this, arguments);
var self = this, o = this.options;
this.editor = BI.createWidget({
- type: "bi.sign_editor",
- element: this,
+ type: "bi.editor",
height: o.height,
hgap: o.hgap,
vgap: o.vgap,
@@ -39,7 +36,7 @@ BI.SignInitialEditor = BI.inherit(BI.Widget, {
rgap: o.rgap,
tgap: o.tgap,
bgap: o.bgap,
- value: o.value || o.text,
+ value: o.value,
validationChecker: o.validationChecker,
quitChecker: o.quitChecker,
mouseOut: o.mouseOut,
@@ -47,67 +44,163 @@ BI.SignInitialEditor = BI.inherit(BI.Widget, {
watermark: o.watermark,
errorText: o.errorText
});
- if(BI.isNotNull(o.value)){
- this.setState(o.value);
- }
+ this.text = BI.createWidget({
+ type: "bi.text_button",
+ cls: "sign-editor-text",
+ title: o.title,
+ warningTitle: o.warningTitle,
+ tipType: o.tipType,
+ textAlign: "left",
+ height: o.height,
+ hgap: 4,
+ handler: function () {
+ self._showInput();
+ self.editor.focus();
+ self.editor.selectAll();
+ }
+ });
+ this.text.on(BI.TextButton.EVENT_CHANGE, function () {
+ BI.nextTick(function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_CLICK_LABEL)
+ });
+ });
+ BI.createWidget({
+ type: "bi.absolute",
+ element: this,
+ items: [{
+ el: this.text,
+ left: 0,
+ right: 0,
+ top: 0,
+ bottom: 0
+ }]
+ });
this.editor.on(BI.Controller.EVENT_CHANGE, function () {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_FOCUS, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_FOCUS);
+ this.editor.on(BI.Editor.EVENT_FOCUS, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_FOCUS, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_BLUR, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_BLUR);
+ this.editor.on(BI.Editor.EVENT_BLUR, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_BLUR, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_CLICK, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_CLICK);
+ this.editor.on(BI.Editor.EVENT_CLICK, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_CLICK, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_CHANGE, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_CHANGE);
+ this.editor.on(BI.Editor.EVENT_CHANGE, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_CHANGE, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_KEY_DOWN, function (v) {
- self.fireEvent(BI.SignInitialEditor.EVENT_KEY_DOWN);
+ this.editor.on(BI.Editor.EVENT_KEY_DOWN, function (v) {
+ self.fireEvent(BI.SignInitialEditor.EVENT_KEY_DOWN, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_VALID, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_VALID);
+ this.editor.on(BI.Editor.EVENT_VALID, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_VALID, arguments);
+ });
+ this.editor.on(BI.Editor.EVENT_CONFIRM, function () {
+ self._showHint();
+ self._checkText();
+ self.fireEvent(BI.SignInitialEditor.EVENT_CONFIRM, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_CONFIRM, function () {
- self.setState(self.editor.getValue());
- self.fireEvent(BI.SignInitialEditor.EVENT_CONFIRM);
+ this.editor.on(BI.Editor.EVENT_START, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_START, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_START, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_START);
+ this.editor.on(BI.Editor.EVENT_PAUSE, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_PAUSE, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_PAUSE, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_PAUSE);
+ this.editor.on(BI.Editor.EVENT_STOP, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_STOP, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_STOP, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_STOP);
+ this.editor.on(BI.Editor.EVENT_SPACE, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_SPACE, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_SPACE, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_SPACE);
+ this.editor.on(BI.Editor.EVENT_ERROR, function () {
+ self._checkText();
+ self.fireEvent(BI.SignInitialEditor.EVENT_ERROR, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_ERROR, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_ERROR);
+ this.editor.on(BI.Editor.EVENT_ENTER, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_ENTER, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_ENTER, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_ENTER);
+ this.editor.on(BI.Editor.EVENT_RESTRICT, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_RESTRICT, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_RESTRICT, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_RESTRICT);
+ this.editor.on(BI.Editor.EVENT_EMPTY, function () {
+ self.fireEvent(BI.SignInitialEditor.EVENT_EMPTY, arguments);
});
- this.editor.on(BI.SignEditor.EVENT_EMPTY, function () {
- self.fireEvent(BI.SignInitialEditor.EVENT_EMPTY);
+ BI.createWidget({
+ type: "bi.vertical",
+ scrolly: false,
+ element: this,
+ items: [this.editor]
});
+ this._showHint();
+ self._checkText();
+ },
+
+ _checkText: function () {
+ var o = this.options;
+ BI.nextTick(BI.bind(function () {
+ if (this.editor.getValue() === "") {
+ this.text.setValue(o.watermark || "");
+ this.text.element.addClass("bi-water-mark");
+ } else {
+ var v = this.editor.getValue();
+ v = (BI.isEmpty(v) || v == o.text) ? o.text : v + "(" + o.text + ")";
+ this.text.setValue(v);
+ this.text.element.removeClass("bi-water-mark");
+ }
+ }, this));
+ },
+
+ _showInput: function () {
+ this.editor.visible();
+ this.text.invisible();
+ },
+
+ _showHint: function () {
+ this.editor.invisible();
+ this.text.visible();
+ },
+
+ setTitle: function (title) {
+ this.text.setTitle(title);
+ },
+
+ setWarningTitle: function (title) {
+ this.text.setWarningTitle(title);
},
focus: function () {
+ this._showInput();
this.editor.focus();
},
blur: function () {
this.editor.blur();
+ this._showHint();
+ this._checkText();
+ },
+
+ doRedMark: function () {
+ if (this.editor.getValue() === "" && BI.isKey(this.options.watermark)) {
+ return;
+ }
+ this.text.doRedMark.apply(this.text, arguments);
+ },
+
+ unRedMark: function () {
+ this.text.unRedMark.apply(this.text, arguments);
+ },
+
+ doHighLight: function () {
+ if (this.editor.getValue() === "" && BI.isKey(this.options.watermark)) {
+ return;
+ }
+ this.text.doHighLight.apply(this.text, arguments);
+ },
+
+ unHighLight: function () {
+ this.text.unHighLight.apply(this.text, arguments);
},
isValid: function () {
@@ -122,9 +215,19 @@ BI.SignInitialEditor = BI.inherit(BI.Widget, {
return this.editor.getErrorText();
},
+ isEditing: function () {
+ return this.editor.isEditing();
+ },
+
+ getLastValidValue: function () {
+ return this.editor.getLastValidValue();
+ },
+
setValue: function (v) {
+ var o = this.options;
this.editor.setValue(v.value);
- this.setState(v.value);
+ o.text = v.text || o.text;
+ this._checkText();
},
getValue: function () {
@@ -135,13 +238,14 @@ BI.SignInitialEditor = BI.inherit(BI.Widget, {
},
getState: function () {
- return this.editor.getState();
+ return this.text.getValue();
},
setState: function (v) {
var o = this.options;
+ this._showHint();
v = (BI.isEmpty(v) || v == o.text) ? o.text : v + "(" + o.text + ")";
- this.editor.setState(v);
+ this.text.setValue(v);
}
});
BI.SignInitialEditor.EVENT_CHANGE = "EVENT_CHANGE";
diff --git a/src/case/list/list.select.js b/src/case/list/list.select.js
index 26d1297b8..b07cca002 100644
--- a/src/case/list/list.select.js
+++ b/src/case/list/list.select.js
@@ -158,6 +158,11 @@ BI.SelectList = BI.inherit(BI.Widget, {
this._checkAllSelected();
},
+ _setEnable: function (enable) {
+ BI.SelectList.superclass._setEnable.apply(this, arguments);
+ this.toolbar.setEnable(enable);
+ },
+
resetHeight: function (h) {
var toolHeight = ( this.toolbar.element.outerHeight() || 25) * ( this.toolbar.isVisible() ? 1 : 0);
this.list.resetHeight ? this.list.resetHeight(h - toolHeight) :
diff --git a/src/core/base.js b/src/core/base.js
index 35ddfdead..9071f40ba 100644
--- a/src/core/base.js
+++ b/src/core/base.js
@@ -1048,10 +1048,7 @@ if (!window.BI) {
return /(msie|trident)/i.test(navigator.userAgent.toLowerCase());
},
- isIE9Below: function () {
- if (!BI.isIE()) {
- return false;
- }
+ getIEVersion: function () {
var version = 0;
var agent = navigator.userAgent.toLowerCase();
var v1 = agent.match(/(?:msie\s([\w.]+))/);
@@ -1065,7 +1062,18 @@ if (!window.BI) {
} else {
version = 0;
}
- return version < 9;
+ return version;
+ },
+
+ isIE9Below: function () {
+ if (!BI.isIE()) {
+ return false;
+ }
+ return this.getIEVersion() < 9;
+ },
+
+ isIE9: function () {
+ return this.getIEVersion() === 9;
},
isEdge: function () {
diff --git a/src/core/widget.js b/src/core/widget.js
index 62775547e..a7536dcf5 100644
--- a/src/core/widget.js
+++ b/src/core/widget.js
@@ -343,6 +343,13 @@ BI.Widget = BI.inherit(BI.OB, {
},
attr: function (key, value) {
+ var self = this;
+ if (BI.isPlainObject(key)) {
+ BI.each(key, function (k, v) {
+ self.attr(k, v);
+ })
+ return;
+ }
if (BI.isNotNull(value)) {
return this.options[key] = value;
}
diff --git a/src/css/resource/font.css b/src/css/resource/font.css
index fa05dd2da..2ea530085 100644
--- a/src/css/resource/font.css
+++ b/src/css/resource/font.css
@@ -12,7 +12,7 @@
-moz-osx-font-smoothing: grayscale;
}
.close-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.close-font .b-font:before {
content: "\e600";
@@ -24,7 +24,7 @@
color: inherit;
}
.close-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.close-h-font .b-font:before {
content: "\e600";
@@ -42,7 +42,7 @@
color: inherit;
}
.close-ha-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.close-ha-font .b-font:before {
content: "\e600";
@@ -65,7 +65,7 @@
color: inherit;
}
.search-close-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.search-close-h-font .b-font:before {
content: "\e600";
@@ -83,7 +83,7 @@
color: inherit;
}
.pre-page-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.pre-page-h-font .b-font:before {
content: "\e601";
@@ -101,7 +101,7 @@
color: inherit;
}
.next-page-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.next-page-h-font .b-font:before {
content: "\e602";
@@ -119,7 +119,7 @@
color: inherit;
}
.search-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.search-font .b-font:before {
content: "\e604";
@@ -131,7 +131,7 @@
color: inherit;
}
.dot-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.dot-font .b-font:before {
content: "\e606";
@@ -143,7 +143,7 @@
color: #1a1a1a;
}
.dot-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.dot-h-font .b-font:before {
content: "\e606";
@@ -161,7 +161,7 @@
color: #1a1a1a;
}
.dot-ha-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.dot-ha-font .b-font:before {
content: "\e606";
@@ -184,7 +184,7 @@
color: #ffffff;
}
.dot-e-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.dot-e-font .b-font:before {
content: "\e606";
@@ -210,7 +210,7 @@
color: #ffffff;
}
.pull-right-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.pull-right-font .b-font:before {
content: "\e607";
@@ -222,7 +222,7 @@
color: inherit;
}
.pull-right-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.pull-right-h-font .b-font:before {
content: "\e607";
@@ -240,7 +240,7 @@
color: inherit;
}
.pull-right-ha-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.pull-right-ha-font .b-font:before {
content: "\e607";
@@ -263,7 +263,7 @@
color: inherit;
}
.pull-right-e-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.pull-right-e-font .b-font:before {
content: "\e607";
@@ -289,7 +289,7 @@
color: inherit;
}
.copy-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.copy-font .b-font:before {
content: "\e610";
@@ -301,7 +301,7 @@
color: inherit;
}
.copy-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.copy-h-font .b-font:before {
content: "\e610";
@@ -319,7 +319,7 @@
color: #1a1a1a;
}
.copy-ha-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.copy-ha-font .b-font:before {
content: "\e610";
@@ -342,7 +342,7 @@
color: inherit;
}
.copy-e-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.copy-e-font .b-font:before {
content: "\e610";
@@ -368,7 +368,7 @@
color: inherit;
}
.check-mark-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.check-mark-font .b-font:before {
content: "\e611";
@@ -380,7 +380,7 @@
color: inherit;
}
.check-mark-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.check-mark-h-font .b-font:before {
content: "\e611";
@@ -398,7 +398,7 @@
color: inherit;
}
.check-mark-ha-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.check-mark-ha-font .b-font:before {
content: "\e611";
@@ -421,7 +421,7 @@
color: inherit;
}
.check-mark-e-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.check-mark-e-font .b-font:before {
content: "\e611";
@@ -448,7 +448,7 @@
}
/** dashboard组件/控件 下拉列表图标字体 ~end~**/
.tree-node-triangle-expand-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.tree-node-triangle-expand-font .b-font:before {
content: "\e608";
@@ -460,7 +460,7 @@
color: inherit;
}
.tree-node-triangle-collapse-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.tree-node-triangle-collapse-font .b-font:before {
content: "\e607";
@@ -472,7 +472,7 @@
color: inherit;
}
.row-pre-page-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.row-pre-page-h-font .b-font:before {
content: "\e6be";
@@ -490,7 +490,7 @@
color: inherit;
}
.row-next-page-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.row-next-page-h-font .b-font:before {
content: "\e6bd";
@@ -508,7 +508,7 @@
color: inherit;
}
.column-pre-page-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.column-pre-page-h-font .b-font:before {
content: "\e6bc";
@@ -526,7 +526,7 @@
color: inherit;
}
.column-next-page-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.column-next-page-h-font .b-font:before {
content: "\e6bb";
@@ -544,7 +544,7 @@
color: inherit;
}
.trigger-triangle-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.trigger-triangle-font .b-font:before {
content: "\e66a";
@@ -567,7 +567,7 @@
color: #999999;
}
.pull-down-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.pull-down-font .b-font:before {
content: "\e608";
@@ -579,7 +579,7 @@
color: inherit;
}
.pull-down-h-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.pull-down-h-font .b-font:before {
content: "\e608";
@@ -597,7 +597,7 @@
color: inherit;
}
.pull-down-ha-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.pull-down-ha-font .b-font:before {
content: "\e608";
@@ -620,7 +620,7 @@
color: inherit;
}
.check-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.check-font .b-font:before {
content: "\e611";
@@ -632,7 +632,7 @@
color: #3f8ce8;
}
.item-check-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.item-check-font .b-font:before {
content: "\e611";
@@ -655,7 +655,7 @@
color: #ffffff;
}
.primary-key-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = ';');
}
.primary-key-font .b-font:before {
content: "\e67d;";
@@ -673,7 +673,7 @@
color: inherit;
}
.drag-tag-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
.drag-tag-font .b-font:before {
content: "\e600";
@@ -684,16 +684,49 @@
content: "\e600";
color: #f07d0a;
}
-
-.chart-date-normal-font .b-font {
- *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+.less-font .b-font {
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
}
-.chart-date-normal-font .b-font:before {
- content: "\e61b";
+.less-font .b-font:before {
+ content: "\e633";
color: inherit;
}
-.chart-date-normal-font.native .b-font:before,
-.chart-date-normal-font.disabled .b-font:before {
- content: "\e61b";
+.less-font:hover .b-font:before,
+.less-font:focus .b-font:before,
+.less-font.hover .b-font:before {
+ content: "\e633";
+ color: inherit;
+}
+.less-font:active .b-font:before,
+.less-font.active .b-font:before {
+ content: "\e633";
+ color: #3f8ce8;
+}
+.less-font.native .b-font:before,
+.less-font.disabled .b-font:before {
+ content: "\e633";
+ color: inherit;
+}
+.less-equal-font .b-font {
+ *zoom: expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '');
+}
+.less-equal-font .b-font:before {
+ content: "\e636";
+ color: inherit;
+}
+.less-equal-font:hover .b-font:before,
+.less-equal-font:focus .b-font:before,
+.less-equal-font.hover .b-font:before {
+ content: "\e636";
+ color: inherit;
+}
+.less-equal-font:active .b-font:before,
+.less-equal-font.active .b-font:before {
+ content: "\e636";
+ color: #3f8ce8;
+}
+.less-equal-font.native .b-font:before,
+.less-equal-font.disabled .b-font:before {
+ content: "\e636";
color: inherit;
}
diff --git a/src/css/resource/icon.css b/src/css/resource/icon.css
index 0118afa4c..dafa8035e 100644
--- a/src/css/resource/icon.css
+++ b/src/css/resource/icon.css
@@ -6,6 +6,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-1.png');
_background: none;
}
+.tree-collapse-icon-type1 .x-icon.hack,
+.tree-collapse-icon-type1:hover .x-icon.hack,
+.tree-collapse-icon-type1:active .x-icon.hack {
+ background: url('icon/tree-collapse-1.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-1.png');
+ _background: none;
+}
.tree-collapse-icon-type1.native .x-icon,
.tree-collapse-icon-type1.disabled .x-icon {
display: block;
@@ -13,6 +20,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-1.png');
_background: none;
}
+.tree-collapse-icon-type1.native .x-icon.hack,
+.tree-collapse-icon-type1.disabled .x-icon.hack {
+ background: url('icon/tree-collapse-1.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-1.png');
+ _background: none;
+}
.tree-collapse-icon-type2 .x-icon,
.tree-collapse-icon-type2:hover .x-icon,
.tree-collapse-icon-type2:active .x-icon {
@@ -21,6 +34,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-2.png');
_background: none;
}
+.tree-collapse-icon-type2 .x-icon.hack,
+.tree-collapse-icon-type2:hover .x-icon.hack,
+.tree-collapse-icon-type2:active .x-icon.hack {
+ background: url('icon/tree-collapse-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-2.png');
+ _background: none;
+}
.tree-collapse-icon-type2.native .x-icon,
.tree-collapse-icon-type2.disabled .x-icon {
display: block;
@@ -28,6 +48,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-2.png');
_background: none;
}
+.tree-collapse-icon-type2.native .x-icon.hack,
+.tree-collapse-icon-type2.disabled .x-icon.hack {
+ background: url('icon/tree-collapse-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-2.png');
+ _background: none;
+}
.tree-collapse-icon-type3 .x-icon,
.tree-collapse-icon-type3:hover .x-icon,
.tree-collapse-icon-type3:active .x-icon {
@@ -36,6 +62,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-3.png');
_background: none;
}
+.tree-collapse-icon-type3 .x-icon.hack,
+.tree-collapse-icon-type3:hover .x-icon.hack,
+.tree-collapse-icon-type3:active .x-icon.hack {
+ background: url('icon/tree-collapse-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-3.png');
+ _background: none;
+}
.tree-collapse-icon-type3.native .x-icon,
.tree-collapse-icon-type3.disabled .x-icon {
display: block;
@@ -43,6 +76,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-3.png');
_background: none;
}
+.tree-collapse-icon-type3.native .x-icon.hack,
+.tree-collapse-icon-type3.disabled .x-icon.hack {
+ background: url('icon/tree-collapse-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-3.png');
+ _background: none;
+}
.tree-collapse-icon-type4 .x-icon,
.tree-collapse-icon-type4:hover .x-icon,
.tree-collapse-icon-type4:active .x-icon {
@@ -51,6 +90,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-4.png');
_background: none;
}
+.tree-collapse-icon-type4 .x-icon.hack,
+.tree-collapse-icon-type4:hover .x-icon.hack,
+.tree-collapse-icon-type4:active .x-icon.hack {
+ background: url('icon/tree-collapse-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-4.png');
+ _background: none;
+}
.tree-collapse-icon-type4.native .x-icon,
.tree-collapse-icon-type4.disabled .x-icon {
display: block;
@@ -58,6 +104,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-4.png');
_background: none;
}
+.tree-collapse-icon-type4.native .x-icon.hack,
+.tree-collapse-icon-type4.disabled .x-icon.hack {
+ background: url('icon/tree-collapse-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-collapse-4.png');
+ _background: none;
+}
.tree-expand-icon-type1 .x-icon,
.tree-expand-icon-type1:hover .x-icon,
.tree-expand-icon-type1:active .x-icon {
@@ -66,6 +118,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-1.png');
_background: none;
}
+.tree-expand-icon-type1 .x-icon.hack,
+.tree-expand-icon-type1:hover .x-icon.hack,
+.tree-expand-icon-type1:active .x-icon.hack {
+ background: url('icon/tree-expand-1.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-1.png');
+ _background: none;
+}
.tree-expand-icon-type1.native .x-icon,
.tree-expand-icon-type1.disabled .x-icon {
display: block;
@@ -73,6 +132,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-1.png');
_background: none;
}
+.tree-expand-icon-type1.native .x-icon.hack,
+.tree-expand-icon-type1.disabled .x-icon.hack {
+ background: url('icon/tree-expand-1.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-1.png');
+ _background: none;
+}
.tree-expand-icon-type2 .x-icon,
.tree-expand-icon-type2:hover .x-icon,
.tree-expand-icon-type2:active .x-icon {
@@ -81,6 +146,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-2.png');
_background: none;
}
+.tree-expand-icon-type2 .x-icon.hack,
+.tree-expand-icon-type2:hover .x-icon.hack,
+.tree-expand-icon-type2:active .x-icon.hack {
+ background: url('icon/tree-expand-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-2.png');
+ _background: none;
+}
.tree-expand-icon-type2.native .x-icon,
.tree-expand-icon-type2.disabled .x-icon {
display: block;
@@ -88,6 +160,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-2.png');
_background: none;
}
+.tree-expand-icon-type2.native .x-icon.hack,
+.tree-expand-icon-type2.disabled .x-icon.hack {
+ background: url('icon/tree-expand-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-2.png');
+ _background: none;
+}
.tree-expand-icon-type3 .x-icon,
.tree-expand-icon-type3:hover .x-icon,
.tree-expand-icon-type3:active .x-icon {
@@ -96,6 +174,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-3.png');
_background: none;
}
+.tree-expand-icon-type3 .x-icon.hack,
+.tree-expand-icon-type3:hover .x-icon.hack,
+.tree-expand-icon-type3:active .x-icon.hack {
+ background: url('icon/tree-expand-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-3.png');
+ _background: none;
+}
.tree-expand-icon-type3.native .x-icon,
.tree-expand-icon-type3.disabled .x-icon {
display: block;
@@ -103,6 +188,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-3.png');
_background: none;
}
+.tree-expand-icon-type3.native .x-icon.hack,
+.tree-expand-icon-type3.disabled .x-icon.hack {
+ background: url('icon/tree-expand-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-3.png');
+ _background: none;
+}
.tree-expand-icon-type4 .x-icon,
.tree-expand-icon-type4:hover .x-icon,
.tree-expand-icon-type4:active .x-icon {
@@ -111,6 +202,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-4.png');
_background: none;
}
+.tree-expand-icon-type4 .x-icon.hack,
+.tree-expand-icon-type4:hover .x-icon.hack,
+.tree-expand-icon-type4:active .x-icon.hack {
+ background: url('icon/tree-expand-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-4.png');
+ _background: none;
+}
.tree-expand-icon-type4.native .x-icon,
.tree-expand-icon-type4.disabled .x-icon {
display: block;
@@ -118,6 +216,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-4.png');
_background: none;
}
+.tree-expand-icon-type4.native .x-icon.hack,
+.tree-expand-icon-type4.disabled .x-icon.hack {
+ background: url('icon/tree-expand-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-expand-4.png');
+ _background: none;
+}
.tree-vertical-line-type2 .x-icon,
.tree-vertical-line-type2:hover .x-icon,
.tree-vertical-line-type2:active .x-icon {
@@ -126,6 +230,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-2.png');
_background: none;
}
+.tree-vertical-line-type2 .x-icon.hack,
+.tree-vertical-line-type2:hover .x-icon.hack,
+.tree-vertical-line-type2:active .x-icon.hack {
+ background: url('icon/tree-vertical-line-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-2.png');
+ _background: none;
+}
.tree-vertical-line-type2.native .x-icon,
.tree-vertical-line-type2.disabled .x-icon {
display: block;
@@ -133,6 +244,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-2.png');
_background: none;
}
+.tree-vertical-line-type2.native .x-icon.hack,
+.tree-vertical-line-type2.disabled .x-icon.hack {
+ background: url('icon/tree-vertical-line-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-2.png');
+ _background: none;
+}
.tree-vertical-line-type3 .x-icon,
.tree-vertical-line-type3:hover .x-icon,
.tree-vertical-line-type3:active .x-icon {
@@ -141,6 +258,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-3.png');
_background: none;
}
+.tree-vertical-line-type3 .x-icon.hack,
+.tree-vertical-line-type3:hover .x-icon.hack,
+.tree-vertical-line-type3:active .x-icon.hack {
+ background: url('icon/tree-vertical-line-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-3.png');
+ _background: none;
+}
.tree-vertical-line-type3.native .x-icon,
.tree-vertical-line-type3.disabled .x-icon {
display: block;
@@ -148,6 +272,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-3.png');
_background: none;
}
+.tree-vertical-line-type3.native .x-icon.hack,
+.tree-vertical-line-type3.disabled .x-icon.hack {
+ background: url('icon/tree-vertical-line-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-3.png');
+ _background: none;
+}
.tree-vertical-line-type4 .x-icon,
.tree-vertical-line-type4:hover .x-icon,
.tree-vertical-line-type4:active .x-icon {
@@ -156,6 +286,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-4.png');
_background: none;
}
+.tree-vertical-line-type4 .x-icon.hack,
+.tree-vertical-line-type4:hover .x-icon.hack,
+.tree-vertical-line-type4:active .x-icon.hack {
+ background: url('icon/tree-vertical-line-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-4.png');
+ _background: none;
+}
.tree-vertical-line-type4.native .x-icon,
.tree-vertical-line-type4.disabled .x-icon {
display: block;
@@ -163,6 +300,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-4.png');
_background: none;
}
+.tree-vertical-line-type4.native .x-icon.hack,
+.tree-vertical-line-type4.disabled .x-icon.hack {
+ background: url('icon/tree-vertical-line-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/tree-vertical-line-4.png');
+ _background: none;
+}
.bi-theme-dark .tree-collapse-icon-type1 .x-icon,
.bi-theme-dark .tree-collapse-icon-type1:hover .x-icon,
.bi-theme-dark .tree-collapse-icon-type1:active .x-icon {
@@ -171,6 +314,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-1.png');
_background: none;
}
+.bi-theme-dark .tree-collapse-icon-type1 .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type1:hover .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type1:active .x-icon.hack {
+ background: url('icon/dark/tree-collapse-1.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-1.png');
+ _background: none;
+}
.bi-theme-dark .tree-collapse-icon-type1.native .x-icon,
.bi-theme-dark .tree-collapse-icon-type1.disabled .x-icon {
display: block;
@@ -178,6 +328,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-1.png');
_background: none;
}
+.bi-theme-dark .tree-collapse-icon-type1.native .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type1.disabled .x-icon.hack {
+ background: url('icon/dark/tree-collapse-1.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-1.png');
+ _background: none;
+}
.bi-theme-dark .tree-collapse-icon-type2 .x-icon,
.bi-theme-dark .tree-collapse-icon-type2:hover .x-icon,
.bi-theme-dark .tree-collapse-icon-type2:active .x-icon {
@@ -186,6 +342,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-2.png');
_background: none;
}
+.bi-theme-dark .tree-collapse-icon-type2 .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type2:hover .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type2:active .x-icon.hack {
+ background: url('icon/dark/tree-collapse-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-2.png');
+ _background: none;
+}
.bi-theme-dark .tree-collapse-icon-type2.native .x-icon,
.bi-theme-dark .tree-collapse-icon-type2.disabled .x-icon {
display: block;
@@ -193,6 +356,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-2.png');
_background: none;
}
+.bi-theme-dark .tree-collapse-icon-type2.native .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type2.disabled .x-icon.hack {
+ background: url('icon/dark/tree-collapse-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-2.png');
+ _background: none;
+}
.bi-theme-dark .tree-collapse-icon-type3 .x-icon,
.bi-theme-dark .tree-collapse-icon-type3:hover .x-icon,
.bi-theme-dark .tree-collapse-icon-type3:active .x-icon {
@@ -201,6 +370,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-3.png');
_background: none;
}
+.bi-theme-dark .tree-collapse-icon-type3 .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type3:hover .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type3:active .x-icon.hack {
+ background: url('icon/dark/tree-collapse-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-3.png');
+ _background: none;
+}
.bi-theme-dark .tree-collapse-icon-type3.native .x-icon,
.bi-theme-dark .tree-collapse-icon-type3.disabled .x-icon {
display: block;
@@ -208,6 +384,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-3.png');
_background: none;
}
+.bi-theme-dark .tree-collapse-icon-type3.native .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type3.disabled .x-icon.hack {
+ background: url('icon/dark/tree-collapse-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-3.png');
+ _background: none;
+}
.bi-theme-dark .tree-collapse-icon-type4 .x-icon,
.bi-theme-dark .tree-collapse-icon-type4:hover .x-icon,
.bi-theme-dark .tree-collapse-icon-type4:active .x-icon {
@@ -216,6 +398,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-4.png');
_background: none;
}
+.bi-theme-dark .tree-collapse-icon-type4 .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type4:hover .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type4:active .x-icon.hack {
+ background: url('icon/dark/tree-collapse-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-4.png');
+ _background: none;
+}
.bi-theme-dark .tree-collapse-icon-type4.native .x-icon,
.bi-theme-dark .tree-collapse-icon-type4.disabled .x-icon {
display: block;
@@ -223,6 +412,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-4.png');
_background: none;
}
+.bi-theme-dark .tree-collapse-icon-type4.native .x-icon.hack,
+.bi-theme-dark .tree-collapse-icon-type4.disabled .x-icon.hack {
+ background: url('icon/dark/tree-collapse-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-collapse-4.png');
+ _background: none;
+}
.bi-theme-dark .tree-expand-icon-type1 .x-icon,
.bi-theme-dark .tree-expand-icon-type1:hover .x-icon,
.bi-theme-dark .tree-expand-icon-type1:active .x-icon {
@@ -231,6 +426,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-1.png');
_background: none;
}
+.bi-theme-dark .tree-expand-icon-type1 .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type1:hover .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type1:active .x-icon.hack {
+ background: url('icon/dark/tree-expand-1.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-1.png');
+ _background: none;
+}
.bi-theme-dark .tree-expand-icon-type1.native .x-icon,
.bi-theme-dark .tree-expand-icon-type1.disabled .x-icon {
display: block;
@@ -238,6 +440,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-1.png');
_background: none;
}
+.bi-theme-dark .tree-expand-icon-type1.native .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type1.disabled .x-icon.hack {
+ background: url('icon/dark/tree-expand-1.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-1.png');
+ _background: none;
+}
.bi-theme-dark .tree-expand-icon-type2 .x-icon,
.bi-theme-dark .tree-expand-icon-type2:hover .x-icon,
.bi-theme-dark .tree-expand-icon-type2:active .x-icon {
@@ -246,6 +454,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-2.png');
_background: none;
}
+.bi-theme-dark .tree-expand-icon-type2 .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type2:hover .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type2:active .x-icon.hack {
+ background: url('icon/dark/tree-expand-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-2.png');
+ _background: none;
+}
.bi-theme-dark .tree-expand-icon-type2.native .x-icon,
.bi-theme-dark .tree-expand-icon-type2.disabled .x-icon {
display: block;
@@ -253,6 +468,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-2.png');
_background: none;
}
+.bi-theme-dark .tree-expand-icon-type2.native .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type2.disabled .x-icon.hack {
+ background: url('icon/dark/tree-expand-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-2.png');
+ _background: none;
+}
.bi-theme-dark .tree-expand-icon-type3 .x-icon,
.bi-theme-dark .tree-expand-icon-type3:hover .x-icon,
.bi-theme-dark .tree-expand-icon-type3:active .x-icon {
@@ -261,6 +482,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-3.png');
_background: none;
}
+.bi-theme-dark .tree-expand-icon-type3 .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type3:hover .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type3:active .x-icon.hack {
+ background: url('icon/dark/tree-expand-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-3.png');
+ _background: none;
+}
.bi-theme-dark .tree-expand-icon-type3.native .x-icon,
.bi-theme-dark .tree-expand-icon-type3.disabled .x-icon {
display: block;
@@ -268,6 +496,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-3.png');
_background: none;
}
+.bi-theme-dark .tree-expand-icon-type3.native .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type3.disabled .x-icon.hack {
+ background: url('icon/dark/tree-expand-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-3.png');
+ _background: none;
+}
.bi-theme-dark .tree-expand-icon-type4 .x-icon,
.bi-theme-dark .tree-expand-icon-type4:hover .x-icon,
.bi-theme-dark .tree-expand-icon-type4:active .x-icon {
@@ -276,6 +510,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-4.png');
_background: none;
}
+.bi-theme-dark .tree-expand-icon-type4 .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type4:hover .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type4:active .x-icon.hack {
+ background: url('icon/dark/tree-expand-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-4.png');
+ _background: none;
+}
.bi-theme-dark .tree-expand-icon-type4.native .x-icon,
.bi-theme-dark .tree-expand-icon-type4.disabled .x-icon {
display: block;
@@ -283,6 +524,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-4.png');
_background: none;
}
+.bi-theme-dark .tree-expand-icon-type4.native .x-icon.hack,
+.bi-theme-dark .tree-expand-icon-type4.disabled .x-icon.hack {
+ background: url('icon/dark/tree-expand-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-expand-4.png');
+ _background: none;
+}
.bi-theme-dark .tree-vertical-line-type2 .x-icon,
.bi-theme-dark .tree-vertical-line-type2:hover .x-icon,
.bi-theme-dark .tree-vertical-line-type2:active .x-icon {
@@ -291,6 +538,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-2.png');
_background: none;
}
+.bi-theme-dark .tree-vertical-line-type2 .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type2:hover .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type2:active .x-icon.hack {
+ background: url('icon/dark/tree-vertical-line-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-2.png');
+ _background: none;
+}
.bi-theme-dark .tree-vertical-line-type2.native .x-icon,
.bi-theme-dark .tree-vertical-line-type2.disabled .x-icon {
display: block;
@@ -298,6 +552,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-2.png');
_background: none;
}
+.bi-theme-dark .tree-vertical-line-type2.native .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type2.disabled .x-icon.hack {
+ background: url('icon/dark/tree-vertical-line-2.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-2.png');
+ _background: none;
+}
.bi-theme-dark .tree-vertical-line-type3 .x-icon,
.bi-theme-dark .tree-vertical-line-type3:hover .x-icon,
.bi-theme-dark .tree-vertical-line-type3:active .x-icon {
@@ -306,6 +566,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-3.png');
_background: none;
}
+.bi-theme-dark .tree-vertical-line-type3 .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type3:hover .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type3:active .x-icon.hack {
+ background: url('icon/dark/tree-vertical-line-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-3.png');
+ _background: none;
+}
.bi-theme-dark .tree-vertical-line-type3.native .x-icon,
.bi-theme-dark .tree-vertical-line-type3.disabled .x-icon {
display: block;
@@ -313,6 +580,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-3.png');
_background: none;
}
+.bi-theme-dark .tree-vertical-line-type3.native .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type3.disabled .x-icon.hack {
+ background: url('icon/dark/tree-vertical-line-3.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-3.png');
+ _background: none;
+}
.bi-theme-dark .tree-vertical-line-type4 .x-icon,
.bi-theme-dark .tree-vertical-line-type4:hover .x-icon,
.bi-theme-dark .tree-vertical-line-type4:active .x-icon {
@@ -321,6 +594,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-4.png');
_background: none;
}
+.bi-theme-dark .tree-vertical-line-type4 .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type4:hover .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type4:active .x-icon.hack {
+ background: url('icon/dark/tree-vertical-line-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-4.png');
+ _background: none;
+}
.bi-theme-dark .tree-vertical-line-type4.native .x-icon,
.bi-theme-dark .tree-vertical-line-type4.disabled .x-icon {
display: block;
@@ -328,12 +608,23 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-4.png');
_background: none;
}
+.bi-theme-dark .tree-vertical-line-type4.native .x-icon.hack,
+.bi-theme-dark .tree-vertical-line-type4.disabled .x-icon.hack {
+ background: url('icon/dark/tree-vertical-line-4.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/dark/tree-vertical-line-4.png');
+ _background: none;
+}
.check-box-icon .x-icon {
display: block;
background: url('icon/check-box-normal.png') no-repeat 0 0;
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-normal.png');
_background: none;
}
+.check-box-icon .x-icon.hack {
+ background: url('icon/check-box-normal.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-normal.png');
+ _background: none;
+}
.check-box-icon:hover .x-icon,
.check-box-icon:focus .x-icon,
.check-box-icon.hover .x-icon {
@@ -342,6 +633,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-normal.png');
_background: none;
}
+.check-box-icon:hover .x-icon.hack,
+.check-box-icon:focus .x-icon.hack,
+.check-box-icon.hover .x-icon.hack {
+ background: url('icon/check-box-normal.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-normal.png');
+ _background: none;
+}
.check-box-icon:active .x-icon,
.check-box-icon.active .x-icon {
display: block;
@@ -349,6 +647,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-active.png');
_background: none;
}
+.check-box-icon:active .x-icon.hack,
+.check-box-icon.active .x-icon.hack {
+ background: url('icon/check-box-active.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-active.png');
+ _background: none;
+}
.check-box-icon.native .x-icon,
.check-box-icon.disabled .x-icon {
display: block;
@@ -356,6 +660,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-disable.png');
_background: none;
}
+.check-box-icon.native .x-icon.hack,
+.check-box-icon.disabled .x-icon.hack {
+ background: url('icon/check-box-disable.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-disable.png');
+ _background: none;
+}
.check-box-icon.native .x-icon,
.check-box-icon.disabled.active .x-icon {
display: block;
@@ -363,12 +673,23 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-disable2.png');
_background: none;
}
+.check-box-icon.native .x-icon.hack,
+.check-box-icon.disabled.active .x-icon.hack {
+ background: url('icon/check-box-disable2.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/check-box-disable2.png');
+ _background: none;
+}
.radio-icon .x-icon {
display: block;
background: url('icon/radio-normal.png') no-repeat 0 0;
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-normal.png');
_background: none;
}
+.radio-icon .x-icon.hack {
+ background: url('icon/radio-normal.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-normal.png');
+ _background: none;
+}
.radio-icon:hover .x-icon,
.radio-icon:focus .x-icon,
.radio-icon.hover .x-icon {
@@ -377,6 +698,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-normal.png');
_background: none;
}
+.radio-icon:hover .x-icon.hack,
+.radio-icon:focus .x-icon.hack,
+.radio-icon.hover .x-icon.hack {
+ background: url('icon/radio-normal.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-normal.png');
+ _background: none;
+}
.radio-icon:active .x-icon,
.radio-icon.active .x-icon {
display: block;
@@ -384,6 +712,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-active.png');
_background: none;
}
+.radio-icon:active .x-icon.hack,
+.radio-icon.active .x-icon.hack {
+ background: url('icon/radio-active.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-active.png');
+ _background: none;
+}
.radio-icon.native .x-icon,
.radio-icon.disabled .x-icon {
display: block;
@@ -391,6 +725,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-disable.png');
_background: none;
}
+.radio-icon.native .x-icon.hack,
+.radio-icon.disabled .x-icon.hack {
+ background: url('icon/radio-disable.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-disable.png');
+ _background: none;
+}
.radio-icon.native .x-icon,
.radio-icon.disabled.active .x-icon {
display: block;
@@ -398,6 +738,12 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-disable2.png');
_background: none;
}
+.radio-icon.native .x-icon.hack,
+.radio-icon.disabled.active .x-icon.hack {
+ background: url('icon/radio-disable2.png') no-repeat 0 0;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/radio-disable2.png');
+ _background: none;
+}
.check-half-select-icon .x-icon,
.check-half-select-icon:hover .x-icon,
.check-half-select-icon:active .x-icon {
@@ -406,6 +752,13 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/half_selected.png');
_background: none;
}
+.check-half-select-icon .x-icon.hack,
+.check-half-select-icon:hover .x-icon.hack,
+.check-half-select-icon:active .x-icon.hack {
+ background: url('icon/half_selected.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/half_selected.png');
+ _background: none;
+}
.check-half-select-icon.native .x-icon,
.check-half-select-icon.disabled .x-icon {
display: block;
@@ -413,3 +766,9 @@
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/half_selected.png');
_background: none;
}
+.check-half-select-icon.native .x-icon.hack,
+.check-half-select-icon.disabled .x-icon.hack {
+ background: url('icon/half_selected.png') no-repeat 0px 0px;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icon/half_selected.png');
+ _background: none;
+}
diff --git a/src/less/image.less b/src/less/image.less
index a714f1fe3..2c70dcae9 100644
--- a/src/less/image.less
+++ b/src/less/image.less
@@ -11,18 +11,30 @@
_background: none;
}
+.image2xPath(@path, @top:center, @left:center, @repeat: no-repeat) when not (@path = none) {
+ background: url('@{image2xUrl}@{path}') @repeat @left @top;
+ _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='@{image2xUrl}@{path}');
+ _background: none;
+}
+
.icon(@class, @iconPath, @top:0px, @left:0px) {
.@{class} {
& .x-icon,
&:hover .x-icon,
&:active .x-icon {
display: block;
- .imagePath(@iconPath, -@top, -@left);
+ .image2xPath(@iconPath, -@top, -@left);
+ &.hack {
+ .imagePath(@iconPath, -@top, -@left);
+ }
}
&.native .x-icon,
&.disabled .x-icon {
display: block;
- .imagePath(@iconPath, -@top, -@left);
+ .image2xPath(@iconPath, -@top, -@left);
+ &.hack {
+ .imagePath(@iconPath, -@top, -@left);
+ }
}
}
}
@@ -31,7 +43,10 @@
.@{class} {
& .x-icon {
display: block;
- .imagePath(@iconPath, -@top, -@left);
+ .image2xPath(@iconPath, -@top, -@left);
+ &.hack {
+ .imagePath(@iconPath, -@top, -@left);
+ }
}
&:hover .x-icon,
&:focus .x-icon,
@@ -39,12 +54,18 @@
&:active .x-icon,
&.active .x-icon {
display: block;
- .imagePath(@iconPath, -@top, -(@left + @distance));
+ .image2xPath(@iconPath, -@top, -(@left + @distance));
+ &.hack {
+ .imagePath(@iconPath, -@top, -(@left + @distance));
+ }
}
&.native .x-icon,
&.disabled .x-icon {
display: block;
- .imagePath(@iconPath, -@top, -@left);
+ .image2xPath(@iconPath, -@top, -@left);
+ &.hack {
+ .imagePath(@iconPath, -@top, -@left);
+ }
}
}
}
@@ -56,17 +77,26 @@
&:focus .x-icon,
&.hover .x-icon {
display: block;
- .imagePath(@iconPath, -@top, -@left);
+ .image2xPath(@iconPath, -@top, -@left);
+ &.hack {
+ .imagePath(@iconPath, -@top, -@left);
+ }
}
&:active .x-icon,
&.active .x-icon {
display: block;
- .imagePath(@iconPath, -@top, -(@left + @distance));
+ .image2xPath(@iconPath, -@top, -(@left + @distance));
+ &.hack {
+ .imagePath(@iconPath, -@top, -(@left + @distance));
+ }
}
&.native .x-icon,
&.disabled .x-icon {
display: block;
- .imagePath(@iconPath, -@top, -@left);
+ .image2xPath(@iconPath, -@top, -@left);
+ &.hack {
+ .imagePath(@iconPath, -@top, -@left);
+ }
}
}
}
@@ -75,24 +105,36 @@
.@{class} {
& .x-icon {
display: block;
- .imagePath(@iconPath, -@top, -@left);
+ .image2xPath(@iconPath, -@top, -@left);
+ &.hack {
+ .imagePath(@iconPath, -@top, -@left);
+ }
}
&:hover .x-icon,
&:focus .x-icon,
&.hover .x-icon {
display: block;
- .imagePath(@iconPath, -@top, -(@left+@distance));
+ .image2xPath(@iconPath, -@top, -(@left+@distance));
+ &.hack {
+ .imagePath(@iconPath, -@top, -(@left+@distance));
+ }
}
&:active .x-icon,
&.active .x-icon {
display: block;
- .imagePath(@iconPath, -@top, -(@left+@distance*2));
+ .image2xPath(@iconPath, -@top, -(@left+@distance*2));
+ &.hack {
+ .imagePath(@iconPath, -@top, -(@left+@distance*2));
+ }
}
&.native .x-icon,
&.disabled .x-icon {
display: block;
- .imagePath(@iconPath, -@top, -@left);
+ .image2xPath(@iconPath, -@top, -@left);
+ &.hack {
+ .imagePath(@iconPath, -@top, -@left);
+ }
}
}
}
@@ -101,16 +143,25 @@
.@{class} {
& .x-icon {
display: block;
- .imagePath(@iconPath, -@top, -@left);
+ .image2xPath(@iconPath, -@top, -@left);
+ &.hack {
+ .imagePath(@iconPath, -@top, -@left);
+ }
}
&.active .x-icon {
display: block;
- .imagePath(@iconPath, -@top, -(@left+@distance));
+ .image2xPath(@iconPath, -@top, -(@left+@distance));
+ &.hack {
+ .imagePath(@iconPath, -@top, -(@left+@distance));
+ }
}
&.native .x-icon,
&.disabled .x-icon {
display: block;
- .imagePath(@iconPath, -@top, -@left);
+ .image2xPath(@iconPath, -@top, -@left);
+ &.hack {
+ .imagePath(@iconPath, -@top, -@left);
+ }
}
}
}
@@ -119,29 +170,44 @@
.@{class} {
& .x-icon {
display: block;
- .imagePath(@iconPath, 0, 0);
+ .image2xPath(@iconPath, 0, 0);
+ &.hack {
+ .imagePath(@iconPath, 0, 0);
+ }
}
&:hover .x-icon,
&:focus .x-icon,
&.hover .x-icon {
display: block;
- .imagePath(@hoverPath, 0, 0);
+ .image2xPath(@hoverPath, 0, 0);
+ &.hack {
+ .imagePath(@hoverPath, 0, 0);
+ }
}
&:active .x-icon,
&.active .x-icon {
display: block;
- .imagePath(@activePath, 0, 0);
+ .image2xPath(@activePath, 0, 0);
+ &.hack {
+ .imagePath(@activePath, 0, 0);
+ }
}
&.native .x-icon,
&.disabled .x-icon {
display: block;
- .imagePath(@disablePath, 0, 0);
+ .image2xPath(@disablePath, 0, 0);
+ &.hack {
+ .imagePath(@disablePath, 0, 0);
+ }
}
&.native .x-icon,
&.disabled.active .x-icon {
display: block;
- .imagePath(@activeDisablePath, 0, 0);
+ .image2xPath(@activeDisablePath, 0, 0);
+ &.hack {
+ .imagePath(@activeDisablePath, 0, 0);
+ }
}
}
}
@@ -150,19 +216,28 @@
.@{class} {
& .x-icon {
display: block;
- .imagePath(@iconPath, 0, 0);
+ .image2xPath(@iconPath, 0, 0);
+ &.hack {
+ .imagePath(@iconPath, 0, 0);
+ }
}
&:hover .x-icon,
&:focus .x-icon,
&.hover .x-icon {
display: block;
- .imagePath(@hoverPath, 0, 0);
+ .image2xPath(@hoverPath, 0, 0);
+ &.hack {
+ .imagePath(@hoverPath, 0, 0);
+ }
}
&.native .x-icon,
&.disabled .x-icon {
display: block;
- .imagePath(@disablePath, 0, 0);
+ .image2xPath(@disablePath, 0, 0);
+ &.hack {
+ .imagePath(@disablePath, 0, 0);
+ }
}
}
}
@@ -177,8 +252,8 @@
.font(@class,@content, @color: @color-bi-font-native) {
@fc: "\@{content}";
.@{class} {
- & .b-font{
- *zoom: ~"expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '@{content}')";
+ & .b-font {
+ *zoom: ~"expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '@{content};')";
}
& .b-font:before {
content: @fc;
@@ -195,8 +270,8 @@
.font-hover(@class,@content,@color-native: @color-bi-font-native, @color-hover: @color-bi-font-hover) {
@fc: "\@{content}";
.@{class} {
- & .b-font{
- *zoom: ~"expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '@{content}')";
+ & .b-font {
+ *zoom: ~"expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '@{content};')";
}
& .b-font:before {
content: @fc;
@@ -219,8 +294,8 @@
.font-effect(@class,@content,@color-native: @color-bi-font-native, @color-hover: @color-bi-font-hover, @color-active: @color-bi-font-active, @color-selected: @color-bi-font-active) {
@fc: "\@{content}";
.@{class} {
- & .b-font{
- *zoom: ~"expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '@{content}')";
+ & .b-font {
+ *zoom: ~"expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '@{content};')";
}
& .b-font:before {
content: @fc;
@@ -251,8 +326,8 @@
.font-hover-active(@class,@content,@color-native: @color-bi-font-native, @color-hover: @color-bi-font-hover, @color-active: @color-bi-font-active) {
@fc: "\@{content}";
.@{class} {
- & .b-font{
- *zoom: ~"expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '@{content}')";
+ & .b-font {
+ *zoom: ~"expression( this.runtimeStyle['zoom'] = '1',this.innerHTML = '@{content};')";
}
& .b-font:before {
content: @fc;
diff --git a/src/less/resource/font.less b/src/less/resource/font.less
index 603ef3fef..6f35e8c35 100644
--- a/src/less/resource/font.less
+++ b/src/less/resource/font.less
@@ -79,4 +79,8 @@
.font-hover(primary-key-font, @font-key);
-.font(drag-tag-font, @font-cross, @color-bi-text-redmark);
\ No newline at end of file
+.font(drag-tag-font, @font-cross, @color-bi-text-redmark);
+
+//数值区间
+.font-hover-active(less-font, @font-less);
+.font-hover-active(less-equal-font, @font-less-equal);
\ No newline at end of file
diff --git a/src/less/var.less b/src/less/var.less
index 7d4d2b66e..f23c097ad 100644
--- a/src/less/var.less
+++ b/src/less/var.less
@@ -1,5 +1,6 @@
@webUrl: '';
@imageUrl: ''; //图片的基本地址
+@image2xUrl: ''; //图片的基本地址
@cursor: '@{imageUrl}cursor/cursor_hand.cur';
@dragCursor: '@{imageUrl}cursor/cursor_drag_hand.cur';
diff --git a/src/widget/adaptivearrangement/adaptivearrangement.js b/src/widget/adaptivearrangement/adaptivearrangement.js
index 0891d19a9..ee4d56348 100644
--- a/src/widget/adaptivearrangement/adaptivearrangement.js
+++ b/src/widget/adaptivearrangement/adaptivearrangement.js
@@ -210,7 +210,12 @@ BI.AdaptiveArrangement = BI.inherit(BI.Widget, {
clearInterval(self._scrollInterval);
self._scrollInterval = null;
}
+ var count = 0;
self._scrollInterval = setInterval(function () {
+ count++;
+ if (count <= 3) {
+ return;
+ }
var offset = self._getScrollOffset();
var t = offset.top + map[direction][0] * 40;
var l = offset.left + map[direction][1] * 40;
diff --git a/src/widget/date/calendar/popup.calendar.date.js b/src/widget/date/calendar/popup.calendar.date.js
index 8784cfc4e..24b57d261 100644
--- a/src/widget/date/calendar/popup.calendar.date.js
+++ b/src/widget/date/calendar/popup.calendar.date.js
@@ -27,22 +27,23 @@ BI.DateCalendarPopup = BI.inherit(BI.Widget, {
month: date.month,
day: this.selectedTime.day
});
- return calendar;
+ return calendar
},
_init: function () {
BI.DateCalendarPopup.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
+ var self = this,
+ o = this.options;
this.today = new Date();
this._year = this.today.getFullYear();
this._month = this.today.getMonth();
this._day = this.today.getDate();
this.selectedTime = o.selectedTime || {
- year: this._year,
- month: this._month,
- day: this._day
- };
+ year: this._year,
+ month: this._month,
+ day: this._day
+ };
this.datePicker = BI.createWidget({
type: "bi.date_picker",
min: o.min,
diff --git a/src/widget/date/combo.date.js b/src/widget/date/combo.date.js
index e70e30138..615c29871 100644
--- a/src/widget/date/combo.date.js
+++ b/src/widget/date/combo.date.js
@@ -14,7 +14,8 @@ BI.DateCombo = BI.inherit(BI.Widget, {
},
_init: function () {
BI.DateCombo.superclass._init.apply(this, arguments);
- var self = this, o = this.options;
+ var self = this,
+ o = this.options;
this.trigger = BI.createWidget({
type: "bi.date_trigger"
diff --git a/src/widget/filemanager/nav/button/button.nav.filemanager.js b/src/widget/filemanager/nav/button/button.nav.filemanager.js
index d34eafb9b..09eaa7d1a 100644
--- a/src/widget/filemanager/nav/button/button.nav.filemanager.js
+++ b/src/widget/filemanager/nav/button/button.nav.filemanager.js
@@ -9,7 +9,7 @@ BI.FileManagerNavButton = BI.inherit(BI.Widget, {
_const: {
normal_color: "#ffffff",
- select_color: "#f4f4f4"
+ select_color: "#eff1f4"
},
_defaultConfig: function () {
return BI.extend(BI.FileManagerNavButton.superclass._defaultConfig.apply(this, arguments), {