diff --git a/dist/base.css b/dist/base.css index c976bb8046..cc07af75c6 100644 --- a/dist/base.css +++ b/dist/base.css @@ -3,7 +3,7 @@ filter: alpha(opacity=50); background-color: #ffffff; } - + .bi-color-chooser-trigger { -webkit-border-radius: 2px; -moz-border-radius: 2px; @@ -163,12 +163,12 @@ border-right: 7px solid transparent; content: ""; } - + .bi-combo.bi-combo-popup { display: block !important; visibility: visible !important; } - + .bi-search-text-value-combo .trigger-icon-button { font-size: 16px; } @@ -187,7 +187,7 @@ .bi-search-text-value-combo.combo-show .trigger-down { display: none; } - + .bi-text-value-combo.combo-error .bi-select-text-trigger .bi-label { color: #ff4949; } @@ -198,7 +198,7 @@ .bi-search-editor .search-font { font-size: 16px; } - + /*************BI.SearchEditor******************/ .bi-small-search-editor .bi-editor { font-size: 12px; @@ -215,7 +215,7 @@ .bi-small-search-editor .search-font { font-size: 18px; } - + .bi-sign-initial-editor .sign-initial-editor-text { font-size: 14px; } @@ -756,14 +756,14 @@ li.CodeMirror-hint-active { .bi-all-count-pager .all-pager-next { font-size: 16px; } - + .bi-direction-pager .direction-pager-prev { font-size: 16px; } .bi-direction-pager .direction-pager-next { font-size: 16px; } - + .bi-pager .page-item { -webkit-border-radius: 2px; -moz-border-radius: 2px; @@ -1168,13 +1168,13 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-theme-dark #body .bi-button.button-common.disabled.ghost .b-font:before { color: #ffffff !important; } - + .bi-single-select-icon-text-item:active .b-font:before, .bi-single-select-icon-text-item.active .b-font:before { color: #3685f2; } - - + + .bi-switch { -webkit-border-radius: 40px 40px 40px 40px; -moz-border-radius: 40px 40px 40px 40px; @@ -1206,19 +1206,19 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, margin: 1px 1px; display: inline-block; } - - + + .bi-multifile-editor .multifile-editor { text-align: right; cursor: pointer; font-size: 100px; z-index: 2; } - - - - - + + + + + .bi-textarea-editor { overflow: hidden; overflow-x: hidden; @@ -1300,11 +1300,11 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, background: #feeed7; color: #faaa39; } - + .bi-tip { position: fixed !important; } - + .bi-toast { font-size: 14px; color: #ffffff; @@ -1329,7 +1329,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-toast .toast-icon { font-size: 16px; } - + .bi-tooltip { max-width: 250px; -webkit-border-radius: 2px; @@ -1393,13 +1393,13 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-theme-dark .bi-collection-table-cell.first-col { border-left: 1px solid #525466; } - + .bi-quick-collection-table > div > .bi-collection { overflow: hidden !important; overflow-x: hidden !important; overflow-y: hidden !important; } - + .bi-grid-table-cell { -webkit-box-sizing: border-box; /*Safari3.2+*/ @@ -1422,7 +1422,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-theme-dark .bi-grid-table-cell.first-col { border-left: 1px solid #525466; } - + .scrollbar-layout-main { box-sizing: border-box; outline: none; @@ -1536,7 +1536,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, bottom: 0; position: absolute; } - + .bi-table > .first-col { border-left: none; } @@ -1615,7 +1615,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, border-top: 1px solid #525466; border-left: 1px solid #525466; } - + .bi-resizable-table-cell .resizable-table-cell-resizer-container { cursor: ew-resize; z-index: 1; @@ -1627,7 +1627,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-resizable-table-cell .resizable-table-cell-resizer-container.suitable .resizable-table-cell-resizer-knob { background-color: #13cd66; } - + .bi-resizable-table .resizable-table-resizer { cursor: ew-resize; z-index: 1; @@ -1644,11 +1644,11 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-resizable-table .resizable-table-region-resizer.dragging .resizable-table-region-resizer-knob { background-color: #3f8ce8; } - + .bi-branch-tree .bi-branch-tree-view { min-width: 300px; } - + .bi-display-tree .ztree * { color: #999999; } @@ -1880,8 +1880,8 @@ ul.ztree.zTreeDragUL { padding:0; background:none; }*/ - - + + .bi-trigger .bi-trigger-icon-button { font-size: 16px; } @@ -1897,13 +1897,13 @@ ul.ztree.zTreeDragUL { .bi-combo-popup .trigger-down { display: none; } - + .bi-select-text-trigger { -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; } - + .bi-small-select-text-trigger { -webkit-border-radius: 2px; -moz-border-radius: 2px; diff --git a/dist/bundle.css b/dist/bundle.css index e706c9324a..045a2569a5 100644 --- a/dist/bundle.css +++ b/dist/bundle.css @@ -1307,7 +1307,7 @@ textarea { -o-align-items: center; align-items: center; } - + .bi-flex-horizontal-layout { display: box; /* OLD - Android 4.4- */ @@ -1378,7 +1378,7 @@ textarea { -o-align-items: flex-end; align-items: flex-end; } - + .bi-flex-vertical-center { display: box; /* OLD - Android 4.4- */ @@ -1455,7 +1455,7 @@ textarea { -o-align-items: stretch; align-items: stretch; } - + .bi-flex-wrapper-center-layout .flex-wrapper-center-layout-wrapper { display: box; /* OLD - Android 4.4- */ @@ -1499,7 +1499,7 @@ textarea { min-height: 100%; float: left; } - + .bi-flex-wrapper-horizontal-layout .flex-wrapper-horizontal-layout-wrapper { display: box; /* OLD - Android 4.4- */ @@ -1569,7 +1569,7 @@ textarea { -o-align-items: flex-end; align-items: flex-end; } - + .bi-flex-wrapper-vertical-center .flex-wrapper-vertical-center-wrapper { display: box; /* OLD - Android 4.4- */ @@ -1654,7 +1654,7 @@ textarea { vertical-align: middle; content: ' '; } - + .bi-inline-vertical-adapt-layout:after { display: inline-block; width: 0; @@ -1674,7 +1674,7 @@ textarea { filter: alpha(opacity=50); background-color: #ffffff; } - + .bi-color-chooser-trigger { -webkit-border-radius: 2px; -moz-border-radius: 2px; @@ -1834,12 +1834,12 @@ textarea { border-right: 7px solid transparent; content: ""; } - + .bi-combo.bi-combo-popup { display: block !important; visibility: visible !important; } - + .bi-search-text-value-combo .trigger-icon-button { font-size: 16px; } @@ -1858,7 +1858,7 @@ textarea { .bi-search-text-value-combo.combo-show .trigger-down { display: none; } - + .bi-text-value-combo.combo-error .bi-select-text-trigger .bi-label { color: #ff4949; } @@ -1869,7 +1869,7 @@ textarea { .bi-search-editor .search-font { font-size: 16px; } - + /*************BI.SearchEditor******************/ .bi-small-search-editor .bi-editor { font-size: 12px; @@ -1886,7 +1886,7 @@ textarea { .bi-small-search-editor .search-font { font-size: 18px; } - + .bi-sign-initial-editor .sign-initial-editor-text { font-size: 14px; } @@ -2427,14 +2427,14 @@ li.CodeMirror-hint-active { .bi-all-count-pager .all-pager-next { font-size: 16px; } - + .bi-direction-pager .direction-pager-prev { font-size: 16px; } .bi-direction-pager .direction-pager-next { font-size: 16px; } - + .bi-pager .page-item { -webkit-border-radius: 2px; -moz-border-radius: 2px; @@ -2839,13 +2839,13 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-theme-dark #body .bi-button.button-common.disabled.ghost .b-font:before { color: #ffffff !important; } - + .bi-single-select-icon-text-item:active .b-font:before, .bi-single-select-icon-text-item.active .b-font:before { color: #3685f2; } - - + + .bi-switch { -webkit-border-radius: 40px 40px 40px 40px; -moz-border-radius: 40px 40px 40px 40px; @@ -2877,19 +2877,19 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, margin: 1px 1px; display: inline-block; } - - + + .bi-multifile-editor .multifile-editor { text-align: right; cursor: pointer; font-size: 100px; z-index: 2; } - - - - - + + + + + .bi-textarea-editor { overflow: hidden; overflow-x: hidden; @@ -2971,11 +2971,11 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, background: #feeed7; color: #faaa39; } - + .bi-tip { position: fixed !important; } - + .bi-toast { font-size: 14px; color: #ffffff; @@ -3000,7 +3000,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-toast .toast-icon { font-size: 16px; } - + .bi-tooltip { max-width: 250px; -webkit-border-radius: 2px; @@ -3064,13 +3064,13 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-theme-dark .bi-collection-table-cell.first-col { border-left: 1px solid #525466; } - + .bi-quick-collection-table > div > .bi-collection { overflow: hidden !important; overflow-x: hidden !important; overflow-y: hidden !important; } - + .bi-grid-table-cell { -webkit-box-sizing: border-box; /*Safari3.2+*/ @@ -3093,7 +3093,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-theme-dark .bi-grid-table-cell.first-col { border-left: 1px solid #525466; } - + .scrollbar-layout-main { box-sizing: border-box; outline: none; @@ -3207,7 +3207,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, bottom: 0; position: absolute; } - + .bi-table > .first-col { border-left: none; } @@ -3286,7 +3286,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, border-top: 1px solid #525466; border-left: 1px solid #525466; } - + .bi-resizable-table-cell .resizable-table-cell-resizer-container { cursor: ew-resize; z-index: 1; @@ -3298,7 +3298,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-resizable-table-cell .resizable-table-cell-resizer-container.suitable .resizable-table-cell-resizer-knob { background-color: #13cd66; } - + .bi-resizable-table .resizable-table-resizer { cursor: ew-resize; z-index: 1; @@ -3315,11 +3315,11 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-resizable-table .resizable-table-region-resizer.dragging .resizable-table-region-resizer-knob { background-color: #3f8ce8; } - + .bi-branch-tree .bi-branch-tree-view { min-width: 300px; } - + .bi-display-tree .ztree * { color: #999999; } @@ -3551,8 +3551,8 @@ ul.ztree.zTreeDragUL { padding:0; background:none; }*/ - - + + .bi-trigger .bi-trigger-icon-button { font-size: 16px; } @@ -3568,13 +3568,13 @@ ul.ztree.zTreeDragUL { .bi-combo-popup .trigger-down { display: none; } - + .bi-select-text-trigger { -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; } - + .bi-small-select-text-trigger { -webkit-border-radius: 2px; -moz-border-radius: 2px; @@ -3624,18 +3624,18 @@ ul.ztree.zTreeDragUL { .bi-down-list-popup .bi-down-list-item .list-item-text { max-width: 203px; } - + .bi-excel-table-header-cell { font-weight: bold; } - + .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-file-manager-nav-button .file-manager-nav-button-text { max-width: 200px; } @@ -3700,7 +3700,7 @@ ul.ztree.zTreeDragUL { .bi-interval-slider-label { min-height: 50px; } - + .bi-interval-slider { min-height: 70px; } @@ -3714,9 +3714,9 @@ ul.ztree.zTreeDragUL { -moz-border-radius: 2px; border-radius: 2px; } - - - + + + .bi-multidate-popup .multidate-popup-label { color: #3685f2; font-size: 14px; @@ -3733,13 +3733,13 @@ ul.ztree.zTreeDragUL { color: #3685f2; font-size: 14px; } - - + + .bi-multidate-segment .bi-multidate-editor { font-size: 14px; } - - + + .bi-multilayer-select-level-tree .tree-view { min-width: 100%; } @@ -3749,7 +3749,7 @@ ul.ztree.zTreeDragUL { .bi-multi-select-check-pane .multi-select-check-selected { text-decoration: underline; } - + .bi-multi-select-combo .multi-select-trigger-icon-button { font-size: 16px; } @@ -3765,7 +3765,7 @@ ul.ztree.zTreeDragUL { .bi-multi-select-combo.combo-show .trigger-down { display: none; } - + .bi-multi-select-insert-combo .multi-select-trigger-icon-button { font-size: 16px; } @@ -3781,8 +3781,8 @@ ul.ztree.zTreeDragUL { .bi-multi-select-insert-combo.combo-show .trigger-down { display: none; } - - + + .bi-multi-select-trigger { -webkit-border-radius: 2px 2px 2px 2px; -moz-border-radius: 2px 2px 2px 2px; @@ -3873,18 +3873,18 @@ ul.ztree.zTreeDragUL { -o-user-select: text; user-select: text; } - + .bi-preview-table-cell { min-height: 25px; min-width: 80px; } - + .bi-preview-table-header-cell { font-weight: bold; min-height: 25px; min-width: 80px; } - + .bi-preview-table { -webkit-user-select: text; -khtml-user-select: text; @@ -4011,7 +4011,7 @@ ul.ztree.zTreeDragUL { .bi-single-slider-label { min-height: 50px; } - + .bi-single-slider-normal { min-height: 30px; } diff --git a/dist/core.css b/dist/core.css index 3849b85877..b5ce7a9911 100644 --- a/dist/core.css +++ b/dist/core.css @@ -1307,7 +1307,7 @@ textarea { -o-align-items: center; align-items: center; } - + .bi-flex-horizontal-layout { display: box; /* OLD - Android 4.4- */ @@ -1378,7 +1378,7 @@ textarea { -o-align-items: flex-end; align-items: flex-end; } - + .bi-flex-vertical-center { display: box; /* OLD - Android 4.4- */ @@ -1455,7 +1455,7 @@ textarea { -o-align-items: stretch; align-items: stretch; } - + .bi-flex-wrapper-center-layout .flex-wrapper-center-layout-wrapper { display: box; /* OLD - Android 4.4- */ @@ -1499,7 +1499,7 @@ textarea { min-height: 100%; float: left; } - + .bi-flex-wrapper-horizontal-layout .flex-wrapper-horizontal-layout-wrapper { display: box; /* OLD - Android 4.4- */ @@ -1569,7 +1569,7 @@ textarea { -o-align-items: flex-end; align-items: flex-end; } - + .bi-flex-wrapper-vertical-center .flex-wrapper-vertical-center-wrapper { display: box; /* OLD - Android 4.4- */ @@ -1654,7 +1654,7 @@ textarea { vertical-align: middle; content: ' '; } - + .bi-inline-vertical-adapt-layout:after { display: inline-block; width: 0; diff --git a/dist/core_without_normalize.css b/dist/core_without_normalize.css index 38c09c037a..1e34700f35 100644 --- a/dist/core_without_normalize.css +++ b/dist/core_without_normalize.css @@ -1029,7 +1029,7 @@ textarea { -o-align-items: center; align-items: center; } - + .bi-flex-horizontal-layout { display: box; /* OLD - Android 4.4- */ @@ -1100,7 +1100,7 @@ textarea { -o-align-items: flex-end; align-items: flex-end; } - + .bi-flex-vertical-center { display: box; /* OLD - Android 4.4- */ @@ -1177,7 +1177,7 @@ textarea { -o-align-items: stretch; align-items: stretch; } - + .bi-flex-wrapper-center-layout .flex-wrapper-center-layout-wrapper { display: box; /* OLD - Android 4.4- */ @@ -1221,7 +1221,7 @@ textarea { min-height: 100%; float: left; } - + .bi-flex-wrapper-horizontal-layout .flex-wrapper-horizontal-layout-wrapper { display: box; /* OLD - Android 4.4- */ @@ -1291,7 +1291,7 @@ textarea { -o-align-items: flex-end; align-items: flex-end; } - + .bi-flex-wrapper-vertical-center .flex-wrapper-vertical-center-wrapper { display: box; /* OLD - Android 4.4- */ @@ -1376,7 +1376,7 @@ textarea { vertical-align: middle; content: ' '; } - + .bi-inline-vertical-adapt-layout:after { display: inline-block; width: 0; diff --git a/dist/fineui.css b/dist/fineui.css index 0a387b352f..cc8babecae 100644 --- a/dist/fineui.css +++ b/dist/fineui.css @@ -1307,7 +1307,7 @@ textarea { -o-align-items: center; align-items: center; } - + .bi-flex-horizontal-layout { display: box; /* OLD - Android 4.4- */ @@ -1378,7 +1378,7 @@ textarea { -o-align-items: flex-end; align-items: flex-end; } - + .bi-flex-vertical-center { display: box; /* OLD - Android 4.4- */ @@ -1455,7 +1455,7 @@ textarea { -o-align-items: stretch; align-items: stretch; } - + .bi-flex-wrapper-center-layout .flex-wrapper-center-layout-wrapper { display: box; /* OLD - Android 4.4- */ @@ -1499,7 +1499,7 @@ textarea { min-height: 100%; float: left; } - + .bi-flex-wrapper-horizontal-layout .flex-wrapper-horizontal-layout-wrapper { display: box; /* OLD - Android 4.4- */ @@ -1569,7 +1569,7 @@ textarea { -o-align-items: flex-end; align-items: flex-end; } - + .bi-flex-wrapper-vertical-center .flex-wrapper-vertical-center-wrapper { display: box; /* OLD - Android 4.4- */ @@ -1654,7 +1654,7 @@ textarea { vertical-align: middle; content: ' '; } - + .bi-inline-vertical-adapt-layout:after { display: inline-block; width: 0; @@ -1674,7 +1674,7 @@ textarea { filter: alpha(opacity=50); background-color: #ffffff; } - + .bi-color-chooser-trigger { -webkit-border-radius: 2px; -moz-border-radius: 2px; @@ -1834,12 +1834,12 @@ textarea { border-right: 7px solid transparent; content: ""; } - + .bi-combo.bi-combo-popup { display: block !important; visibility: visible !important; } - + .bi-search-text-value-combo .trigger-icon-button { font-size: 16px; } @@ -1858,7 +1858,7 @@ textarea { .bi-search-text-value-combo.combo-show .trigger-down { display: none; } - + .bi-text-value-combo.combo-error .bi-select-text-trigger .bi-label { color: #ff4949; } @@ -1869,7 +1869,7 @@ textarea { .bi-search-editor .search-font { font-size: 16px; } - + /*************BI.SearchEditor******************/ .bi-small-search-editor .bi-editor { font-size: 12px; @@ -1886,7 +1886,7 @@ textarea { .bi-small-search-editor .search-font { font-size: 18px; } - + .bi-sign-initial-editor .sign-initial-editor-text { font-size: 14px; } @@ -2427,14 +2427,14 @@ li.CodeMirror-hint-active { .bi-all-count-pager .all-pager-next { font-size: 16px; } - + .bi-direction-pager .direction-pager-prev { font-size: 16px; } .bi-direction-pager .direction-pager-next { font-size: 16px; } - + .bi-pager .page-item { -webkit-border-radius: 2px; -moz-border-radius: 2px; @@ -2839,13 +2839,13 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-theme-dark #body .bi-button.button-common.disabled.ghost .b-font:before { color: #ffffff !important; } - + .bi-single-select-icon-text-item:active .b-font:before, .bi-single-select-icon-text-item.active .b-font:before { color: #3685f2; } - - + + .bi-switch { -webkit-border-radius: 40px 40px 40px 40px; -moz-border-radius: 40px 40px 40px 40px; @@ -2877,19 +2877,19 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, margin: 1px 1px; display: inline-block; } - - + + .bi-multifile-editor .multifile-editor { text-align: right; cursor: pointer; font-size: 100px; z-index: 2; } - - - - - + + + + + .bi-textarea-editor { overflow: hidden; overflow-x: hidden; @@ -2971,11 +2971,11 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, background: #feeed7; color: #faaa39; } - + .bi-tip { position: fixed !important; } - + .bi-toast { font-size: 14px; color: #ffffff; @@ -3000,7 +3000,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-toast .toast-icon { font-size: 16px; } - + .bi-tooltip { max-width: 250px; -webkit-border-radius: 2px; @@ -3064,13 +3064,13 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-theme-dark .bi-collection-table-cell.first-col { border-left: 1px solid #525466; } - + .bi-quick-collection-table > div > .bi-collection { overflow: hidden !important; overflow-x: hidden !important; overflow-y: hidden !important; } - + .bi-grid-table-cell { -webkit-box-sizing: border-box; /*Safari3.2+*/ @@ -3093,7 +3093,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-theme-dark .bi-grid-table-cell.first-col { border-left: 1px solid #525466; } - + .scrollbar-layout-main { box-sizing: border-box; outline: none; @@ -3207,7 +3207,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, bottom: 0; position: absolute; } - + .bi-table > .first-col { border-left: none; } @@ -3286,7 +3286,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, border-top: 1px solid #525466; border-left: 1px solid #525466; } - + .bi-resizable-table-cell .resizable-table-cell-resizer-container { cursor: ew-resize; z-index: 1; @@ -3298,7 +3298,7 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-resizable-table-cell .resizable-table-cell-resizer-container.suitable .resizable-table-cell-resizer-knob { background-color: #13cd66; } - + .bi-resizable-table .resizable-table-resizer { cursor: ew-resize; z-index: 1; @@ -3315,11 +3315,11 @@ body .bi-button.button-ignore.disabled.ghost .b-font:before, .bi-resizable-table .resizable-table-region-resizer.dragging .resizable-table-region-resizer-knob { background-color: #3f8ce8; } - + .bi-branch-tree .bi-branch-tree-view { min-width: 300px; } - + .bi-display-tree .ztree * { color: #999999; } @@ -3551,8 +3551,8 @@ ul.ztree.zTreeDragUL { padding:0; background:none; }*/ - - + + .bi-trigger .bi-trigger-icon-button { font-size: 16px; } @@ -3568,13 +3568,13 @@ ul.ztree.zTreeDragUL { .bi-combo-popup .trigger-down { display: none; } - + .bi-select-text-trigger { -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; } - + .bi-small-select-text-trigger { -webkit-border-radius: 2px; -moz-border-radius: 2px; @@ -3624,18 +3624,18 @@ ul.ztree.zTreeDragUL { .bi-down-list-popup .bi-down-list-item .list-item-text { max-width: 203px; } - + .bi-excel-table-header-cell { font-weight: bold; } - + .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-file-manager-nav-button .file-manager-nav-button-text { max-width: 200px; } @@ -3700,7 +3700,7 @@ ul.ztree.zTreeDragUL { .bi-interval-slider-label { min-height: 50px; } - + .bi-interval-slider { min-height: 70px; } @@ -3714,9 +3714,9 @@ ul.ztree.zTreeDragUL { -moz-border-radius: 2px; border-radius: 2px; } - - - + + + .bi-multidate-popup .multidate-popup-label { color: #3685f2; font-size: 14px; @@ -3733,13 +3733,13 @@ ul.ztree.zTreeDragUL { color: #3685f2; font-size: 14px; } - - + + .bi-multidate-segment .bi-multidate-editor { font-size: 14px; } - - + + .bi-multilayer-select-level-tree .tree-view { min-width: 100%; } @@ -3749,7 +3749,7 @@ ul.ztree.zTreeDragUL { .bi-multi-select-check-pane .multi-select-check-selected { text-decoration: underline; } - + .bi-multi-select-combo .multi-select-trigger-icon-button { font-size: 16px; } @@ -3765,7 +3765,7 @@ ul.ztree.zTreeDragUL { .bi-multi-select-combo.combo-show .trigger-down { display: none; } - + .bi-multi-select-insert-combo .multi-select-trigger-icon-button { font-size: 16px; } @@ -3781,8 +3781,8 @@ ul.ztree.zTreeDragUL { .bi-multi-select-insert-combo.combo-show .trigger-down { display: none; } - - + + .bi-multi-select-trigger { -webkit-border-radius: 2px 2px 2px 2px; -moz-border-radius: 2px 2px 2px 2px; @@ -3873,18 +3873,18 @@ ul.ztree.zTreeDragUL { -o-user-select: text; user-select: text; } - + .bi-preview-table-cell { min-height: 25px; min-width: 80px; } - + .bi-preview-table-header-cell { font-weight: bold; min-height: 25px; min-width: 80px; } - + .bi-preview-table { -webkit-user-select: text; -khtml-user-select: text; @@ -4011,7 +4011,7 @@ ul.ztree.zTreeDragUL { .bi-single-slider-label { min-height: 50px; } - + .bi-single-slider-normal { min-height: 30px; } diff --git a/dist/polyfill.js b/dist/polyfill.js index 47f771c9df..46ebb57940 100644 --- a/dist/polyfill.js +++ b/dist/polyfill.js @@ -1,244 +1,244 @@ -// Production steps of ECMA-262, Edition 5, 15.4.4.14 -// Reference: http://es5.github.io/#x15.4.4.14 -if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (searchElement, fromIndex) { - - var k; - - // 1. Let o be the result of calling ToObject passing - // the this value as the argument. - if (this == null) { - throw new TypeError("\"this\" is null or not defined"); - } - - var o = Object(this); - - // 2. Let lenValue be the result of calling the Get - // internal method of o with the argument "length". - // 3. Let len be ToUint32(lenValue). - var len = o.length >>> 0; - - // 4. If len is 0, return -1. - if (len === 0) { - return -1; - } - - // 5. If argument fromIndex was passed let n be - // ToInteger(fromIndex); else let n be 0. - var n = fromIndex | 0; - - // 6. If n >= len, return -1. - if (n >= len) { - return -1; - } - - // 7. If n >= 0, then Let k be n. - // 8. Else, n<0, Let k be len - abs(n). - // If k is less than 0, then let k be 0. - k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); - - // 9. Repeat, while k < len - while (k < len) { - // a. Let Pk be ToString(k). - // This is implicit for LHS operands of the in operator - // b. Let kPresent be the result of calling the - // HasProperty internal method of o with argument Pk. - // This step can be combined with c - // c. If kPresent is true, then - // i. Let elementK be the result of calling the Get - // internal method of o with the argument ToString(k). - // ii. Let same be the result of applying the - // Strict Equality Comparison Algorithm to - // searchElement and elementK. - // iii. If same is true, return k. - if (k in o && o[k] === searchElement) { - return k; - } - k++; - } - return -1; - }; -} -if (!Array.prototype.lastIndexOf) { - Array.prototype.lastIndexOf = function (searchElement /* , fromIndex*/) { - "use strict"; - - if (this === void 0 || this === null) { - throw new TypeError(); - } - - var n, k, - t = Object(this), - len = t.length >>> 0; - if (len === 0) { - return -1; - } - - n = len - 1; - if (arguments.length > 1) { - n = Number(arguments[1]); - if (n != n) { - n = 0; - } else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) { - n = (n > 0 || -1) * Math.floor(Math.abs(n)); - } - } - - for (k = n >= 0 - ? Math.min(n, len - 1) - : len - Math.abs(n); k >= 0; k--) { - if (k in t && t[k] === searchElement) { - return k; - } - } - return -1; - }; -} -/** - * 特殊情况 - * Created by wang on 15/6/23. - */ -// 解决console未定义问题 guy -window.console = window.console || (function () { - var c = {}; - c.log = c.warn = c.debug = c.info = c.error = c.time = c.dir = c.profile - = c.clear = c.exception = c.trace = c.assert = function () { - }; - return c; -})(); -if (!Function.prototype.bind) { - Function.prototype.bind = function(oThis) { - if (typeof this !== 'function') { - // closest thing possible to the ECMAScript 5 - // internal IsCallable function - throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); - } - - var aArgs = Array.prototype.slice.call(arguments, 1), - fToBind = this, - fNOP = function() {}, - fBound = function() { - return fToBind.apply(this instanceof fNOP - ? this - : oThis, - // 获取调用时(fBound)的传参.bind 返回的函数入参往往是这么传递的 - aArgs.concat(Array.prototype.slice.call(arguments))); - }; - - // 维护原型关系 - if (this.prototype) { - // Function.prototype doesn't have a prototype property - fNOP.prototype = this.prototype; - } - fBound.prototype = new fNOP(); - - return fBound; - }; -}/* - * 前端缓存 - */ -window.localStorage || (window.localStorage = { - items: {}, - setItem: function (k, v) { - BI.Cache.addCookie(k, v); - }, - getItem: function (k) { - return BI.Cache.getCookie(k); - }, - removeItem: function (k) { - BI.Cache.deleteCookie(k); - }, - key: function () { - - }, - clear: function () { - this.items = {}; - } -}); -if (!Object.keys) { - Object.keys = function(o) { - if (o !== Object(o)) { - throw new TypeError('Object.keys called on a non-object'); - } - // fix的问题 - var falsy; - var skipArray = { - __ob__: falsy, - $accessors: falsy, - $vbthis: falsy, - $vbsetter: falsy - }; - var k = [], p; - for (p in o) { - if (!(p in skipArray)) { - if (Object.prototype.hasOwnProperty.call(o, p)) { - k.push(p); - } - } - } - return k; - }; -} - -if (!Array.isArray) { - Array.isArray = function(arg) { - return Object.prototype.toString.call(arg) === '[object Array]'; - }; -} - -// https://stackoverflow.com/questions/10919915/ie8-getprototypeof-method -if (typeof Object.getPrototypeOf !== "function") { - Object.getPrototypeOf = "".__proto__ === String.prototype - ? function (object) { - return object.__proto__; - } - : function (object) { - // May break if the constructor has been tampered with - return object.constructor.prototype; - }; -}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 = {}; - }; -}// 修复ie9下sort方法的bug -!function (window) { - var ua = window.navigator.userAgent.toLowerCase(), - reg = /msie|applewebkit.+safari/; - if (reg.test(ua)) { - var _sort = Array.prototype.sort; - Array.prototype.sort = function (fn) { - if (!!fn && typeof fn === "function") { - if (this.length < 2) { - return this; - } - var i = 0, j = i + 1, l = this.length, tmp, r = false, t = 0; - for (; i < l; i++) { - for (j = i + 1; j < l; j++) { - t = fn.call(this, this[i], this[j]); - r = (typeof t === "number" ? t : - t ? 1 : 0) > 0; - if (r === true) { - tmp = this[i]; - this[i] = this[j]; - this[j] = tmp; - } - } - } - return this; - } - return _sort.call(this); - - }; - } +// Production steps of ECMA-262, Edition 5, 15.4.4.14 +// Reference: http://es5.github.io/#x15.4.4.14 +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (searchElement, fromIndex) { + + var k; + + // 1. Let o be the result of calling ToObject passing + // the this value as the argument. + if (this == null) { + throw new TypeError("\"this\" is null or not defined"); + } + + var o = Object(this); + + // 2. Let lenValue be the result of calling the Get + // internal method of o with the argument "length". + // 3. Let len be ToUint32(lenValue). + var len = o.length >>> 0; + + // 4. If len is 0, return -1. + if (len === 0) { + return -1; + } + + // 5. If argument fromIndex was passed let n be + // ToInteger(fromIndex); else let n be 0. + var n = fromIndex | 0; + + // 6. If n >= len, return -1. + if (n >= len) { + return -1; + } + + // 7. If n >= 0, then Let k be n. + // 8. Else, n<0, Let k be len - abs(n). + // If k is less than 0, then let k be 0. + k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); + + // 9. Repeat, while k < len + while (k < len) { + // a. Let Pk be ToString(k). + // This is implicit for LHS operands of the in operator + // b. Let kPresent be the result of calling the + // HasProperty internal method of o with argument Pk. + // This step can be combined with c + // c. If kPresent is true, then + // i. Let elementK be the result of calling the Get + // internal method of o with the argument ToString(k). + // ii. Let same be the result of applying the + // Strict Equality Comparison Algorithm to + // searchElement and elementK. + // iii. If same is true, return k. + if (k in o && o[k] === searchElement) { + return k; + } + k++; + } + return -1; + }; +} +if (!Array.prototype.lastIndexOf) { + Array.prototype.lastIndexOf = function (searchElement /* , fromIndex*/) { + "use strict"; + + if (this === void 0 || this === null) { + throw new TypeError(); + } + + var n, k, + t = Object(this), + len = t.length >>> 0; + if (len === 0) { + return -1; + } + + n = len - 1; + if (arguments.length > 1) { + n = Number(arguments[1]); + if (n != n) { + n = 0; + } else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) { + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + } + + for (k = n >= 0 + ? Math.min(n, len - 1) + : len - Math.abs(n); k >= 0; k--) { + if (k in t && t[k] === searchElement) { + return k; + } + } + return -1; + }; +} +/** + * 特殊情况 + * Created by wang on 15/6/23. + */ +// 解决console未定义问题 guy +window.console = window.console || (function () { + var c = {}; + c.log = c.warn = c.debug = c.info = c.error = c.time = c.dir = c.profile + = c.clear = c.exception = c.trace = c.assert = function () { + }; + return c; +})(); +if (!Function.prototype.bind) { + Function.prototype.bind = function(oThis) { + if (typeof this !== 'function') { + // closest thing possible to the ECMAScript 5 + // internal IsCallable function + throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); + } + + var aArgs = Array.prototype.slice.call(arguments, 1), + fToBind = this, + fNOP = function() {}, + fBound = function() { + return fToBind.apply(this instanceof fNOP + ? this + : oThis, + // 获取调用时(fBound)的传参.bind 返回的函数入参往往是这么传递的 + aArgs.concat(Array.prototype.slice.call(arguments))); + }; + + // 维护原型关系 + if (this.prototype) { + // Function.prototype doesn't have a prototype property + fNOP.prototype = this.prototype; + } + fBound.prototype = new fNOP(); + + return fBound; + }; +}/* + * 前端缓存 + */ +window.localStorage || (window.localStorage = { + items: {}, + setItem: function (k, v) { + BI.Cache.addCookie(k, v); + }, + getItem: function (k) { + return BI.Cache.getCookie(k); + }, + removeItem: function (k) { + BI.Cache.deleteCookie(k); + }, + key: function () { + + }, + clear: function () { + this.items = {}; + } +}); +if (!Object.keys) { + Object.keys = function(o) { + if (o !== Object(o)) { + throw new TypeError('Object.keys called on a non-object'); + } + // fix的问题 + var falsy; + var skipArray = { + __ob__: falsy, + $accessors: falsy, + $vbthis: falsy, + $vbsetter: falsy + }; + var k = [], p; + for (p in o) { + if (!(p in skipArray)) { + if (Object.prototype.hasOwnProperty.call(o, p)) { + k.push(p); + } + } + } + return k; + }; +} + +if (!Array.isArray) { + Array.isArray = function(arg) { + return Object.prototype.toString.call(arg) === '[object Array]'; + }; +} + +// https://stackoverflow.com/questions/10919915/ie8-getprototypeof-method +if (typeof Object.getPrototypeOf !== "function") { + Object.getPrototypeOf = "".__proto__ === String.prototype + ? function (object) { + return object.__proto__; + } + : function (object) { + // May break if the constructor has been tampered with + return object.constructor.prototype; + }; +}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 = {}; + }; +}// 修复ie9下sort方法的bug +!function (window) { + var ua = window.navigator.userAgent.toLowerCase(), + reg = /msie|applewebkit.+safari/; + if (reg.test(ua)) { + var _sort = Array.prototype.sort; + Array.prototype.sort = function (fn) { + if (!!fn && typeof fn === "function") { + if (this.length < 2) { + return this; + } + var i = 0, j = i + 1, l = this.length, tmp, r = false, t = 0; + for (; i < l; i++) { + for (j = i + 1; j < l; j++) { + t = fn.call(this, this[i], this[j]); + r = (typeof t === "number" ? t : + t ? 1 : 0) > 0; + if (r === true) { + tmp = this[i]; + this[i] = this[j]; + this[j] = tmp; + } + } + } + return this; + } + return _sort.call(this); + + }; + } }(window); \ No newline at end of file diff --git a/dist/router.js b/dist/router.js index a84085b737..ee6eb92fdf 100644 --- a/dist/router.js +++ b/dist/router.js @@ -1,585 +1,585 @@ -(function () { - var 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; - } - }; - - // 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; - }); - } - - }); - - // 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 = function () { - this.handlers = []; - this.checkUrl = _.bind(this.checkUrl, this); - - // 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 _.some(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; +(function () { + var 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; + } + }; + + // 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; + }); + } + + }); + + // 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 = function () { + this.handlers = []; + this.checkUrl = _.bind(this.checkUrl, this); + + // 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 _.some(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; }()); \ No newline at end of file diff --git a/dist/widget.css b/dist/widget.css index d1909068a0..3e2fc01ebe 100644 --- a/dist/widget.css +++ b/dist/widget.css @@ -9,18 +9,18 @@ .bi-down-list-popup .bi-down-list-item .list-item-text { max-width: 203px; } - + .bi-excel-table-header-cell { font-weight: bold; } - + .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-file-manager-nav-button .file-manager-nav-button-text { max-width: 200px; } @@ -85,7 +85,7 @@ .bi-interval-slider-label { min-height: 50px; } - + .bi-interval-slider { min-height: 70px; } @@ -99,9 +99,9 @@ -moz-border-radius: 2px; border-radius: 2px; } - - - + + + .bi-multidate-popup .multidate-popup-label { color: #3685f2; font-size: 14px; @@ -118,13 +118,13 @@ color: #3685f2; font-size: 14px; } - - + + .bi-multidate-segment .bi-multidate-editor { font-size: 14px; } - - + + .bi-multilayer-select-level-tree .tree-view { min-width: 100%; } @@ -134,7 +134,7 @@ .bi-multi-select-check-pane .multi-select-check-selected { text-decoration: underline; } - + .bi-multi-select-combo .multi-select-trigger-icon-button { font-size: 16px; } @@ -150,7 +150,7 @@ .bi-multi-select-combo.combo-show .trigger-down { display: none; } - + .bi-multi-select-insert-combo .multi-select-trigger-icon-button { font-size: 16px; } @@ -166,8 +166,8 @@ .bi-multi-select-insert-combo.combo-show .trigger-down { display: none; } - - + + .bi-multi-select-trigger { -webkit-border-radius: 2px 2px 2px 2px; -moz-border-radius: 2px 2px 2px 2px; @@ -258,18 +258,18 @@ -o-user-select: text; user-select: text; } - + .bi-preview-table-cell { min-height: 25px; min-width: 80px; } - + .bi-preview-table-header-cell { font-weight: bold; min-height: 25px; min-width: 80px; } - + .bi-preview-table { -webkit-user-select: text; -khtml-user-select: text; @@ -396,7 +396,7 @@ .bi-single-slider-label { min-height: 50px; } - + .bi-single-slider-normal { min-height: 30px; } diff --git a/src/css/base/colorchooser/colorchooser.css b/src/css/base/colorchooser/colorchooser.css index f49d79fc24..a7880faf5c 100644 --- a/src/css/base/colorchooser/colorchooser.css +++ b/src/css/base/colorchooser/colorchooser.css @@ -3,7 +3,7 @@ filter: alpha(opacity=50); background-color: #ffffff; } - + .bi-color-chooser-trigger { -webkit-border-radius: 2px; -moz-border-radius: 2px; diff --git a/src/css/base/combo/combo.css b/src/css/base/combo/combo.css index 7a5a144f86..e2d4860df4 100644 --- a/src/css/base/combo/combo.css +++ b/src/css/base/combo/combo.css @@ -106,12 +106,12 @@ border-right: 7px solid transparent; content: ""; } - + .bi-combo.bi-combo-popup { display: block !important; visibility: visible !important; } - + .bi-search-text-value-combo .trigger-icon-button { font-size: 16px; } @@ -130,7 +130,7 @@ .bi-search-text-value-combo.combo-show .trigger-down { display: none; } - + .bi-text-value-combo.combo-error .bi-select-text-trigger .bi-label { color: #ff4949; } diff --git a/src/css/base/editor/editor.css b/src/css/base/editor/editor.css index 1a55535c16..dbd49dc9a7 100644 --- a/src/css/base/editor/editor.css +++ b/src/css/base/editor/editor.css @@ -5,7 +5,7 @@ .bi-search-editor .search-font { font-size: 16px; } - + /*************BI.SearchEditor******************/ .bi-small-search-editor .bi-editor { font-size: 12px; @@ -22,7 +22,7 @@ .bi-small-search-editor .search-font { font-size: 18px; } - + .bi-sign-initial-editor .sign-initial-editor-text { font-size: 14px; } diff --git a/src/css/base/pager/pager.css b/src/css/base/pager/pager.css index b28d243600..0fa934087d 100644 --- a/src/css/base/pager/pager.css +++ b/src/css/base/pager/pager.css @@ -4,14 +4,14 @@ .bi-all-count-pager .all-pager-next { font-size: 16px; } - + .bi-direction-pager .direction-pager-prev { font-size: 16px; } .bi-direction-pager .direction-pager-next { font-size: 16px; } - + .bi-pager .page-item { -webkit-border-radius: 2px; -moz-border-radius: 2px; diff --git a/src/css/base/single/button/item.css b/src/css/base/single/button/item.css index 7711adc00a..f3f42583c9 100644 --- a/src/css/base/single/button/item.css +++ b/src/css/base/single/button/item.css @@ -1,7 +1,7 @@ - + .bi-single-select-icon-text-item:active .b-font:before, .bi-single-select-icon-text-item.active .b-font:before { color: #3685f2; } - - + + diff --git a/src/css/base/single/editor/editor.css b/src/css/base/single/editor/editor.css index 78a27e88dd..0e68a8c171 100644 --- a/src/css/base/single/editor/editor.css +++ b/src/css/base/single/editor/editor.css @@ -14,19 +14,19 @@ margin: 1px 1px; display: inline-block; } - - + + .bi-multifile-editor .multifile-editor { text-align: right; cursor: pointer; font-size: 100px; z-index: 2; } - - - - - + + + + + .bi-textarea-editor { overflow: hidden; overflow-x: hidden; diff --git a/src/css/base/single/tip/tip.css b/src/css/base/single/tip/tip.css index bdc76432fb..6f6575cf63 100644 --- a/src/css/base/single/tip/tip.css +++ b/src/css/base/single/tip/tip.css @@ -19,11 +19,11 @@ background: #feeed7; color: #faaa39; } - + .bi-tip { position: fixed !important; } - + .bi-toast { font-size: 14px; color: #ffffff; @@ -48,7 +48,7 @@ .bi-toast .toast-icon { font-size: 16px; } - + .bi-tooltip { max-width: 250px; -webkit-border-radius: 2px; diff --git a/src/css/base/table/table.css b/src/css/base/table/table.css index b9ee529342..78ce840f30 100644 --- a/src/css/base/table/table.css +++ b/src/css/base/table/table.css @@ -20,13 +20,13 @@ .bi-theme-dark .bi-collection-table-cell.first-col { border-left: 1px solid #525466; } - + .bi-quick-collection-table > div > .bi-collection { overflow: hidden !important; overflow-x: hidden !important; overflow-y: hidden !important; } - + .bi-grid-table-cell { -webkit-box-sizing: border-box; /*Safari3.2+*/ @@ -49,7 +49,7 @@ .bi-theme-dark .bi-grid-table-cell.first-col { border-left: 1px solid #525466; } - + .scrollbar-layout-main { box-sizing: border-box; outline: none; @@ -163,7 +163,7 @@ bottom: 0; position: absolute; } - + .bi-table > .first-col { border-left: none; } @@ -242,7 +242,7 @@ border-top: 1px solid #525466; border-left: 1px solid #525466; } - + .bi-resizable-table-cell .resizable-table-cell-resizer-container { cursor: ew-resize; z-index: 1; @@ -254,7 +254,7 @@ .bi-resizable-table-cell .resizable-table-cell-resizer-container.suitable .resizable-table-cell-resizer-knob { background-color: #13cd66; } - + .bi-resizable-table .resizable-table-resizer { cursor: ew-resize; z-index: 1; @@ -271,4 +271,4 @@ .bi-resizable-table .resizable-table-region-resizer.dragging .resizable-table-region-resizer-knob { background-color: #3f8ce8; } - + diff --git a/src/css/base/tree/tree.css b/src/css/base/tree/tree.css index 9ae37a8a11..127bb62753 100644 --- a/src/css/base/tree/tree.css +++ b/src/css/base/tree/tree.css @@ -1,7 +1,7 @@ .bi-branch-tree .bi-branch-tree-view { min-width: 300px; } - + .bi-display-tree .ztree * { color: #999999; } diff --git a/src/css/base/trigger/trigger.css b/src/css/base/trigger/trigger.css index 463ef61330..23f9af2060 100644 --- a/src/css/base/trigger/trigger.css +++ b/src/css/base/trigger/trigger.css @@ -1,5 +1,5 @@ - - + + .bi-trigger .bi-trigger-icon-button { font-size: 16px; } @@ -15,13 +15,13 @@ .bi-combo-popup .trigger-down { display: none; } - + .bi-select-text-trigger { -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; } - + .bi-small-select-text-trigger { -webkit-border-radius: 2px; -moz-border-radius: 2px; diff --git a/src/css/core/wrapper/flex.css b/src/css/core/wrapper/flex.css index 9a7e072f0e..6f72eb95fd 100644 --- a/src/css/core/wrapper/flex.css +++ b/src/css/core/wrapper/flex.css @@ -38,7 +38,7 @@ -o-align-items: center; align-items: center; } - + .bi-flex-horizontal-layout { display: box; /* OLD - Android 4.4- */ @@ -109,7 +109,7 @@ -o-align-items: flex-end; align-items: flex-end; } - + .bi-flex-vertical-center { display: box; /* OLD - Android 4.4- */ @@ -186,7 +186,7 @@ -o-align-items: stretch; align-items: stretch; } - + .bi-flex-wrapper-center-layout .flex-wrapper-center-layout-wrapper { display: box; /* OLD - Android 4.4- */ @@ -230,7 +230,7 @@ min-height: 100%; float: left; } - + .bi-flex-wrapper-horizontal-layout .flex-wrapper-horizontal-layout-wrapper { display: box; /* OLD - Android 4.4- */ @@ -300,7 +300,7 @@ -o-align-items: flex-end; align-items: flex-end; } - + .bi-flex-wrapper-vertical-center .flex-wrapper-vertical-center-wrapper { display: box; /* OLD - Android 4.4- */ diff --git a/src/css/core/wrapper/inline.css b/src/css/core/wrapper/inline.css index dec7d7ec9c..df745a62c3 100644 --- a/src/css/core/wrapper/inline.css +++ b/src/css/core/wrapper/inline.css @@ -5,7 +5,7 @@ vertical-align: middle; content: ' '; } - + .bi-inline-vertical-adapt-layout:after { display: inline-block; width: 0; diff --git a/src/css/widget/exceltable/exceltable.css b/src/css/widget/exceltable/exceltable.css index ef99484d46..8a52ce9dd9 100644 --- a/src/css/widget/exceltable/exceltable.css +++ b/src/css/widget/exceltable/exceltable.css @@ -1,8 +1,8 @@ - + .bi-excel-table-header-cell { font-weight: bold; } - + .bi-excel-table > div.bottom-right > div > div > table { border-right: 1px solid #d4dadd; } diff --git a/src/css/widget/filemanager/items/item.css b/src/css/widget/filemanager/items/item.css index 8b13789179..d3f5a12faa 100644 --- a/src/css/widget/filemanager/items/item.css +++ b/src/css/widget/filemanager/items/item.css @@ -1 +1 @@ - + diff --git a/src/css/widget/intervalslider/intervalslider.css b/src/css/widget/intervalslider/intervalslider.css index 18bcc2934f..f9388f670a 100644 --- a/src/css/widget/intervalslider/intervalslider.css +++ b/src/css/widget/intervalslider/intervalslider.css @@ -1,7 +1,7 @@ .bi-interval-slider-label { min-height: 50px; } - + .bi-interval-slider { min-height: 70px; } diff --git a/src/css/widget/multidate/multidate.css b/src/css/widget/multidate/multidate.css index 5fac983678..fe217be02c 100644 --- a/src/css/widget/multidate/multidate.css +++ b/src/css/widget/multidate/multidate.css @@ -3,9 +3,9 @@ -moz-border-radius: 2px; border-radius: 2px; } - - - + + + .bi-multidate-popup .multidate-popup-label { color: #3685f2; font-size: 14px; @@ -22,10 +22,10 @@ color: #3685f2; font-size: 14px; } - - + + .bi-multidate-segment .bi-multidate-editor { font-size: 14px; } - - + + diff --git a/src/css/widget/multiselect/check/multiselect.css b/src/css/widget/multiselect/check/multiselect.css index 016c3c3f6d..b8668a4c7e 100644 --- a/src/css/widget/multiselect/check/multiselect.css +++ b/src/css/widget/multiselect/check/multiselect.css @@ -1,4 +1,4 @@ .bi-multi-select-check-pane .multi-select-check-selected { text-decoration: underline; } - + diff --git a/src/css/widget/multiselect/multiselect.css b/src/css/widget/multiselect/multiselect.css index 8c0b0adf2b..7bf8d5fc13 100644 --- a/src/css/widget/multiselect/multiselect.css +++ b/src/css/widget/multiselect/multiselect.css @@ -13,7 +13,7 @@ .bi-multi-select-combo.combo-show .trigger-down { display: none; } - + .bi-multi-select-insert-combo .multi-select-trigger-icon-button { font-size: 16px; } @@ -29,8 +29,8 @@ .bi-multi-select-insert-combo.combo-show .trigger-down { display: none; } - - + + .bi-multi-select-trigger { -webkit-border-radius: 2px 2px 2px 2px; -moz-border-radius: 2px 2px 2px 2px; diff --git a/src/css/widget/pagetable/pagetable.css b/src/css/widget/pagetable/pagetable.css index 3c575f5242..22bc743545 100644 --- a/src/css/widget/pagetable/pagetable.css +++ b/src/css/widget/pagetable/pagetable.css @@ -6,4 +6,4 @@ -o-user-select: text; user-select: text; } - + diff --git a/src/css/widget/previewtable/previewtable.css b/src/css/widget/previewtable/previewtable.css index 043b8d6cfa..ab9905255e 100644 --- a/src/css/widget/previewtable/previewtable.css +++ b/src/css/widget/previewtable/previewtable.css @@ -2,13 +2,13 @@ min-height: 25px; min-width: 80px; } - + .bi-preview-table-header-cell { font-weight: bold; min-height: 25px; min-width: 80px; } - + .bi-preview-table { -webkit-user-select: text; -khtml-user-select: text; diff --git a/src/css/widget/singleslider/singlelider.css b/src/css/widget/singleslider/singlelider.css index 89c22bab6a..b71d5ade1a 100644 --- a/src/css/widget/singleslider/singlelider.css +++ b/src/css/widget/singleslider/singlelider.css @@ -1,7 +1,7 @@ .bi-single-slider-label { min-height: 50px; } - + .bi-single-slider-normal { min-height: 30px; } diff --git a/utils/utils.js b/utils/utils.js index 980ffcd351..35c80b9b3b 100644 --- a/utils/utils.js +++ b/utils/utils.js @@ -10001,562 +10001,562 @@ root._ = lodash; } }.call(this)); -/** - * Created by richie on 15/7/8. - */ -/** - * 初始化BI对象 - */ -if (window.BI == null) { - window.BI = {}; -}/** - * 常量 - */ - -_.extend(BI, { - MAX: 0xfffffffffffffff, - MIN: -0xfffffffffffffff, - EVENT_RESPONSE_TIME: 200, - zIndex_layer: 1e5, - zIndex_popover: 1e6, - zIndex_popup: 1e7, - zIndex_masker: 1e8, - zIndex_tip: 1e9, - emptyStr: "", - emptyFn: function () { - }, - empty: null, - Key: { - 48: "0", - 49: "1", - 50: "2", - 51: "3", - 52: "4", - 53: "5", - 54: "6", - 55: "7", - 56: "8", - 57: "9", - 65: "a", - 66: "b", - 67: "c", - 68: "d", - 69: "e", - 70: "f", - 71: "g", - 72: "h", - 73: "i", - 74: "j", - 75: "k", - 76: "l", - 77: "m", - 78: "n", - 79: "o", - 80: "p", - 81: "q", - 82: "r", - 83: "s", - 84: "t", - 85: "u", - 86: "v", - 87: "w", - 88: "x", - 89: "y", - 90: "z", - 96: "0", - 97: "1", - 98: "2", - 99: "3", - 100: "4", - 101: "5", - 102: "6", - 103: "7", - 104: "8", - 105: "9", - 106: "*", - 107: "+", - 109: "-", - 110: ".", - 111: "/" - }, - 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", - Stretch: "stretch" - }, - VerticalAlign: { - Middle: "middle", - Top: "top", - Bottom: "bottom", - Stretch: "stretch" - } -});/** - * 对数组对象的扩展 - * @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]); - } - } -}); -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 (value, name) { - 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; - } - 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; - } +/** + * Created by richie on 15/7/8. + */ +/** + * 初始化BI对象 + */ +if (window.BI == null) { + window.BI = {}; +}/** + * 常量 + */ + +_.extend(BI, { + MAX: 0xfffffffffffffff, + MIN: -0xfffffffffffffff, + EVENT_RESPONSE_TIME: 200, + zIndex_layer: 1e5, + zIndex_popover: 1e6, + zIndex_popup: 1e7, + zIndex_masker: 1e8, + zIndex_tip: 1e9, + emptyStr: "", + emptyFn: function () { + }, + empty: null, + Key: { + 48: "0", + 49: "1", + 50: "2", + 51: "3", + 52: "4", + 53: "5", + 54: "6", + 55: "7", + 56: "8", + 57: "9", + 65: "a", + 66: "b", + 67: "c", + 68: "d", + 69: "e", + 70: "f", + 71: "g", + 72: "h", + 73: "i", + 74: "j", + 75: "k", + 76: "l", + 77: "m", + 78: "n", + 79: "o", + 80: "p", + 81: "q", + 82: "r", + 83: "s", + 84: "t", + 85: "u", + 86: "v", + 87: "w", + 88: "x", + 89: "y", + 90: "z", + 96: "0", + 97: "1", + 98: "2", + 99: "3", + 100: "4", + 101: "5", + 102: "6", + 103: "7", + 104: "8", + 105: "9", + 106: "*", + 107: "+", + 109: "-", + 110: ".", + 111: "/" + }, + 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", + Stretch: "stretch" + }, + VerticalAlign: { + Middle: "middle", + Top: "top", + Bottom: "bottom", + Stretch: "stretch" + } +});/** + * 对数组对象的扩展 + * @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]); + } + } +}); +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 (value, name) { + 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; + } + 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; + } }); /** Constants used for time computations */ Date.SECOND = 1000; @@ -10790,26 +10790,26 @@ Date.prototype.print = function (str) { return str; }; -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; - }; +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; + }; };/** * 基本函数 * Create By GUY 2014\11\17 @@ -12285,4326 +12285,4326 @@ if (!window.BI) { }); } }); -})();/** - * 客户端观察者,主要处理事件的添加、删除、执行等 - * @class BI.OB - * @abstract - */ -BI.OB = function (config) { - var props = this.props; - if (BI.isFunction(this.props)) { - props = this.props(config); - } - this.options = (window.$ || window._).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 (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); - } - }, - - //释放当前对象 - _purgeRef: function(){ - if (this.options.ref) { - this.options.ref.call(null); - } - }, - - _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 (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._purgeRef(); - this.purgeListeners(); - } -});(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)); - } - return _numberFormat((-text) + "", format.substr(numMod + 1)); - - } - // 兼容格式处理负数的情况(copy:fr-jquery.format.js) - if (+text < 0 && format.charAt(0) !== "-") { - return _numberFormat((-text) + "", "-" + format); - } - - 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; - } - 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 = BI.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; - }; - - /** - * 将cjkEncode处理过的字符串转化为原始字符串 - * - * @static - * @param text 需要做解码的字符串 - * @return {String} 解码后的字符串 - */ - BI.cjkDecode = function (text) { - if (text == null) { - return ""; - } - // 查找没有 "[", 直接返回. kunsnat:数字的时候, 不支持indexOf方法, 也是直接返回. - if (!isNaN(text) || text.indexOf("[") == -1) { - return text; - } - - var newText = ""; - for (var i = 0; i < text.length; i++) { - var ch = text.charAt(i); - if (ch == "[") { - var rightIdx = text.indexOf("]", i + 1); - if (rightIdx > i + 1) { - var subText = text.substring(i + 1, rightIdx); - // james:主要是考虑[CDATA[]]这样的值的出现 - if (subText.length > 0) { - ch = String.fromCharCode(eval("0x" + subText)); - } - - i = rightIdx; - } - } - - newText += ch; - } - - return newText; - }; - - // replace the html special tags - BI.htmlEncode = function (text) { - return (text == null) ? "" : String(text).replace(/&/g, "&").replace(/\"/g, """).replace(//g, ">").replace(/\s/g, " "); - }; - // html decode - BI.htmlDecode = function (text) { - return (text == null) ? "" : String(text).replace(/&/g, "&").replace(/"/g, "\"").replace(/</g, "<").replace(/>/g, ">").replace(/ /g, " "); - }; - - BI.cjkEncodeDO = function (o) { - if (BI.isPlainObject(o)) { - var result = {}; - _.each(o, function (v, k) { - 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; - - // 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); - } - 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) : window.JSON.parse(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 { - // 数字格式 - var s = []; - BI.clamp(s); - text = _numberFormat(text, fmt); - } - // ¤ - 货币格式 - text = text.replace(/¤/g, "¥"); - return text; - }; - - /** - * 将Java提供的日期格式字符串装换为JS识别的日期格式字符串 - * @class FR.parseFmt - * @param fmt 日期格式 - * @returns {String} - */ - BI.parseFmt = function (fmt) { - if (!fmt) { - return ""; - } - //日期 - fmt = String(fmt) - //年 - .replace(/y{4,}/g, "%Y")//yyyy的时候替换为Y - .replace(/y{2}/g, "%y")//yy的时候替换为y - //月 - .replace(/M{4,}/g, "%b")//MMMM的时候替换为b,八 - .replace(/M{3}/g, "%B")//MMM的时候替换为M,八月 - .replace(/M{2}/g, "%X")//MM的时候替换为X,08 - .replace(/M{1}/g, "%x")//M的时候替换为x,8 - .replace(/a{1}/g, "%p"); - //天 - if (new RegExp("d{2,}", "g").test(fmt)) { - fmt = fmt.replace(/d{2,}/g, "%d");//dd的时候替换为d - } else { - fmt = fmt.replace(/d{1}/g, "%e");//d的时候替换为j - } - //时 - if (new RegExp("h{2,}", "g").test(fmt)) {//12小时制 - fmt = fmt.replace(/h{2,}/g, "%I"); - } else { - fmt = fmt.replace(/h{1}/g, "%I"); - } - if (new RegExp("H{2,}", "g").test(fmt)) {//24小时制 - fmt = fmt.replace(/H{2,}/g, "%H"); - } else { - fmt = fmt.replace(/H{1}/g, "%H"); - } - fmt = fmt.replace(/m{2,}/g, "%M")//分 - //秒 - .replace(/s{2,}/g, "%S"); - - return fmt; - }; - - /** - * 把字符串按照对应的格式转化成日期对象 - * - * @example - * var result = FR.str2Date('2013-12-12', 'yyyy-MM-dd');//Thu Dec 12 2013 00:00:00 GMT+0800 - * - * @class FR.str2Date - * @param str 字符串 - * @param format 日期格式 - * @returns {*} - */ - BI.str2Date = function (str, format) { - if (typeof str != "string" || typeof format != "string") { - return null; - } - var fmt = BI.parseFmt(format); - return BI.parseDateTime(str, fmt); - }; - - /** - * 把日期对象按照指定格式转化成字符串 - * - * @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 = BI.leftPad(date.getMonth() + 1 + "", 2, "0"); - } - break; - case "d": // 日 - if (len > 1) { - str = BI.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 = BI.leftPad(hour + "", 2, "0"); - } else { - str = hour; - } - break; - case "H": // 时(24) - if (len > 1) { - str = BI.leftPad(date.getHours() + "", 2, "0"); - } else { - str = date.getHours(); - } - break; - case "m": - if (len > 1) { - str = BI.leftPad(date.getMinutes() + "", 2, "0"); - } else { - str = date.getMinutes(); - } - break; - case "s": - if (len > 1) { - str = BI.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; - } - var str = value + ""; - if (str.indexOf(".") === -1) { - return parseInt(str); - } - 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); - } - 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; - } - 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.parseDateTime(str, "HH:mm:ss"); - if (!isInvalidDate(dt)) { - return dt; - } - return new Date(); - - }; -})(); -(function () { - var constantInjection = {}; - BI.constant = function (xtype, cls) { - if (constantInjection[xtype] != null) { - console.error("constant:[" + xtype + "] has been registed"); - } - constantInjection[xtype] = cls; - }; - - var modelInjection = {}; - BI.model = function (xtype, cls) { - if (modelInjection[xtype] != null) { - console.error("model:[" + xtype + "] has been registed"); - } - modelInjection[xtype] = cls; - }; - - var storeInjection = {}; - BI.store = function (xtype, cls) { - if (storeInjection[xtype] != null) { - console.error("store:[" + xtype + "] has been registed"); - } - storeInjection[xtype] = cls; - }; - - var serviceInjection = {}; - BI.service = function (xtype, cls) { - if (serviceInjection[xtype] != null) { - console.error("service:[" + xtype + "] has been registed"); - } - serviceInjection[xtype] = cls; - }; - - var providerInjection = {}; - BI.provider = function (xtype, cls) { - if (providerInjection[xtype] != null) { - console.error("provider:[" + xtype + "] has been registed"); - } - providerInjection[xtype] = cls; - }; - - BI.config = function (type, configFn) { - if (constantInjection[type]) { - return constantInjection[type] = configFn(constantInjection[type]); - } - if (providerInjection[type]) { - if (!providers[type]) { - providers[type] = new providerInjection[type](); - } - return configFn(providers[type]); - } - BI.Plugin.configWidget(type, configFn); - }; - - var actions = {}; - var globalAction = []; - BI.action = function (type, actionFn) { - if (BI.isFunction(type)) { - globalAction.push(type); - return function () { - BI.remove(globalAction, actionFn); - }; - } - if (!actions[type]) { - actions[type] = []; - } - actions[type].push(actionFn); - return function () { - actions[type].remove(actionFn); - if (actions[type].length === 0) { - delete actions[type]; - } - }; - }; - - var points = {}; - BI.point = function (type, action, pointFn, after) { - if (!points[type]) { - points[type] = {}; - } - if (!points[type][action]) { - points[type][action] = {}; - } - if (!points[type][action][after ? "after" : "before"]) { - points[type][action][after ? "after" : "before"] = []; - } - points[type][action][after ? "after" : "before"].push(pointFn); - }; - - BI.Constants = { - getConstant: function (type) { - return constantInjection[type]; - } - }; - - var callPoint = function (inst, type) { - if (points[type]) { - for (var action in points[type]) { - var bfns = points[type][action].before; - if (bfns) { - BI.aspect.before(inst, action, function (bfns) { - return function () { - for (var i = 0, len = bfns.length; i < len; i++) { - try { - bfns[i].apply(inst, arguments); - } catch (e) { - console.error(e); - } - } - }; - }(bfns)); - } - var afns = points[type][action].after; - if (afns) { - BI.aspect.after(inst, action, function (afns) { - return function () { - for (var i = 0, len = afns.length; i < len; i++) { - try { - afns[i].apply(inst, arguments); - } catch (e) { - console.error(e); - } - } - }; - }(afns)); - } - } - } - }; - - BI.Models = { - getModel: function (type, config) { - var inst = new modelInjection[type](config); - callPoint(inst, type); - return inst; - } - }; - - var stores = {}; - - BI.Stores = { - getStore: function (type, config) { - if (stores[type]) { - return stores[type]; - } - stores[type] = new storeInjection[type](config); - callPoint(stores[type], type); - return stores[type]; - } - }; - - var services = {}; - - BI.Services = { - getService: function (type, config) { - if (services[type]) { - return services[type]; - } - services[type] = new serviceInjection[type](config); - callPoint(services[type], type); - return services[type]; - } - }; - - var providers = {}, providerInstance = {}; - - BI.Providers = { - getProvider: function (type, config) { - if (!providers[type]) { - providers[type] = new providerInjection[type](); - } - if (!providerInstance[type]) { - providerInstance[type] = new providers[type].$get()(config); - } - return providerInstance[type]; - } - }; - - BI.Actions = { - runAction: function (type, config) { - BI.each(actions[type], function (i, act) { - try { - act(config); - } catch (e) { - console.error(e); - } - }); - }, - runGlobalAction: function () { - var args = [].slice.call(arguments); - BI.each(globalAction, function (i, act) { - try { - act.apply(null, args); - } catch (e) { - console.error(e); - } - }); - } - }; -})(); -(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.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(BI.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]);} - return null; - }, - deleteCookie: function (name, path) { - var date = new Date(); - date.setTime(BI.getTime() - 10000); - var cookieString = name + "=v; expires=" + date.toGMTString(); - if (path) { - cookieString = cookieString + "; path=" + path; - } - document.cookie = cookieString; - } -};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); - } - 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; - } - 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; - } - var offsetPercentage = this._getOffsetPercentage(containerSize, offset, safeTotalSize); - - return Math.round(offsetPercentage * (totalSize - containerSize)); - - } -};/** - * 汉字拼音索引 - */ - -!(function () { - var _ChineseFirstPY = "YDYQSXMWZSSXJBYMGCCZQPSSQBYCDSCDQLDYLYBSSJGYZZJJFKCCLZDHWDWZJLJPFYYNWJJTMYHZWZHFLZPPQHGSCYYYNJQYXXGJHHSDSJNKKTMOMLCRXYPSNQSECCQZGGLLYJLMYZZSECYKYYHQWJSSGGYXYZYJWWKDJHYCHMYXJTLXJYQBYXZLDWRDJRWYSRLDZJPCBZJJBRCFTLECZSTZFXXZHTRQHYBDLYCZSSYMMRFMYQZPWWJJYFCRWFDFZQPYDDWYXKYJAWJFFXYPSFTZYHHYZYSWCJYXSCLCXXWZZXNBGNNXBXLZSZSBSGPYSYZDHMDZBQBZCWDZZYYTZHBTSYYBZGNTNXQYWQSKBPHHLXGYBFMJEBJHHGQTJCYSXSTKZHLYCKGLYSMZXYALMELDCCXGZYRJXSDLTYZCQKCNNJWHJTZZCQLJSTSTBNXBTYXCEQXGKWJYFLZQLYHYXSPSFXLMPBYSXXXYDJCZYLLLSJXFHJXPJBTFFYABYXBHZZBJYZLWLCZGGBTSSMDTJZXPTHYQTGLJSCQFZKJZJQNLZWLSLHDZBWJNCJZYZSQQYCQYRZCJJWYBRTWPYFTWEXCSKDZCTBZHYZZYYJXZCFFZZMJYXXSDZZOTTBZLQWFCKSZSXFYRLNYJMBDTHJXSQQCCSBXYYTSYFBXDZTGBCNSLCYZZPSAZYZZSCJCSHZQYDXLBPJLLMQXTYDZXSQJTZPXLCGLQTZWJBHCTSYJSFXYEJJTLBGXSXJMYJQQPFZASYJNTYDJXKJCDJSZCBARTDCLYJQMWNQNCLLLKBYBZZSYHQQLTWLCCXTXLLZNTYLNEWYZYXCZXXGRKRMTCNDNJTSYYSSDQDGHSDBJGHRWRQLYBGLXHLGTGXBQJDZPYJSJYJCTMRNYMGRZJCZGJMZMGXMPRYXKJNYMSGMZJYMKMFXMLDTGFBHCJHKYLPFMDXLQJJSMTQGZSJLQDLDGJYCALCMZCSDJLLNXDJFFFFJCZFMZFFPFKHKGDPSXKTACJDHHZDDCRRCFQYJKQCCWJDXHWJLYLLZGCFCQDSMLZPBJJPLSBCJGGDCKKDEZSQCCKJGCGKDJTJDLZYCXKLQSCGJCLTFPCQCZGWPJDQYZJJBYJHSJDZWGFSJGZKQCCZLLPSPKJGQJHZZLJPLGJGJJTHJJYJZCZMLZLYQBGJWMLJKXZDZNJQSYZMLJLLJKYWXMKJLHSKJGBMCLYYMKXJQLBMLLKMDXXKWYXYSLMLPSJQQJQXYXFJTJDXMXXLLCXQBSYJBGWYMBGGBCYXPJYGPEPFGDJGBHBNSQJYZJKJKHXQFGQZKFHYGKHDKLLSDJQXPQYKYBNQSXQNSZSWHBSXWHXWBZZXDMNSJBSBKBBZKLYLXGWXDRWYQZMYWSJQLCJXXJXKJEQXSCYETLZHLYYYSDZPAQYZCMTLSHTZCFYZYXYLJSDCJQAGYSLCQLYYYSHMRQQKLDXZSCSSSYDYCJYSFSJBFRSSZQSBXXPXJYSDRCKGJLGDKZJZBDKTCSYQPYHSTCLDJDHMXMCGXYZHJDDTMHLTXZXYLYMOHYJCLTYFBQQXPFBDFHHTKSQHZYYWCNXXCRWHOWGYJLEGWDQCWGFJYCSNTMYTOLBYGWQWESJPWNMLRYDZSZTXYQPZGCWXHNGPYXSHMYQJXZTDPPBFYHZHTJYFDZWKGKZBLDNTSXHQEEGZZYLZMMZYJZGXZXKHKSTXNXXWYLYAPSTHXDWHZYMPXAGKYDXBHNHXKDPJNMYHYLPMGOCSLNZHKXXLPZZLBMLSFBHHGYGYYGGBHSCYAQTYWLXTZQCEZYDQDQMMHTKLLSZHLSJZWFYHQSWSCWLQAZYNYTLSXTHAZNKZZSZZLAXXZWWCTGQQTDDYZTCCHYQZFLXPSLZYGPZSZNGLNDQTBDLXGTCTAJDKYWNSYZLJHHZZCWNYYZYWMHYCHHYXHJKZWSXHZYXLYSKQYSPSLYZWMYPPKBYGLKZHTYXAXQSYSHXASMCHKDSCRSWJPWXSGZJLWWSCHSJHSQNHCSEGNDAQTBAALZZMSSTDQJCJKTSCJAXPLGGXHHGXXZCXPDMMHLDGTYBYSJMXHMRCPXXJZCKZXSHMLQXXTTHXWZFKHCCZDYTCJYXQHLXDHYPJQXYLSYYDZOZJNYXQEZYSQYAYXWYPDGXDDXSPPYZNDLTWRHXYDXZZJHTCXMCZLHPYYYYMHZLLHNXMYLLLMDCPPXHMXDKYCYRDLTXJCHHZZXZLCCLYLNZSHZJZZLNNRLWHYQSNJHXYNTTTKYJPYCHHYEGKCTTWLGQRLGGTGTYGYHPYHYLQYQGCWYQKPYYYTTTTLHYHLLTYTTSPLKYZXGZWGPYDSSZZDQXSKCQNMJJZZBXYQMJRTFFBTKHZKBXLJJKDXJTLBWFZPPTKQTZTGPDGNTPJYFALQMKGXBDCLZFHZCLLLLADPMXDJHLCCLGYHDZFGYDDGCYYFGYDXKSSEBDHYKDKDKHNAXXYBPBYYHXZQGAFFQYJXDMLJCSQZLLPCHBSXGJYNDYBYQSPZWJLZKSDDTACTBXZDYZYPJZQSJNKKTKNJDJGYYPGTLFYQKASDNTCYHBLWDZHBBYDWJRYGKZYHEYYFJMSDTYFZJJHGCXPLXHLDWXXJKYTCYKSSSMTWCTTQZLPBSZDZWZXGZAGYKTYWXLHLSPBCLLOQMMZSSLCMBJCSZZKYDCZJGQQDSMCYTZQQLWZQZXSSFPTTFQMDDZDSHDTDWFHTDYZJYQJQKYPBDJYYXTLJHDRQXXXHAYDHRJLKLYTWHLLRLLRCXYLBWSRSZZSYMKZZHHKYHXKSMDSYDYCJPBZBSQLFCXXXNXKXWYWSDZYQOGGQMMYHCDZTTFJYYBGSTTTYBYKJDHKYXBELHTYPJQNFXFDYKZHQKZBYJTZBXHFDXKDASWTAWAJLDYJSFHBLDNNTNQJTJNCHXFJSRFWHZFMDRYJYJWZPDJKZYJYMPCYZNYNXFBYTFYFWYGDBNZZZDNYTXZEMMQBSQEHXFZMBMFLZZSRXYMJGSXWZJSPRYDJSJGXHJJGLJJYNZZJXHGXKYMLPYYYCXYTWQZSWHWLYRJLPXSLSXMFSWWKLCTNXNYNPSJSZHDZEPTXMYYWXYYSYWLXJQZQXZDCLEEELMCPJPCLWBXSQHFWWTFFJTNQJHJQDXHWLBYZNFJLALKYYJLDXHHYCSTYYWNRJYXYWTRMDRQHWQCMFJDYZMHMYYXJWMYZQZXTLMRSPWWCHAQBXYGZYPXYYRRCLMPYMGKSJSZYSRMYJSNXTPLNBAPPYPYLXYYZKYNLDZYJZCZNNLMZHHARQMPGWQTZMXXMLLHGDZXYHXKYXYCJMFFYYHJFSBSSQLXXNDYCANNMTCJCYPRRNYTYQNYYMBMSXNDLYLYSLJRLXYSXQMLLYZLZJJJKYZZCSFBZXXMSTBJGNXYZHLXNMCWSCYZYFZLXBRNNNYLBNRTGZQYSATSWRYHYJZMZDHZGZDWYBSSCSKXSYHYTXXGCQGXZZSHYXJSCRHMKKBXCZJYJYMKQHZJFNBHMQHYSNJNZYBKNQMCLGQHWLZNZSWXKHLJHYYBQLBFCDSXDLDSPFZPSKJYZWZXZDDXJSMMEGJSCSSMGCLXXKYYYLNYPWWWGYDKZJGGGZGGSYCKNJWNJPCXBJJTQTJWDSSPJXZXNZXUMELPXFSXTLLXCLJXJJLJZXCTPSWXLYDHLYQRWHSYCSQYYBYAYWJJJQFWQCQQCJQGXALDBZZYJGKGXPLTZYFXJLTPADKYQHPMATLCPDCKBMTXYBHKLENXDLEEGQDYMSAWHZMLJTWYGXLYQZLJEEYYBQQFFNLYXRDSCTGJGXYYNKLLYQKCCTLHJLQMKKZGCYYGLLLJDZGYDHZWXPYSJBZKDZGYZZHYWYFQYTYZSZYEZZLYMHJJHTSMQWYZLKYYWZCSRKQYTLTDXWCTYJKLWSQZWBDCQYNCJSRSZJLKCDCDTLZZZACQQZZDDXYPLXZBQJYLZLLLQDDZQJYJYJZYXNYYYNYJXKXDAZWYRDLJYYYRJLXLLDYXJCYWYWNQCCLDDNYYYNYCKCZHXXCCLGZQJGKWPPCQQJYSBZZXYJSQPXJPZBSBDSFNSFPZXHDWZTDWPPTFLZZBZDMYYPQJRSDZSQZSQXBDGCPZSWDWCSQZGMDHZXMWWFYBPDGPHTMJTHZSMMBGZMBZJCFZWFZBBZMQCFMBDMCJXLGPNJBBXGYHYYJGPTZGZMQBQTCGYXJXLWZKYDPDYMGCFTPFXYZTZXDZXTGKMTYBBCLBJASKYTSSQYYMSZXFJEWLXLLSZBQJJJAKLYLXLYCCTSXMCWFKKKBSXLLLLJYXTYLTJYYTDPJHNHNNKBYQNFQYYZBYYESSESSGDYHFHWTCJBSDZZTFDMXHCNJZYMQWSRYJDZJQPDQBBSTJGGFBKJBXTGQHNGWJXJGDLLTHZHHYYYYYYSXWTYYYCCBDBPYPZYCCZYJPZYWCBDLFWZCWJDXXHYHLHWZZXJTCZLCDPXUJCZZZLYXJJTXPHFXWPYWXZPTDZZBDZCYHJHMLXBQXSBYLRDTGJRRCTTTHYTCZWMXFYTWWZCWJWXJYWCSKYBZSCCTZQNHXNWXXKHKFHTSWOCCJYBCMPZZYKBNNZPBZHHZDLSYDDYTYFJPXYNGFXBYQXCBHXCPSXTYZDMKYSNXSXLHKMZXLYHDHKWHXXSSKQYHHCJYXGLHZXCSNHEKDTGZXQYPKDHEXTYKCNYMYYYPKQYYYKXZLTHJQTBYQHXBMYHSQCKWWYLLHCYYLNNEQXQWMCFBDCCMLJGGXDQKTLXKGNQCDGZJWYJJLYHHQTTTNWCHMXCXWHWSZJYDJCCDBQCDGDNYXZTHCQRXCBHZTQCBXWGQWYYBXHMBYMYQTYEXMQKYAQYRGYZSLFYKKQHYSSQYSHJGJCNXKZYCXSBXYXHYYLSTYCXQTHYSMGSCPMMGCCCCCMTZTASMGQZJHKLOSQYLSWTMXSYQKDZLJQQYPLSYCZTCQQPBBQJZCLPKHQZYYXXDTDDTSJCXFFLLCHQXMJLWCJCXTSPYCXNDTJSHJWXDQQJSKXYAMYLSJHMLALYKXCYYDMNMDQMXMCZNNCYBZKKYFLMCHCMLHXRCJJHSYLNMTJZGZGYWJXSRXCWJGJQHQZDQJDCJJZKJKGDZQGJJYJYLXZXXCDQHHHEYTMHLFSBDJSYYSHFYSTCZQLPBDRFRZTZYKYWHSZYQKWDQZRKMSYNBCRXQBJYFAZPZZEDZCJYWBCJWHYJBQSZYWRYSZPTDKZPFPBNZTKLQYHBBZPNPPTYZZYBQNYDCPJMMCYCQMCYFZZDCMNLFPBPLNGQJTBTTNJZPZBBZNJKLJQYLNBZQHKSJZNGGQSZZKYXSHPZSNBCGZKDDZQANZHJKDRTLZLSWJLJZLYWTJNDJZJHXYAYNCBGTZCSSQMNJPJYTYSWXZFKWJQTKHTZPLBHSNJZSYZBWZZZZLSYLSBJHDWWQPSLMMFBJDWAQYZTCJTBNNWZXQXCDSLQGDSDPDZHJTQQPSWLYYJZLGYXYZLCTCBJTKTYCZJTQKBSJLGMGZDMCSGPYNJZYQYYKNXRPWSZXMTNCSZZYXYBYHYZAXYWQCJTLLCKJJTJHGDXDXYQYZZBYWDLWQCGLZGJGQRQZCZSSBCRPCSKYDZNXJSQGXSSJMYDNSTZTPBDLTKZWXQWQTZEXNQCZGWEZKSSBYBRTSSSLCCGBPSZQSZLCCGLLLZXHZQTHCZMQGYZQZNMCOCSZJMMZSQPJYGQLJYJPPLDXRGZYXCCSXHSHGTZNLZWZKJCXTCFCJXLBMQBCZZWPQDNHXLJCTHYZLGYLNLSZZPCXDSCQQHJQKSXZPBAJYEMSMJTZDXLCJYRYYNWJBNGZZTMJXLTBSLYRZPYLSSCNXPHLLHYLLQQZQLXYMRSYCXZLMMCZLTZSDWTJJLLNZGGQXPFSKYGYGHBFZPDKMWGHCXMSGDXJMCJZDYCABXJDLNBCDQYGSKYDQTXDJJYXMSZQAZDZFSLQXYJSJZYLBTXXWXQQZBJZUFBBLYLWDSLJHXJYZJWTDJCZFQZQZZDZSXZZQLZCDZFJHYSPYMPQZMLPPLFFXJJNZZYLSJEYQZFPFZKSYWJJJHRDJZZXTXXGLGHYDXCSKYSWMMZCWYBAZBJKSHFHJCXMHFQHYXXYZFTSJYZFXYXPZLCHMZMBXHZZSXYFYMNCWDABAZLXKTCSHHXKXJJZJSTHYGXSXYYHHHJWXKZXSSBZZWHHHCWTZZZPJXSNXQQJGZYZYWLLCWXZFXXYXYHXMKYYSWSQMNLNAYCYSPMJKHWCQHYLAJJMZXHMMCNZHBHXCLXTJPLTXYJHDYYLTTXFSZHYXXSJBJYAYRSMXYPLCKDUYHLXRLNLLSTYZYYQYGYHHSCCSMZCTZQXKYQFPYYRPFFLKQUNTSZLLZMWWTCQQYZWTLLMLMPWMBZSSTZRBPDDTLQJJBXZCSRZQQYGWCSXFWZLXCCRSZDZMCYGGDZQSGTJSWLJMYMMZYHFBJDGYXCCPSHXNZCSBSJYJGJMPPWAFFYFNXHYZXZYLREMZGZCYZSSZDLLJCSQFNXZKPTXZGXJJGFMYYYSNBTYLBNLHPFZDCYFBMGQRRSSSZXYSGTZRNYDZZCDGPJAFJFZKNZBLCZSZPSGCYCJSZLMLRSZBZZLDLSLLYSXSQZQLYXZLSKKBRXBRBZCYCXZZZEEYFGKLZLYYHGZSGZLFJHGTGWKRAAJYZKZQTSSHJJXDCYZUYJLZYRZDQQHGJZXSSZBYKJPBFRTJXLLFQWJHYLQTYMBLPZDXTZYGBDHZZRBGXHWNJTJXLKSCFSMWLSDQYSJTXKZSCFWJLBXFTZLLJZLLQBLSQMQQCGCZFPBPHZCZJLPYYGGDTGWDCFCZQYYYQYSSCLXZSKLZZZGFFCQNWGLHQYZJJCZLQZZYJPJZZBPDCCMHJGXDQDGDLZQMFGPSYTSDYFWWDJZJYSXYYCZCYHZWPBYKXRYLYBHKJKSFXTZJMMCKHLLTNYYMSYXYZPYJQYCSYCWMTJJKQYRHLLQXPSGTLYYCLJSCPXJYZFNMLRGJJTYZBXYZMSJYJHHFZQMSYXRSZCWTLRTQZSSTKXGQKGSPTGCZNJSJCQCXHMXGGZTQYDJKZDLBZSXJLHYQGGGTHQSZPYHJHHGYYGKGGCWJZZYLCZLXQSFTGZSLLLMLJSKCTBLLZZSZMMNYTPZSXQHJCJYQXYZXZQZCPSHKZZYSXCDFGMWQRLLQXRFZTLYSTCTMJCXJJXHJNXTNRZTZFQYHQGLLGCXSZSJDJLJCYDSJTLNYXHSZXCGJZYQPYLFHDJSBPCCZHJJJQZJQDYBSSLLCMYTTMQTBHJQNNYGKYRQYQMZGCJKPDCGMYZHQLLSLLCLMHOLZGDYYFZSLJCQZLYLZQJESHNYLLJXGJXLYSYYYXNBZLJSSZCQQCJYLLZLTJYLLZLLBNYLGQCHXYYXOXCXQKYJXXXYKLXSXXYQXCYKQXQCSGYXXYQXYGYTQOHXHXPYXXXULCYEYCHZZCBWQBBWJQZSCSZSSLZYLKDESJZWMYMCYTSDSXXSCJPQQSQYLYYZYCMDJDZYWCBTJSYDJKCYDDJLBDJJSODZYSYXQQYXDHHGQQYQHDYXWGMMMAJDYBBBPPBCMUUPLJZSMTXERXJMHQNUTPJDCBSSMSSSTKJTSSMMTRCPLZSZMLQDSDMJMQPNQDXCFYNBFSDQXYXHYAYKQYDDLQYYYSSZBYDSLNTFQTZQPZMCHDHCZCWFDXTMYQSPHQYYXSRGJCWTJTZZQMGWJJTJHTQJBBHWZPXXHYQFXXQYWYYHYSCDYDHHQMNMTMWCPBSZPPZZGLMZFOLLCFWHMMSJZTTDHZZYFFYTZZGZYSKYJXQYJZQBHMBZZLYGHGFMSHPZFZSNCLPBQSNJXZSLXXFPMTYJYGBXLLDLXPZJYZJYHHZCYWHJYLSJEXFSZZYWXKZJLUYDTMLYMQJPWXYHXSKTQJEZRPXXZHHMHWQPWQLYJJQJJZSZCPHJLCHHNXJLQWZJHBMZYXBDHHYPZLHLHLGFWLCHYYTLHJXCJMSCPXSTKPNHQXSRTYXXTESYJCTLSSLSTDLLLWWYHDHRJZSFGXTSYCZYNYHTDHWJSLHTZDQDJZXXQHGYLTZPHCSQFCLNJTCLZPFSTPDYNYLGMJLLYCQHYSSHCHYLHQYQTMZYPBYWRFQYKQSYSLZDQJMPXYYSSRHZJNYWTQDFZBWWTWWRXCWHGYHXMKMYYYQMSMZHNGCEPMLQQMTCWCTMMPXJPJJHFXYYZSXZHTYBMSTSYJTTQQQYYLHYNPYQZLCYZHZWSMYLKFJXLWGXYPJYTYSYXYMZCKTTWLKSMZSYLMPWLZWXWQZSSAQSYXYRHSSNTSRAPXCPWCMGDXHXZDZYFJHGZTTSBJHGYZSZYSMYCLLLXBTYXHBBZJKSSDMALXHYCFYGMQYPJYCQXJLLLJGSLZGQLYCJCCZOTYXMTMTTLLWTGPXYMZMKLPSZZZXHKQYSXCTYJZYHXSHYXZKXLZWPSQPYHJWPJPWXQQYLXSDHMRSLZZYZWTTCYXYSZZSHBSCCSTPLWSSCJCHNLCGCHSSPHYLHFHHXJSXYLLNYLSZDHZXYLSXLWZYKCLDYAXZCMDDYSPJTQJZLNWQPSSSWCTSTSZLBLNXSMNYYMJQBQHRZWTYYDCHQLXKPZWBGQYBKFCMZWPZLLYYLSZYDWHXPSBCMLJBSCGBHXLQHYRLJXYSWXWXZSLDFHLSLYNJLZYFLYJYCDRJLFSYZFSLLCQYQFGJYHYXZLYLMSTDJCYHBZLLNWLXXYGYYHSMGDHXXHHLZZJZXCZZZCYQZFNGWPYLCPKPYYPMCLQKDGXZGGWQBDXZZKZFBXXLZXJTPJPTTBYTSZZDWSLCHZHSLTYXHQLHYXXXYYZYSWTXZKHLXZXZPYHGCHKCFSYHUTJRLXFJXPTZTWHPLYXFCRHXSHXKYXXYHZQDXQWULHYHMJTBFLKHTXCWHJFWJCFPQRYQXCYYYQYGRPYWSGSUNGWCHKZDXYFLXXHJJBYZWTSXXNCYJJYMSWZJQRMHXZWFQSYLZJZGBHYNSLBGTTCSYBYXXWXYHXYYXNSQYXMQYWRGYQLXBBZLJSYLPSYTJZYHYZAWLRORJMKSCZJXXXYXCHDYXRYXXJDTSQFXLYLTSFFYXLMTYJMJUYYYXLTZCSXQZQHZXLYYXZHDNBRXXXJCTYHLBRLMBRLLAXKYLLLJLYXXLYCRYLCJTGJCMTLZLLCYZZPZPCYAWHJJFYBDYYZSMPCKZDQYQPBPCJPDCYZMDPBCYYDYCNNPLMTMLRMFMMGWYZBSJGYGSMZQQQZTXMKQWGXLLPJGZBQCDJJJFPKJKCXBLJMSWMDTQJXLDLPPBXCWRCQFBFQJCZAHZGMYKPHYYHZYKNDKZMBPJYXPXYHLFPNYYGXJDBKXNXHJMZJXSTRSTLDXSKZYSYBZXJLXYSLBZYSLHXJPFXPQNBYLLJQKYGZMCYZZYMCCSLCLHZFWFWYXZMWSXTYNXJHPYYMCYSPMHYSMYDYSHQYZCHMJJMZCAAGCFJBBHPLYZYLXXSDJGXDHKXXTXXNBHRMLYJSLTXMRHNLXQJXYZLLYSWQGDLBJHDCGJYQYCMHWFMJYBMBYJYJWYMDPWHXQLDYGPDFXXBCGJSPCKRSSYZJMSLBZZJFLJJJLGXZGYXYXLSZQYXBEXYXHGCXBPLDYHWETTWWCJMBTXCHXYQXLLXFLYXLLJLSSFWDPZSMYJCLMWYTCZPCHQEKCQBWLCQYDPLQPPQZQFJQDJHYMMCXTXDRMJWRHXCJZYLQXDYYNHYYHRSLSRSYWWZJYMTLTLLGTQCJZYABTCKZCJYCCQLJZQXALMZYHYWLWDXZXQDLLQSHGPJFJLJHJABCQZDJGTKHSSTCYJLPSWZLXZXRWGLDLZRLZXTGSLLLLZLYXXWGDZYGBDPHZPBRLWSXQBPFDWOFMWHLYPCBJCCLDMBZPBZZLCYQXLDOMZBLZWPDWYYGDSTTHCSQSCCRSSSYSLFYBFNTYJSZDFNDPDHDZZMBBLSLCMYFFGTJJQWFTMTPJWFNLBZCMMJTGBDZLQLPYFHYYMJYLSDCHDZJWJCCTLJCLDTLJJCPDDSQDSSZYBNDBJLGGJZXSXNLYCYBJXQYCBYLZCFZPPGKCXZDZFZTJJFJSJXZBNZYJQTTYJYHTYCZHYMDJXTTMPXSPLZCDWSLSHXYPZGTFMLCJTYCBPMGDKWYCYZCDSZZYHFLYCTYGWHKJYYLSJCXGYWJCBLLCSNDDBTZBSCLYZCZZSSQDLLMQYYHFSLQLLXFTYHABXGWNYWYYPLLSDLDLLBJCYXJZMLHLJDXYYQYTDLLLBUGBFDFBBQJZZMDPJHGCLGMJJPGAEHHBWCQXAXHHHZCHXYPHJAXHLPHJPGPZJQCQZGJJZZUZDMQYYBZZPHYHYBWHAZYJHYKFGDPFQSDLZMLJXKXGALXZDAGLMDGXMWZQYXXDXXPFDMMSSYMPFMDMMKXKSYZYSHDZKXSYSMMZZZMSYDNZZCZXFPLSTMZDNMXCKJMZTYYMZMZZMSXHHDCZJEMXXKLJSTLWLSQLYJZLLZJSSDPPMHNLZJCZYHMXXHGZCJMDHXTKGRMXFWMCGMWKDTKSXQMMMFZZYDKMSCLCMPCGMHSPXQPZDSSLCXKYXTWLWJYAHZJGZQMCSNXYYMMPMLKJXMHLMLQMXCTKZMJQYSZJSYSZHSYJZJCDAJZYBSDQJZGWZQQXFKDMSDJLFWEHKZQKJPEYPZYSZCDWYJFFMZZYLTTDZZEFMZLBNPPLPLPEPSZALLTYLKCKQZKGENQLWAGYXYDPXLHSXQQWQCQXQCLHYXXMLYCCWLYMQYSKGCHLCJNSZKPYZKCQZQLJPDMDZHLASXLBYDWQLWDNBQCRYDDZTJYBKBWSZDXDTNPJDTCTQDFXQQMGNXECLTTBKPWSLCTYQLPWYZZKLPYGZCQQPLLKCCYLPQMZCZQCLJSLQZDJXLDDHPZQDLJJXZQDXYZQKZLJCYQDYJPPYPQYKJYRMPCBYMCXKLLZLLFQPYLLLMBSGLCYSSLRSYSQTMXYXZQZFDZUYSYZTFFMZZSMZQHZSSCCMLYXWTPZGXZJGZGSJSGKDDHTQGGZLLBJDZLCBCHYXYZHZFYWXYZYMSDBZZYJGTSMTFXQYXQSTDGSLNXDLRYZZLRYYLXQHTXSRTZNGZXBNQQZFMYKMZJBZYMKBPNLYZPBLMCNQYZZZSJZHJCTZKHYZZJRDYZHNPXGLFZTLKGJTCTSSYLLGZRZBBQZZKLPKLCZYSSUYXBJFPNJZZXCDWXZYJXZZDJJKGGRSRJKMSMZJLSJYWQSKYHQJSXPJZZZLSNSHRNYPZTWCHKLPSRZLZXYJQXQKYSJYCZTLQZYBBYBWZPQDWWYZCYTJCJXCKCWDKKZXSGKDZXWWYYJQYYTCYTDLLXWKCZKKLCCLZCQQDZLQLCSFQCHQHSFSMQZZLNBJJZBSJHTSZDYSJQJPDLZCDCWJKJZZLPYCGMZWDJJBSJQZSYZYHHXJPBJYDSSXDZNCGLQMBTSFSBPDZDLZNFGFJGFSMPXJQLMBLGQCYYXBQKDJJQYRFKZTJDHCZKLBSDZCFJTPLLJGXHYXZCSSZZXSTJYGKGCKGYOQXJPLZPBPGTGYJZGHZQZZLBJLSQFZGKQQJZGYCZBZQTLDXRJXBSXXPZXHYZYCLWDXJJHXMFDZPFZHQHQMQGKSLYHTYCGFRZGNQXCLPDLBZCSCZQLLJBLHBZCYPZZPPDYMZZSGYHCKCPZJGSLJLNSCDSLDLXBMSTLDDFJMKDJDHZLZXLSZQPQPGJLLYBDSZGQLBZLSLKYYHZTTNTJYQTZZPSZQZTLLJTYYLLQLLQYZQLBDZLSLYYZYMDFSZSNHLXZNCZQZPBWSKRFBSYZMTHBLGJPMCZZLSTLXSHTCSYZLZBLFEQHLXFLCJLYLJQCBZLZJHHSSTBRMHXZHJZCLXFNBGXGTQJCZTMSFZKJMSSNXLJKBHSJXNTNLZDNTLMSJXGZJYJCZXYJYJWRWWQNZTNFJSZPZSHZJFYRDJSFSZJZBJFZQZZHZLXFYSBZQLZSGYFTZDCSZXZJBQMSZKJRHYJZCKMJKHCHGTXKXQGLXPXFXTRTYLXJXHDTSJXHJZJXZWZLCQSBTXWXGXTXXHXFTSDKFJHZYJFJXRZSDLLLTQSQQZQWZXSYQTWGWBZCGZLLYZBCLMQQTZHZXZXLJFRMYZFLXYSQXXJKXRMQDZDMMYYBSQBHGZMWFWXGMXLZPYYTGZYCCDXYZXYWGSYJYZNBHPZJSQSYXSXRTFYZGRHZTXSZZTHCBFCLSYXZLZQMZLMPLMXZJXSFLBYZMYQHXJSXRXSQZZZSSLYFRCZJRCRXHHZXQYDYHXSJJHZCXZBTYNSYSXJBQLPXZQPYMLXZKYXLXCJLCYSXXZZLXDLLLJJYHZXGYJWKJRWYHCPSGNRZLFZWFZZNSXGXFLZSXZZZBFCSYJDBRJKRDHHGXJLJJTGXJXXSTJTJXLYXQFCSGSWMSBCTLQZZWLZZKXJMLTMJYHSDDBXGZHDLBMYJFRZFSGCLYJBPMLYSMSXLSZJQQHJZFXGFQFQBPXZGYYQXGZTCQWYLTLGWSGWHRLFSFGZJMGMGBGTJFSYZZGZYZAFLSSPMLPFLCWBJZCLJJMZLPJJLYMQDMYYYFBGYGYZMLYZDXQYXRQQQHSYYYQXYLJTYXFSFSLLGNQCYHYCWFHCCCFXPYLYPLLZYXXXXXKQHHXSHJZCFZSCZJXCPZWHHHHHAPYLQALPQAFYHXDYLUKMZQGGGDDESRNNZLTZGCHYPPYSQJJHCLLJTOLNJPZLJLHYMHEYDYDSQYCDDHGZUNDZCLZYZLLZNTNYZGSLHSLPJJBDGWXPCDUTJCKLKCLWKLLCASSTKZZDNQNTTLYYZSSYSSZZRYLJQKCQDHHCRXRZYDGRGCWCGZQFFFPPJFZYNAKRGYWYQPQXXFKJTSZZXSWZDDFBBXTBGTZKZNPZZPZXZPJSZBMQHKCYXYLDKLJNYPKYGHGDZJXXEAHPNZKZTZCMXCXMMJXNKSZQNMNLWBWWXJKYHCPSTMCSQTZJYXTPCTPDTNNPGLLLZSJLSPBLPLQHDTNJNLYYRSZFFJFQWDPHZDWMRZCCLODAXNSSNYZRESTYJWJYJDBCFXNMWTTBYLWSTSZGYBLJPXGLBOCLHPCBJLTMXZLJYLZXCLTPNCLCKXTPZJSWCYXSFYSZDKNTLBYJCYJLLSTGQCBXRYZXBXKLYLHZLQZLNZCXWJZLJZJNCJHXMNZZGJZZXTZJXYCYYCXXJYYXJJXSSSJSTSSTTPPGQTCSXWZDCSYFPTFBFHFBBLZJCLZZDBXGCXLQPXKFZFLSYLTUWBMQJHSZBMDDBCYSCCLDXYCDDQLYJJWMQLLCSGLJJSYFPYYCCYLTJANTJJPWYCMMGQYYSXDXQMZHSZXPFTWWZQSWQRFKJLZJQQYFBRXJHHFWJJZYQAZMYFRHCYYBYQWLPEXCCZSTYRLTTDMQLYKMBBGMYYJPRKZNPBSXYXBHYZDJDNGHPMFSGMWFZMFQMMBCMZZCJJLCNUXYQLMLRYGQZCYXZLWJGCJCGGMCJNFYZZJHYCPRRCMTZQZXHFQGTJXCCJEAQCRJYHPLQLSZDJRBCQHQDYRHYLYXJSYMHZYDWLDFRYHBPYDTSSCNWBXGLPZMLZZTQSSCPJMXXYCSJYTYCGHYCJWYRXXLFEMWJNMKLLSWTXHYYYNCMMCWJDQDJZGLLJWJRKHPZGGFLCCSCZMCBLTBHBQJXQDSPDJZZGHGLFQYWBZYZJLTSTDHQHCTCBCHFLQMPWDSHYYTQWCNZZJTLBYMBPDYYYXSQKXWYYFLXXNCWCXYPMAELYKKJMZZZBRXYYQJFLJPFHHHYTZZXSGQQMHSPGDZQWBWPJHZJDYSCQWZKTXXSQLZYYMYSDZGRXCKKUJLWPYSYSCSYZLRMLQSYLJXBCXTLWDQZPCYCYKPPPNSXFYZJJRCEMHSZMSXLXGLRWGCSTLRSXBZGBZGZTCPLUJLSLYLYMTXMTZPALZXPXJTJWTCYYZLBLXBZLQMYLXPGHDSLSSDMXMBDZZSXWHAMLCZCPJMCNHJYSNSYGCHSKQMZZQDLLKABLWJXSFMOCDXJRRLYQZKJMYBYQLYHETFJZFRFKSRYXFJTWDSXXSYSQJYSLYXWJHSNLXYYXHBHAWHHJZXWMYLJCSSLKYDZTXBZSYFDXGXZJKHSXXYBSSXDPYNZWRPTQZCZENYGCXQFJYKJBZMLJCMQQXUOXSLYXXLYLLJDZBTYMHPFSTTQQWLHOKYBLZZALZXQLHZWRRQHLSTMYPYXJJXMQSJFNBXYXYJXXYQYLTHYLQYFMLKLJTMLLHSZWKZHLJMLHLJKLJSTLQXYLMBHHLNLZXQJHXCFXXLHYHJJGBYZZKBXSCQDJQDSUJZYYHZHHMGSXCSYMXFEBCQWWRBPYYJQTYZCYQYQQZYHMWFFHGZFRJFCDPXNTQYZPDYKHJLFRZXPPXZDBBGZQSTLGDGYLCQMLCHHMFYWLZYXKJLYPQHSYWMQQGQZMLZJNSQXJQSYJYCBEHSXFSZPXZWFLLBCYYJDYTDTHWZSFJMQQYJLMQXXLLDTTKHHYBFPWTYYSQQWNQWLGWDEBZWCMYGCULKJXTMXMYJSXHYBRWFYMWFRXYQMXYSZTZZTFYKMLDHQDXWYYNLCRYJBLPSXCXYWLSPRRJWXHQYPHTYDNXHHMMYWYTZCSQMTSSCCDALWZTCPQPYJLLQZYJSWXMZZMMYLMXCLMXCZMXMZSQTZPPQQBLPGXQZHFLJJHYTJSRXWZXSCCDLXTYJDCQJXSLQYCLZXLZZXMXQRJMHRHZJBHMFLJLMLCLQNLDXZLLLPYPSYJYSXCQQDCMQJZZXHNPNXZMEKMXHYKYQLXSXTXJYYHWDCWDZHQYYBGYBCYSCFGPSJNZDYZZJZXRZRQJJYMCANYRJTLDPPYZBSTJKXXZYPFDWFGZZRPYMTNGXZQBYXNBUFNQKRJQZMJEGRZGYCLKXZDSKKNSXKCLJSPJYYZLQQJYBZSSQLLLKJXTBKTYLCCDDBLSPPFYLGYDTZJYQGGKQTTFZXBDKTYYHYBBFYTYYBCLPDYTGDHRYRNJSPTCSNYJQHKLLLZSLYDXXWBCJQSPXBPJZJCJDZFFXXBRMLAZHCSNDLBJDSZBLPRZTSWSBXBCLLXXLZDJZSJPYLYXXYFTFFFBHJJXGBYXJPMMMPSSJZJMTLYZJXSWXTYLEDQPJMYGQZJGDJLQJWJQLLSJGJGYGMSCLJJXDTYGJQJQJCJZCJGDZZSXQGSJGGCXHQXSNQLZZBXHSGZXCXYLJXYXYYDFQQJHJFXDHCTXJYRXYSQTJXYEFYYSSYYJXNCYZXFXMSYSZXYYSCHSHXZZZGZZZGFJDLTYLNPZGYJYZYYQZPBXQBDZTZCZYXXYHHSQXSHDHGQHJHGYWSZTMZMLHYXGEBTYLZKQWYTJZRCLEKYSTDBCYKQQSAYXCJXWWGSBHJYZYDHCSJKQCXSWXFLTYNYZPZCCZJQTZWJQDZZZQZLJJXLSBHPYXXPSXSHHEZTXFPTLQYZZXHYTXNCFZYYHXGNXMYWXTZSJPTHHGYMXMXQZXTSBCZYJYXXTYYZYPCQLMMSZMJZZLLZXGXZAAJZYXJMZXWDXZSXZDZXLEYJJZQBHZWZZZQTZPSXZTDSXJJJZNYAZPHXYYSRNQDTHZHYYKYJHDZXZLSWCLYBZYECWCYCRYLCXNHZYDZYDYJDFRJJHTRSQTXYXJRJHOJYNXELXSFSFJZGHPZSXZSZDZCQZBYYKLSGSJHCZSHDGQGXYZGXCHXZJWYQWGYHKSSEQZZNDZFKWYSSTCLZSTSYMCDHJXXYWEYXCZAYDMPXMDSXYBSQMJMZJMTZQLPJYQZCGQHXJHHLXXHLHDLDJQCLDWBSXFZZYYSCHTYTYYBHECXHYKGJPXHHYZJFXHWHBDZFYZBCAPNPGNYDMSXHMMMMAMYNBYJTMPXYYMCTHJBZYFCGTYHWPHFTWZZEZSBZEGPFMTSKFTYCMHFLLHGPZJXZJGZJYXZSBBQSCZZLZCCSTPGXMJSFTCCZJZDJXCYBZLFCJSYZFGSZLYBCWZZBYZDZYPSWYJZXZBDSYUXLZZBZFYGCZXBZHZFTPBGZGEJBSTGKDMFHYZZJHZLLZZGJQZLSFDJSSCBZGPDLFZFZSZYZYZSYGCXSNXXCHCZXTZZLJFZGQSQYXZJQDCCZTQCDXZJYQJQCHXZTDLGSCXZSYQJQTZWLQDQZTQCHQQJZYEZZZPBWKDJFCJPZTYPQYQTTYNLMBDKTJZPQZQZZFPZSBNJLGYJDXJDZZKZGQKXDLPZJTCJDQBXDJQJSTCKNXBXZMSLYJCQMTJQWWCJQNJNLLLHJCWQTBZQYDZCZPZZDZYDDCYZZZCCJTTJFZDPRRTZTJDCQTQZDTJNPLZBCLLCTZSXKJZQZPZLBZRBTJDCXFCZDBCCJJLTQQPLDCGZDBBZJCQDCJWYNLLZYZCCDWLLXWZLXRXNTQQCZXKQLSGDFQTDDGLRLAJJTKUYMKQLLTZYTDYYCZGJWYXDXFRSKSTQTENQMRKQZHHQKDLDAZFKYPBGGPZREBZZYKZZSPEGJXGYKQZZZSLYSYYYZWFQZYLZZLZHWCHKYPQGNPGBLPLRRJYXCCSYYHSFZFYBZYYTGZXYLXCZWXXZJZBLFFLGSKHYJZEYJHLPLLLLCZGXDRZELRHGKLZZYHZLYQSZZJZQLJZFLNBHGWLCZCFJYSPYXZLZLXGCCPZBLLCYBBBBUBBCBPCRNNZCZYRBFSRLDCGQYYQXYGMQZWTZYTYJXYFWTEHZZJYWLCCNTZYJJZDEDPZDZTSYQJHDYMBJNYJZLXTSSTPHNDJXXBYXQTZQDDTJTDYYTGWSCSZQFLSHLGLBCZPHDLYZJYCKWTYTYLBNYTSDSYCCTYSZYYEBHEXHQDTWNYGYCLXTSZYSTQMYGZAZCCSZZDSLZCLZRQXYYELJSBYMXSXZTEMBBLLYYLLYTDQYSHYMRQWKFKBFXNXSBYCHXBWJYHTQBPBSBWDZYLKGZSKYHXQZJXHXJXGNLJKZLYYCDXLFYFGHLJGJYBXQLYBXQPQGZTZPLNCYPXDJYQYDYMRBESJYYHKXXSTMXRCZZYWXYQYBMCLLYZHQYZWQXDBXBZWZMSLPDMYSKFMZKLZCYQYCZLQXFZZYDQZPZYGYJYZMZXDZFYFYTTQTZHGSPCZMLCCYTZXJCYTJMKSLPZHYSNZLLYTPZCTZZCKTXDHXXTQCYFKSMQCCYYAZHTJPCYLZLYJBJXTPNYLJYYNRXSYLMMNXJSMYBCSYSYLZYLXJJQYLDZLPQBFZZBLFNDXQKCZFYWHGQMRDSXYCYTXNQQJZYYPFZXDYZFPRXEJDGYQBXRCNFYYQPGHYJDYZXGRHTKYLNWDZNTSMPKLBTHBPYSZBZTJZSZZJTYYXZPHSSZZBZCZPTQFZMYFLYPYBBJQXZMXXDJMTSYSKKBJZXHJCKLPSMKYJZCXTMLJYXRZZQSLXXQPYZXMKYXXXJCLJPRMYYGADYSKQLSNDHYZKQXZYZTCGHZTLMLWZYBWSYCTBHJHJFCWZTXWYTKZLXQSHLYJZJXTMPLPYCGLTBZZTLZJCYJGDTCLKLPLLQPJMZPAPXYZLKKTKDZCZZBNZDYDYQZJYJGMCTXLTGXSZLMLHBGLKFWNWZHDXUHLFMKYSLGXDTWWFRJEJZTZHYDXYKSHWFZCQSHKTMQQHTZHYMJDJSKHXZJZBZZXYMPAGQMSTPXLSKLZYNWRTSQLSZBPSPSGZWYHTLKSSSWHZZLYYTNXJGMJSZSUFWNLSOZTXGXLSAMMLBWLDSZYLAKQCQCTMYCFJBSLXCLZZCLXXKSBZQCLHJPSQPLSXXCKSLNHPSFQQYTXYJZLQLDXZQJZDYYDJNZPTUZDSKJFSLJHYLZSQZLBTXYDGTQFDBYAZXDZHZJNHHQBYKNXJJQCZMLLJZKSPLDYCLBBLXKLELXJLBQYCXJXGCNLCQPLZLZYJTZLJGYZDZPLTQCSXFDMNYCXGBTJDCZNBGBQYQJWGKFHTNPYQZQGBKPBBYZMTJDYTBLSQMPSXTBNPDXKLEMYYCJYNZCTLDYKZZXDDXHQSHDGMZSJYCCTAYRZLPYLTLKXSLZCGGEXCLFXLKJRTLQJAQZNCMBYDKKCXGLCZJZXJHPTDJJMZQYKQSECQZDSHHADMLZFMMZBGNTJNNLGBYJBRBTMLBYJDZXLCJLPLDLPCQDHLXZLYCBLCXZZJADJLNZMMSSSMYBHBSQKBHRSXXJMXSDZNZPXLGBRHWGGFCXGMSKLLTSJYYCQLTSKYWYYHYWXBXQYWPYWYKQLSQPTNTKHQCWDQKTWPXXHCPTHTWUMSSYHBWCRWXHJMKMZNGWTMLKFGHKJYLSYYCXWHYECLQHKQHTTQKHFZLDXQWYZYYDESBPKYRZPJFYYZJCEQDZZDLATZBBFJLLCXDLMJSSXEGYGSJQXCWBXSSZPDYZCXDNYXPPZYDLYJCZPLTXLSXYZYRXCYYYDYLWWNZSAHJSYQYHGYWWAXTJZDAXYSRLTDPSSYYFNEJDXYZHLXLLLZQZSJNYQYQQXYJGHZGZCYJCHZLYCDSHWSHJZYJXCLLNXZJJYYXNFXMWFPYLCYLLABWDDHWDXJMCXZTZPMLQZHSFHZYNZTLLDYWLSLXHYMMYLMBWWKYXYADTXYLLDJPYBPWUXJMWMLLSAFDLLYFLBHHHBQQLTZJCQJLDJTFFKMMMBYTHYGDCQRDDWRQJXNBYSNWZDBYYTBJHPYBYTTJXAAHGQDQTMYSTQXKBTZPKJLZRBEQQSSMJJBDJOTGTBXPGBKTLHQXJJJCTHXQDWJLWRFWQGWSHCKRYSWGFTGYGBXSDWDWRFHWYTJJXXXJYZYSLPYYYPAYXHYDQKXSHXYXGSKQHYWFDDDPPLCJLQQEEWXKSYYKDYPLTJTHKJLTCYYHHJTTPLTZZCDLTHQKZXQYSTEEYWYYZYXXYYSTTJKLLPZMCYHQGXYHSRMBXPLLNQYDQHXSXXWGDQBSHYLLPJJJTHYJKYPPTHYYKTYEZYENMDSHLCRPQFDGFXZPSFTLJXXJBSWYYSKSFLXLPPLBBBLBSFXFYZBSJSSYLPBBFFFFSSCJDSTZSXZRYYSYFFSYZYZBJTBCTSBSDHRTJJBYTCXYJEYLXCBNEBJDSYXYKGSJZBXBYTFZWGENYHHTHZHHXFWGCSTBGXKLSXYWMTMBYXJSTZSCDYQRCYTWXZFHMYMCXLZNSDJTTTXRYCFYJSBSDYERXJLJXBBDEYNJGHXGCKGSCYMBLXJMSZNSKGXFBNBPTHFJAAFXYXFPXMYPQDTZCXZZPXRSYWZDLYBBKTYQPQJPZYPZJZNJPZJLZZFYSBTTSLMPTZRTDXQSJEHBZYLZDHLJSQMLHTXTJECXSLZZSPKTLZKQQYFSYGYWPCPQFHQHYTQXZKRSGTTSQCZLPTXCDYYZXSQZSLXLZMYCPCQBZYXHBSXLZDLTCDXTYLZJYYZPZYZLTXJSJXHLPMYTXCQRBLZSSFJZZTNJYTXMYJHLHPPLCYXQJQQKZZSCPZKSWALQSBLCCZJSXGWWWYGYKTJBBZTDKHXHKGTGPBKQYSLPXPJCKBMLLXDZSTBKLGGQKQLSBKKTFXRMDKBFTPZFRTBBRFERQGXYJPZSSTLBZTPSZQZSJDHLJQLZBPMSMMSXLQQNHKNBLRDDNXXDHDDJCYYGYLXGZLXSYGMQQGKHBPMXYXLYTQWLWGCPBMQXCYZYDRJBHTDJYHQSHTMJSBYPLWHLZFFNYPMHXXHPLTBQPFBJWQDBYGPNZTPFZJGSDDTQSHZEAWZZYLLTYYBWJKXXGHLFKXDJTMSZSQYNZGGSWQSPHTLSSKMCLZXYSZQZXNCJDQGZDLFNYKLJCJLLZLMZZNHYDSSHTHZZLZZBBHQZWWYCRZHLYQQJBEYFXXXWHSRXWQHWPSLMSSKZTTYGYQQWRSLALHMJTQJSMXQBJJZJXZYZKXBYQXBJXSHZTSFJLXMXZXFGHKZSZGGYLCLSARJYHSLLLMZXELGLXYDJYTLFBHBPNLYZFBBHPTGJKWETZHKJJXZXXGLLJLSTGSHJJYQLQZFKCGNNDJSSZFDBCTWWSEQFHQJBSAQTGYPQLBXBMMYWXGSLZHGLZGQYFLZBYFZJFRYSFMBYZHQGFWZSYFYJJPHZBYYZFFWODGRLMFTWLBZGYCQXCDJYGZYYYYTYTYDWEGAZYHXJLZYYHLRMGRXXZCLHNELJJTJTPWJYBJJBXJJTJTEEKHWSLJPLPSFYZPQQBDLQJJTYYQLYZKDKSQJYYQZLDQTGJQYZJSUCMRYQTHTEJMFCTYHYPKMHYZWJDQFHYYXWSHCTXRLJHQXHCCYYYJLTKTTYTMXGTCJTZAYYOCZLYLBSZYWJYTSJYHBYSHFJLYGJXXTMZYYLTXXYPZLXYJZYZYYPNHMYMDYYLBLHLSYYQQLLNJJYMSOYQBZGDLYXYLCQYXTSZEGXHZGLHWBLJHEYXTWQMAKBPQCGYSHHEGQCMWYYWLJYJHYYZLLJJYLHZYHMGSLJLJXCJJYCLYCJPCPZJZJMMYLCQLNQLJQJSXYJMLSZLJQLYCMMHCFMMFPQQMFYLQMCFFQMMMMHMZNFHHJGTTHHKHSLNCHHYQDXTMMQDCYZYXYQMYQYLTDCYYYZAZZCYMZYDLZFFFMMYCQZWZZMABTBYZTDMNZZGGDFTYPCGQYTTSSFFWFDTZQSSYSTWXJHXYTSXXYLBYQHWWKXHZXWZNNZZJZJJQJCCCHYYXBZXZCYZTLLCQXYNJYCYYCYNZZQYYYEWYCZDCJYCCHYJLBTZYYCQWMPWPYMLGKDLDLGKQQBGYCHJXY"; - - // 此处收录了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", - 20315: "BF", - 20340: "NE", - 20375: "TD", - 20389: "YJ", - 20391: "CZ", - 20415: "PB", - 20446: "YS", - 20447: "SQ", - 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; - } - }; -})();_.extend(BI, { - $import: function () { - var _LOADED = {}; // alex:保存加载过的 - function loadReady (src, must) { - var $scripts = $("head script, body 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; - }; - - p.has = function (key) { - return this._keymap[key] != null; - }; -})(); -!(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.length = 0; - } - }; -})();!(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); - }); - } - }; -})(); -(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) && 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; - } - 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; - } - 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; - } -};/** - * 缓冲池 - * @type {{Buffer: {}}} - */ - -(function () { - var Buffer = {}; - var MODE = false;// 设置缓存模式为关闭 - - BI.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 = {}; - BI.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 && copy[args[i]]; - } - return copy; - }, - - get: function () { - return BI.deepClone(this.cat.apply(this, arguments)); - }, - - remove: function (key) { - delete _Shared[key]; - } - }; -})();BI.Req = { - -}; +})();/** + * 客户端观察者,主要处理事件的添加、删除、执行等 + * @class BI.OB + * @abstract + */ +BI.OB = function (config) { + var props = this.props; + if (BI.isFunction(this.props)) { + props = this.props(config); + } + this.options = (window.$ || window._).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 (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); + } + }, + + //释放当前对象 + _purgeRef: function(){ + if (this.options.ref) { + this.options.ref.call(null); + } + }, + + _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 (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._purgeRef(); + this.purgeListeners(); + } +});(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)); + } + return _numberFormat((-text) + "", format.substr(numMod + 1)); + + } + // 兼容格式处理负数的情况(copy:fr-jquery.format.js) + if (+text < 0 && format.charAt(0) !== "-") { + return _numberFormat((-text) + "", "-" + format); + } + + 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; + } + 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 = BI.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; + }; + + /** + * 将cjkEncode处理过的字符串转化为原始字符串 + * + * @static + * @param text 需要做解码的字符串 + * @return {String} 解码后的字符串 + */ + BI.cjkDecode = function (text) { + if (text == null) { + return ""; + } + // 查找没有 "[", 直接返回. kunsnat:数字的时候, 不支持indexOf方法, 也是直接返回. + if (!isNaN(text) || text.indexOf("[") == -1) { + return text; + } + + var newText = ""; + for (var i = 0; i < text.length; i++) { + var ch = text.charAt(i); + if (ch == "[") { + var rightIdx = text.indexOf("]", i + 1); + if (rightIdx > i + 1) { + var subText = text.substring(i + 1, rightIdx); + // james:主要是考虑[CDATA[]]这样的值的出现 + if (subText.length > 0) { + ch = String.fromCharCode(eval("0x" + subText)); + } + + i = rightIdx; + } + } + + newText += ch; + } + + return newText; + }; + + // replace the html special tags + BI.htmlEncode = function (text) { + return (text == null) ? "" : String(text).replace(/&/g, "&").replace(/\"/g, """).replace(//g, ">").replace(/\s/g, " "); + }; + // html decode + BI.htmlDecode = function (text) { + return (text == null) ? "" : String(text).replace(/&/g, "&").replace(/"/g, "\"").replace(/</g, "<").replace(/>/g, ">").replace(/ /g, " "); + }; + + BI.cjkEncodeDO = function (o) { + if (BI.isPlainObject(o)) { + var result = {}; + _.each(o, function (v, k) { + 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; + + // 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); + } + 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) : window.JSON.parse(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 { + // 数字格式 + var s = []; + BI.clamp(s); + text = _numberFormat(text, fmt); + } + // ¤ - 货币格式 + text = text.replace(/¤/g, "¥"); + return text; + }; + + /** + * 将Java提供的日期格式字符串装换为JS识别的日期格式字符串 + * @class FR.parseFmt + * @param fmt 日期格式 + * @returns {String} + */ + BI.parseFmt = function (fmt) { + if (!fmt) { + return ""; + } + //日期 + fmt = String(fmt) + //年 + .replace(/y{4,}/g, "%Y")//yyyy的时候替换为Y + .replace(/y{2}/g, "%y")//yy的时候替换为y + //月 + .replace(/M{4,}/g, "%b")//MMMM的时候替换为b,八 + .replace(/M{3}/g, "%B")//MMM的时候替换为M,八月 + .replace(/M{2}/g, "%X")//MM的时候替换为X,08 + .replace(/M{1}/g, "%x")//M的时候替换为x,8 + .replace(/a{1}/g, "%p"); + //天 + if (new RegExp("d{2,}", "g").test(fmt)) { + fmt = fmt.replace(/d{2,}/g, "%d");//dd的时候替换为d + } else { + fmt = fmt.replace(/d{1}/g, "%e");//d的时候替换为j + } + //时 + if (new RegExp("h{2,}", "g").test(fmt)) {//12小时制 + fmt = fmt.replace(/h{2,}/g, "%I"); + } else { + fmt = fmt.replace(/h{1}/g, "%I"); + } + if (new RegExp("H{2,}", "g").test(fmt)) {//24小时制 + fmt = fmt.replace(/H{2,}/g, "%H"); + } else { + fmt = fmt.replace(/H{1}/g, "%H"); + } + fmt = fmt.replace(/m{2,}/g, "%M")//分 + //秒 + .replace(/s{2,}/g, "%S"); + + return fmt; + }; + + /** + * 把字符串按照对应的格式转化成日期对象 + * + * @example + * var result = FR.str2Date('2013-12-12', 'yyyy-MM-dd');//Thu Dec 12 2013 00:00:00 GMT+0800 + * + * @class FR.str2Date + * @param str 字符串 + * @param format 日期格式 + * @returns {*} + */ + BI.str2Date = function (str, format) { + if (typeof str != "string" || typeof format != "string") { + return null; + } + var fmt = BI.parseFmt(format); + return BI.parseDateTime(str, fmt); + }; + + /** + * 把日期对象按照指定格式转化成字符串 + * + * @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 = BI.leftPad(date.getMonth() + 1 + "", 2, "0"); + } + break; + case "d": // 日 + if (len > 1) { + str = BI.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 = BI.leftPad(hour + "", 2, "0"); + } else { + str = hour; + } + break; + case "H": // 时(24) + if (len > 1) { + str = BI.leftPad(date.getHours() + "", 2, "0"); + } else { + str = date.getHours(); + } + break; + case "m": + if (len > 1) { + str = BI.leftPad(date.getMinutes() + "", 2, "0"); + } else { + str = date.getMinutes(); + } + break; + case "s": + if (len > 1) { + str = BI.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; + } + var str = value + ""; + if (str.indexOf(".") === -1) { + return parseInt(str); + } + 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); + } + 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; + } + 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.parseDateTime(str, "HH:mm:ss"); + if (!isInvalidDate(dt)) { + return dt; + } + return new Date(); + + }; +})(); +(function () { + var constantInjection = {}; + BI.constant = function (xtype, cls) { + if (constantInjection[xtype] != null) { + console.error("constant:[" + xtype + "] has been registed"); + } + constantInjection[xtype] = cls; + }; + + var modelInjection = {}; + BI.model = function (xtype, cls) { + if (modelInjection[xtype] != null) { + console.error("model:[" + xtype + "] has been registed"); + } + modelInjection[xtype] = cls; + }; + + var storeInjection = {}; + BI.store = function (xtype, cls) { + if (storeInjection[xtype] != null) { + console.error("store:[" + xtype + "] has been registed"); + } + storeInjection[xtype] = cls; + }; + + var serviceInjection = {}; + BI.service = function (xtype, cls) { + if (serviceInjection[xtype] != null) { + console.error("service:[" + xtype + "] has been registed"); + } + serviceInjection[xtype] = cls; + }; + + var providerInjection = {}; + BI.provider = function (xtype, cls) { + if (providerInjection[xtype] != null) { + console.error("provider:[" + xtype + "] has been registed"); + } + providerInjection[xtype] = cls; + }; + + BI.config = function (type, configFn) { + if (constantInjection[type]) { + return constantInjection[type] = configFn(constantInjection[type]); + } + if (providerInjection[type]) { + if (!providers[type]) { + providers[type] = new providerInjection[type](); + } + return configFn(providers[type]); + } + BI.Plugin.configWidget(type, configFn); + }; + + var actions = {}; + var globalAction = []; + BI.action = function (type, actionFn) { + if (BI.isFunction(type)) { + globalAction.push(type); + return function () { + BI.remove(globalAction, actionFn); + }; + } + if (!actions[type]) { + actions[type] = []; + } + actions[type].push(actionFn); + return function () { + actions[type].remove(actionFn); + if (actions[type].length === 0) { + delete actions[type]; + } + }; + }; + + var points = {}; + BI.point = function (type, action, pointFn, after) { + if (!points[type]) { + points[type] = {}; + } + if (!points[type][action]) { + points[type][action] = {}; + } + if (!points[type][action][after ? "after" : "before"]) { + points[type][action][after ? "after" : "before"] = []; + } + points[type][action][after ? "after" : "before"].push(pointFn); + }; + + BI.Constants = { + getConstant: function (type) { + return constantInjection[type]; + } + }; + + var callPoint = function (inst, type) { + if (points[type]) { + for (var action in points[type]) { + var bfns = points[type][action].before; + if (bfns) { + BI.aspect.before(inst, action, function (bfns) { + return function () { + for (var i = 0, len = bfns.length; i < len; i++) { + try { + bfns[i].apply(inst, arguments); + } catch (e) { + console.error(e); + } + } + }; + }(bfns)); + } + var afns = points[type][action].after; + if (afns) { + BI.aspect.after(inst, action, function (afns) { + return function () { + for (var i = 0, len = afns.length; i < len; i++) { + try { + afns[i].apply(inst, arguments); + } catch (e) { + console.error(e); + } + } + }; + }(afns)); + } + } + } + }; + + BI.Models = { + getModel: function (type, config) { + var inst = new modelInjection[type](config); + callPoint(inst, type); + return inst; + } + }; + + var stores = {}; + + BI.Stores = { + getStore: function (type, config) { + if (stores[type]) { + return stores[type]; + } + stores[type] = new storeInjection[type](config); + callPoint(stores[type], type); + return stores[type]; + } + }; + + var services = {}; + + BI.Services = { + getService: function (type, config) { + if (services[type]) { + return services[type]; + } + services[type] = new serviceInjection[type](config); + callPoint(services[type], type); + return services[type]; + } + }; + + var providers = {}, providerInstance = {}; + + BI.Providers = { + getProvider: function (type, config) { + if (!providers[type]) { + providers[type] = new providerInjection[type](); + } + if (!providerInstance[type]) { + providerInstance[type] = new providers[type].$get()(config); + } + return providerInstance[type]; + } + }; + + BI.Actions = { + runAction: function (type, config) { + BI.each(actions[type], function (i, act) { + try { + act(config); + } catch (e) { + console.error(e); + } + }); + }, + runGlobalAction: function () { + var args = [].slice.call(arguments); + BI.each(globalAction, function (i, act) { + try { + act.apply(null, args); + } catch (e) { + console.error(e); + } + }); + } + }; +})(); +(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.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(BI.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]);} + return null; + }, + deleteCookie: function (name, path) { + var date = new Date(); + date.setTime(BI.getTime() - 10000); + var cookieString = name + "=v; expires=" + date.toGMTString(); + if (path) { + cookieString = cookieString + "; path=" + path; + } + document.cookie = cookieString; + } +};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); + } + 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; + } + 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; + } + var offsetPercentage = this._getOffsetPercentage(containerSize, offset, safeTotalSize); + + return Math.round(offsetPercentage * (totalSize - containerSize)); + + } +};/** + * 汉字拼音索引 + */ + +!(function () { + var _ChineseFirstPY = "YDYQSXMWZSSXJBYMGCCZQPSSQBYCDSCDQLDYLYBSSJGYZZJJFKCCLZDHWDWZJLJPFYYNWJJTMYHZWZHFLZPPQHGSCYYYNJQYXXGJHHSDSJNKKTMOMLCRXYPSNQSECCQZGGLLYJLMYZZSECYKYYHQWJSSGGYXYZYJWWKDJHYCHMYXJTLXJYQBYXZLDWRDJRWYSRLDZJPCBZJJBRCFTLECZSTZFXXZHTRQHYBDLYCZSSYMMRFMYQZPWWJJYFCRWFDFZQPYDDWYXKYJAWJFFXYPSFTZYHHYZYSWCJYXSCLCXXWZZXNBGNNXBXLZSZSBSGPYSYZDHMDZBQBZCWDZZYYTZHBTSYYBZGNTNXQYWQSKBPHHLXGYBFMJEBJHHGQTJCYSXSTKZHLYCKGLYSMZXYALMELDCCXGZYRJXSDLTYZCQKCNNJWHJTZZCQLJSTSTBNXBTYXCEQXGKWJYFLZQLYHYXSPSFXLMPBYSXXXYDJCZYLLLSJXFHJXPJBTFFYABYXBHZZBJYZLWLCZGGBTSSMDTJZXPTHYQTGLJSCQFZKJZJQNLZWLSLHDZBWJNCJZYZSQQYCQYRZCJJWYBRTWPYFTWEXCSKDZCTBZHYZZYYJXZCFFZZMJYXXSDZZOTTBZLQWFCKSZSXFYRLNYJMBDTHJXSQQCCSBXYYTSYFBXDZTGBCNSLCYZZPSAZYZZSCJCSHZQYDXLBPJLLMQXTYDZXSQJTZPXLCGLQTZWJBHCTSYJSFXYEJJTLBGXSXJMYJQQPFZASYJNTYDJXKJCDJSZCBARTDCLYJQMWNQNCLLLKBYBZZSYHQQLTWLCCXTXLLZNTYLNEWYZYXCZXXGRKRMTCNDNJTSYYSSDQDGHSDBJGHRWRQLYBGLXHLGTGXBQJDZPYJSJYJCTMRNYMGRZJCZGJMZMGXMPRYXKJNYMSGMZJYMKMFXMLDTGFBHCJHKYLPFMDXLQJJSMTQGZSJLQDLDGJYCALCMZCSDJLLNXDJFFFFJCZFMZFFPFKHKGDPSXKTACJDHHZDDCRRCFQYJKQCCWJDXHWJLYLLZGCFCQDSMLZPBJJPLSBCJGGDCKKDEZSQCCKJGCGKDJTJDLZYCXKLQSCGJCLTFPCQCZGWPJDQYZJJBYJHSJDZWGFSJGZKQCCZLLPSPKJGQJHZZLJPLGJGJJTHJJYJZCZMLZLYQBGJWMLJKXZDZNJQSYZMLJLLJKYWXMKJLHSKJGBMCLYYMKXJQLBMLLKMDXXKWYXYSLMLPSJQQJQXYXFJTJDXMXXLLCXQBSYJBGWYMBGGBCYXPJYGPEPFGDJGBHBNSQJYZJKJKHXQFGQZKFHYGKHDKLLSDJQXPQYKYBNQSXQNSZSWHBSXWHXWBZZXDMNSJBSBKBBZKLYLXGWXDRWYQZMYWSJQLCJXXJXKJEQXSCYETLZHLYYYSDZPAQYZCMTLSHTZCFYZYXYLJSDCJQAGYSLCQLYYYSHMRQQKLDXZSCSSSYDYCJYSFSJBFRSSZQSBXXPXJYSDRCKGJLGDKZJZBDKTCSYQPYHSTCLDJDHMXMCGXYZHJDDTMHLTXZXYLYMOHYJCLTYFBQQXPFBDFHHTKSQHZYYWCNXXCRWHOWGYJLEGWDQCWGFJYCSNTMYTOLBYGWQWESJPWNMLRYDZSZTXYQPZGCWXHNGPYXSHMYQJXZTDPPBFYHZHTJYFDZWKGKZBLDNTSXHQEEGZZYLZMMZYJZGXZXKHKSTXNXXWYLYAPSTHXDWHZYMPXAGKYDXBHNHXKDPJNMYHYLPMGOCSLNZHKXXLPZZLBMLSFBHHGYGYYGGBHSCYAQTYWLXTZQCEZYDQDQMMHTKLLSZHLSJZWFYHQSWSCWLQAZYNYTLSXTHAZNKZZSZZLAXXZWWCTGQQTDDYZTCCHYQZFLXPSLZYGPZSZNGLNDQTBDLXGTCTAJDKYWNSYZLJHHZZCWNYYZYWMHYCHHYXHJKZWSXHZYXLYSKQYSPSLYZWMYPPKBYGLKZHTYXAXQSYSHXASMCHKDSCRSWJPWXSGZJLWWSCHSJHSQNHCSEGNDAQTBAALZZMSSTDQJCJKTSCJAXPLGGXHHGXXZCXPDMMHLDGTYBYSJMXHMRCPXXJZCKZXSHMLQXXTTHXWZFKHCCZDYTCJYXQHLXDHYPJQXYLSYYDZOZJNYXQEZYSQYAYXWYPDGXDDXSPPYZNDLTWRHXYDXZZJHTCXMCZLHPYYYYMHZLLHNXMYLLLMDCPPXHMXDKYCYRDLTXJCHHZZXZLCCLYLNZSHZJZZLNNRLWHYQSNJHXYNTTTKYJPYCHHYEGKCTTWLGQRLGGTGTYGYHPYHYLQYQGCWYQKPYYYTTTTLHYHLLTYTTSPLKYZXGZWGPYDSSZZDQXSKCQNMJJZZBXYQMJRTFFBTKHZKBXLJJKDXJTLBWFZPPTKQTZTGPDGNTPJYFALQMKGXBDCLZFHZCLLLLADPMXDJHLCCLGYHDZFGYDDGCYYFGYDXKSSEBDHYKDKDKHNAXXYBPBYYHXZQGAFFQYJXDMLJCSQZLLPCHBSXGJYNDYBYQSPZWJLZKSDDTACTBXZDYZYPJZQSJNKKTKNJDJGYYPGTLFYQKASDNTCYHBLWDZHBBYDWJRYGKZYHEYYFJMSDTYFZJJHGCXPLXHLDWXXJKYTCYKSSSMTWCTTQZLPBSZDZWZXGZAGYKTYWXLHLSPBCLLOQMMZSSLCMBJCSZZKYDCZJGQQDSMCYTZQQLWZQZXSSFPTTFQMDDZDSHDTDWFHTDYZJYQJQKYPBDJYYXTLJHDRQXXXHAYDHRJLKLYTWHLLRLLRCXYLBWSRSZZSYMKZZHHKYHXKSMDSYDYCJPBZBSQLFCXXXNXKXWYWSDZYQOGGQMMYHCDZTTFJYYBGSTTTYBYKJDHKYXBELHTYPJQNFXFDYKZHQKZBYJTZBXHFDXKDASWTAWAJLDYJSFHBLDNNTNQJTJNCHXFJSRFWHZFMDRYJYJWZPDJKZYJYMPCYZNYNXFBYTFYFWYGDBNZZZDNYTXZEMMQBSQEHXFZMBMFLZZSRXYMJGSXWZJSPRYDJSJGXHJJGLJJYNZZJXHGXKYMLPYYYCXYTWQZSWHWLYRJLPXSLSXMFSWWKLCTNXNYNPSJSZHDZEPTXMYYWXYYSYWLXJQZQXZDCLEEELMCPJPCLWBXSQHFWWTFFJTNQJHJQDXHWLBYZNFJLALKYYJLDXHHYCSTYYWNRJYXYWTRMDRQHWQCMFJDYZMHMYYXJWMYZQZXTLMRSPWWCHAQBXYGZYPXYYRRCLMPYMGKSJSZYSRMYJSNXTPLNBAPPYPYLXYYZKYNLDZYJZCZNNLMZHHARQMPGWQTZMXXMLLHGDZXYHXKYXYCJMFFYYHJFSBSSQLXXNDYCANNMTCJCYPRRNYTYQNYYMBMSXNDLYLYSLJRLXYSXQMLLYZLZJJJKYZZCSFBZXXMSTBJGNXYZHLXNMCWSCYZYFZLXBRNNNYLBNRTGZQYSATSWRYHYJZMZDHZGZDWYBSSCSKXSYHYTXXGCQGXZZSHYXJSCRHMKKBXCZJYJYMKQHZJFNBHMQHYSNJNZYBKNQMCLGQHWLZNZSWXKHLJHYYBQLBFCDSXDLDSPFZPSKJYZWZXZDDXJSMMEGJSCSSMGCLXXKYYYLNYPWWWGYDKZJGGGZGGSYCKNJWNJPCXBJJTQTJWDSSPJXZXNZXUMELPXFSXTLLXCLJXJJLJZXCTPSWXLYDHLYQRWHSYCSQYYBYAYWJJJQFWQCQQCJQGXALDBZZYJGKGXPLTZYFXJLTPADKYQHPMATLCPDCKBMTXYBHKLENXDLEEGQDYMSAWHZMLJTWYGXLYQZLJEEYYBQQFFNLYXRDSCTGJGXYYNKLLYQKCCTLHJLQMKKZGCYYGLLLJDZGYDHZWXPYSJBZKDZGYZZHYWYFQYTYZSZYEZZLYMHJJHTSMQWYZLKYYWZCSRKQYTLTDXWCTYJKLWSQZWBDCQYNCJSRSZJLKCDCDTLZZZACQQZZDDXYPLXZBQJYLZLLLQDDZQJYJYJZYXNYYYNYJXKXDAZWYRDLJYYYRJLXLLDYXJCYWYWNQCCLDDNYYYNYCKCZHXXCCLGZQJGKWPPCQQJYSBZZXYJSQPXJPZBSBDSFNSFPZXHDWZTDWPPTFLZZBZDMYYPQJRSDZSQZSQXBDGCPZSWDWCSQZGMDHZXMWWFYBPDGPHTMJTHZSMMBGZMBZJCFZWFZBBZMQCFMBDMCJXLGPNJBBXGYHYYJGPTZGZMQBQTCGYXJXLWZKYDPDYMGCFTPFXYZTZXDZXTGKMTYBBCLBJASKYTSSQYYMSZXFJEWLXLLSZBQJJJAKLYLXLYCCTSXMCWFKKKBSXLLLLJYXTYLTJYYTDPJHNHNNKBYQNFQYYZBYYESSESSGDYHFHWTCJBSDZZTFDMXHCNJZYMQWSRYJDZJQPDQBBSTJGGFBKJBXTGQHNGWJXJGDLLTHZHHYYYYYYSXWTYYYCCBDBPYPZYCCZYJPZYWCBDLFWZCWJDXXHYHLHWZZXJTCZLCDPXUJCZZZLYXJJTXPHFXWPYWXZPTDZZBDZCYHJHMLXBQXSBYLRDTGJRRCTTTHYTCZWMXFYTWWZCWJWXJYWCSKYBZSCCTZQNHXNWXXKHKFHTSWOCCJYBCMPZZYKBNNZPBZHHZDLSYDDYTYFJPXYNGFXBYQXCBHXCPSXTYZDMKYSNXSXLHKMZXLYHDHKWHXXSSKQYHHCJYXGLHZXCSNHEKDTGZXQYPKDHEXTYKCNYMYYYPKQYYYKXZLTHJQTBYQHXBMYHSQCKWWYLLHCYYLNNEQXQWMCFBDCCMLJGGXDQKTLXKGNQCDGZJWYJJLYHHQTTTNWCHMXCXWHWSZJYDJCCDBQCDGDNYXZTHCQRXCBHZTQCBXWGQWYYBXHMBYMYQTYEXMQKYAQYRGYZSLFYKKQHYSSQYSHJGJCNXKZYCXSBXYXHYYLSTYCXQTHYSMGSCPMMGCCCCCMTZTASMGQZJHKLOSQYLSWTMXSYQKDZLJQQYPLSYCZTCQQPBBQJZCLPKHQZYYXXDTDDTSJCXFFLLCHQXMJLWCJCXTSPYCXNDTJSHJWXDQQJSKXYAMYLSJHMLALYKXCYYDMNMDQMXMCZNNCYBZKKYFLMCHCMLHXRCJJHSYLNMTJZGZGYWJXSRXCWJGJQHQZDQJDCJJZKJKGDZQGJJYJYLXZXXCDQHHHEYTMHLFSBDJSYYSHFYSTCZQLPBDRFRZTZYKYWHSZYQKWDQZRKMSYNBCRXQBJYFAZPZZEDZCJYWBCJWHYJBQSZYWRYSZPTDKZPFPBNZTKLQYHBBZPNPPTYZZYBQNYDCPJMMCYCQMCYFZZDCMNLFPBPLNGQJTBTTNJZPZBBZNJKLJQYLNBZQHKSJZNGGQSZZKYXSHPZSNBCGZKDDZQANZHJKDRTLZLSWJLJZLYWTJNDJZJHXYAYNCBGTZCSSQMNJPJYTYSWXZFKWJQTKHTZPLBHSNJZSYZBWZZZZLSYLSBJHDWWQPSLMMFBJDWAQYZTCJTBNNWZXQXCDSLQGDSDPDZHJTQQPSWLYYJZLGYXYZLCTCBJTKTYCZJTQKBSJLGMGZDMCSGPYNJZYQYYKNXRPWSZXMTNCSZZYXYBYHYZAXYWQCJTLLCKJJTJHGDXDXYQYZZBYWDLWQCGLZGJGQRQZCZSSBCRPCSKYDZNXJSQGXSSJMYDNSTZTPBDLTKZWXQWQTZEXNQCZGWEZKSSBYBRTSSSLCCGBPSZQSZLCCGLLLZXHZQTHCZMQGYZQZNMCOCSZJMMZSQPJYGQLJYJPPLDXRGZYXCCSXHSHGTZNLZWZKJCXTCFCJXLBMQBCZZWPQDNHXLJCTHYZLGYLNLSZZPCXDSCQQHJQKSXZPBAJYEMSMJTZDXLCJYRYYNWJBNGZZTMJXLTBSLYRZPYLSSCNXPHLLHYLLQQZQLXYMRSYCXZLMMCZLTZSDWTJJLLNZGGQXPFSKYGYGHBFZPDKMWGHCXMSGDXJMCJZDYCABXJDLNBCDQYGSKYDQTXDJJYXMSZQAZDZFSLQXYJSJZYLBTXXWXQQZBJZUFBBLYLWDSLJHXJYZJWTDJCZFQZQZZDZSXZZQLZCDZFJHYSPYMPQZMLPPLFFXJJNZZYLSJEYQZFPFZKSYWJJJHRDJZZXTXXGLGHYDXCSKYSWMMZCWYBAZBJKSHFHJCXMHFQHYXXYZFTSJYZFXYXPZLCHMZMBXHZZSXYFYMNCWDABAZLXKTCSHHXKXJJZJSTHYGXSXYYHHHJWXKZXSSBZZWHHHCWTZZZPJXSNXQQJGZYZYWLLCWXZFXXYXYHXMKYYSWSQMNLNAYCYSPMJKHWCQHYLAJJMZXHMMCNZHBHXCLXTJPLTXYJHDYYLTTXFSZHYXXSJBJYAYRSMXYPLCKDUYHLXRLNLLSTYZYYQYGYHHSCCSMZCTZQXKYQFPYYRPFFLKQUNTSZLLZMWWTCQQYZWTLLMLMPWMBZSSTZRBPDDTLQJJBXZCSRZQQYGWCSXFWZLXCCRSZDZMCYGGDZQSGTJSWLJMYMMZYHFBJDGYXCCPSHXNZCSBSJYJGJMPPWAFFYFNXHYZXZYLREMZGZCYZSSZDLLJCSQFNXZKPTXZGXJJGFMYYYSNBTYLBNLHPFZDCYFBMGQRRSSSZXYSGTZRNYDZZCDGPJAFJFZKNZBLCZSZPSGCYCJSZLMLRSZBZZLDLSLLYSXSQZQLYXZLSKKBRXBRBZCYCXZZZEEYFGKLZLYYHGZSGZLFJHGTGWKRAAJYZKZQTSSHJJXDCYZUYJLZYRZDQQHGJZXSSZBYKJPBFRTJXLLFQWJHYLQTYMBLPZDXTZYGBDHZZRBGXHWNJTJXLKSCFSMWLSDQYSJTXKZSCFWJLBXFTZLLJZLLQBLSQMQQCGCZFPBPHZCZJLPYYGGDTGWDCFCZQYYYQYSSCLXZSKLZZZGFFCQNWGLHQYZJJCZLQZZYJPJZZBPDCCMHJGXDQDGDLZQMFGPSYTSDYFWWDJZJYSXYYCZCYHZWPBYKXRYLYBHKJKSFXTZJMMCKHLLTNYYMSYXYZPYJQYCSYCWMTJJKQYRHLLQXPSGTLYYCLJSCPXJYZFNMLRGJJTYZBXYZMSJYJHHFZQMSYXRSZCWTLRTQZSSTKXGQKGSPTGCZNJSJCQCXHMXGGZTQYDJKZDLBZSXJLHYQGGGTHQSZPYHJHHGYYGKGGCWJZZYLCZLXQSFTGZSLLLMLJSKCTBLLZZSZMMNYTPZSXQHJCJYQXYZXZQZCPSHKZZYSXCDFGMWQRLLQXRFZTLYSTCTMJCXJJXHJNXTNRZTZFQYHQGLLGCXSZSJDJLJCYDSJTLNYXHSZXCGJZYQPYLFHDJSBPCCZHJJJQZJQDYBSSLLCMYTTMQTBHJQNNYGKYRQYQMZGCJKPDCGMYZHQLLSLLCLMHOLZGDYYFZSLJCQZLYLZQJESHNYLLJXGJXLYSYYYXNBZLJSSZCQQCJYLLZLTJYLLZLLBNYLGQCHXYYXOXCXQKYJXXXYKLXSXXYQXCYKQXQCSGYXXYQXYGYTQOHXHXPYXXXULCYEYCHZZCBWQBBWJQZSCSZSSLZYLKDESJZWMYMCYTSDSXXSCJPQQSQYLYYZYCMDJDZYWCBTJSYDJKCYDDJLBDJJSODZYSYXQQYXDHHGQQYQHDYXWGMMMAJDYBBBPPBCMUUPLJZSMTXERXJMHQNUTPJDCBSSMSSSTKJTSSMMTRCPLZSZMLQDSDMJMQPNQDXCFYNBFSDQXYXHYAYKQYDDLQYYYSSZBYDSLNTFQTZQPZMCHDHCZCWFDXTMYQSPHQYYXSRGJCWTJTZZQMGWJJTJHTQJBBHWZPXXHYQFXXQYWYYHYSCDYDHHQMNMTMWCPBSZPPZZGLMZFOLLCFWHMMSJZTTDHZZYFFYTZZGZYSKYJXQYJZQBHMBZZLYGHGFMSHPZFZSNCLPBQSNJXZSLXXFPMTYJYGBXLLDLXPZJYZJYHHZCYWHJYLSJEXFSZZYWXKZJLUYDTMLYMQJPWXYHXSKTQJEZRPXXZHHMHWQPWQLYJJQJJZSZCPHJLCHHNXJLQWZJHBMZYXBDHHYPZLHLHLGFWLCHYYTLHJXCJMSCPXSTKPNHQXSRTYXXTESYJCTLSSLSTDLLLWWYHDHRJZSFGXTSYCZYNYHTDHWJSLHTZDQDJZXXQHGYLTZPHCSQFCLNJTCLZPFSTPDYNYLGMJLLYCQHYSSHCHYLHQYQTMZYPBYWRFQYKQSYSLZDQJMPXYYSSRHZJNYWTQDFZBWWTWWRXCWHGYHXMKMYYYQMSMZHNGCEPMLQQMTCWCTMMPXJPJJHFXYYZSXZHTYBMSTSYJTTQQQYYLHYNPYQZLCYZHZWSMYLKFJXLWGXYPJYTYSYXYMZCKTTWLKSMZSYLMPWLZWXWQZSSAQSYXYRHSSNTSRAPXCPWCMGDXHXZDZYFJHGZTTSBJHGYZSZYSMYCLLLXBTYXHBBZJKSSDMALXHYCFYGMQYPJYCQXJLLLJGSLZGQLYCJCCZOTYXMTMTTLLWTGPXYMZMKLPSZZZXHKQYSXCTYJZYHXSHYXZKXLZWPSQPYHJWPJPWXQQYLXSDHMRSLZZYZWTTCYXYSZZSHBSCCSTPLWSSCJCHNLCGCHSSPHYLHFHHXJSXYLLNYLSZDHZXYLSXLWZYKCLDYAXZCMDDYSPJTQJZLNWQPSSSWCTSTSZLBLNXSMNYYMJQBQHRZWTYYDCHQLXKPZWBGQYBKFCMZWPZLLYYLSZYDWHXPSBCMLJBSCGBHXLQHYRLJXYSWXWXZSLDFHLSLYNJLZYFLYJYCDRJLFSYZFSLLCQYQFGJYHYXZLYLMSTDJCYHBZLLNWLXXYGYYHSMGDHXXHHLZZJZXCZZZCYQZFNGWPYLCPKPYYPMCLQKDGXZGGWQBDXZZKZFBXXLZXJTPJPTTBYTSZZDWSLCHZHSLTYXHQLHYXXXYYZYSWTXZKHLXZXZPYHGCHKCFSYHUTJRLXFJXPTZTWHPLYXFCRHXSHXKYXXYHZQDXQWULHYHMJTBFLKHTXCWHJFWJCFPQRYQXCYYYQYGRPYWSGSUNGWCHKZDXYFLXXHJJBYZWTSXXNCYJJYMSWZJQRMHXZWFQSYLZJZGBHYNSLBGTTCSYBYXXWXYHXYYXNSQYXMQYWRGYQLXBBZLJSYLPSYTJZYHYZAWLRORJMKSCZJXXXYXCHDYXRYXXJDTSQFXLYLTSFFYXLMTYJMJUYYYXLTZCSXQZQHZXLYYXZHDNBRXXXJCTYHLBRLMBRLLAXKYLLLJLYXXLYCRYLCJTGJCMTLZLLCYZZPZPCYAWHJJFYBDYYZSMPCKZDQYQPBPCJPDCYZMDPBCYYDYCNNPLMTMLRMFMMGWYZBSJGYGSMZQQQZTXMKQWGXLLPJGZBQCDJJJFPKJKCXBLJMSWMDTQJXLDLPPBXCWRCQFBFQJCZAHZGMYKPHYYHZYKNDKZMBPJYXPXYHLFPNYYGXJDBKXNXHJMZJXSTRSTLDXSKZYSYBZXJLXYSLBZYSLHXJPFXPQNBYLLJQKYGZMCYZZYMCCSLCLHZFWFWYXZMWSXTYNXJHPYYMCYSPMHYSMYDYSHQYZCHMJJMZCAAGCFJBBHPLYZYLXXSDJGXDHKXXTXXNBHRMLYJSLTXMRHNLXQJXYZLLYSWQGDLBJHDCGJYQYCMHWFMJYBMBYJYJWYMDPWHXQLDYGPDFXXBCGJSPCKRSSYZJMSLBZZJFLJJJLGXZGYXYXLSZQYXBEXYXHGCXBPLDYHWETTWWCJMBTXCHXYQXLLXFLYXLLJLSSFWDPZSMYJCLMWYTCZPCHQEKCQBWLCQYDPLQPPQZQFJQDJHYMMCXTXDRMJWRHXCJZYLQXDYYNHYYHRSLSRSYWWZJYMTLTLLGTQCJZYABTCKZCJYCCQLJZQXALMZYHYWLWDXZXQDLLQSHGPJFJLJHJABCQZDJGTKHSSTCYJLPSWZLXZXRWGLDLZRLZXTGSLLLLZLYXXWGDZYGBDPHZPBRLWSXQBPFDWOFMWHLYPCBJCCLDMBZPBZZLCYQXLDOMZBLZWPDWYYGDSTTHCSQSCCRSSSYSLFYBFNTYJSZDFNDPDHDZZMBBLSLCMYFFGTJJQWFTMTPJWFNLBZCMMJTGBDZLQLPYFHYYMJYLSDCHDZJWJCCTLJCLDTLJJCPDDSQDSSZYBNDBJLGGJZXSXNLYCYBJXQYCBYLZCFZPPGKCXZDZFZTJJFJSJXZBNZYJQTTYJYHTYCZHYMDJXTTMPXSPLZCDWSLSHXYPZGTFMLCJTYCBPMGDKWYCYZCDSZZYHFLYCTYGWHKJYYLSJCXGYWJCBLLCSNDDBTZBSCLYZCZZSSQDLLMQYYHFSLQLLXFTYHABXGWNYWYYPLLSDLDLLBJCYXJZMLHLJDXYYQYTDLLLBUGBFDFBBQJZZMDPJHGCLGMJJPGAEHHBWCQXAXHHHZCHXYPHJAXHLPHJPGPZJQCQZGJJZZUZDMQYYBZZPHYHYBWHAZYJHYKFGDPFQSDLZMLJXKXGALXZDAGLMDGXMWZQYXXDXXPFDMMSSYMPFMDMMKXKSYZYSHDZKXSYSMMZZZMSYDNZZCZXFPLSTMZDNMXCKJMZTYYMZMZZMSXHHDCZJEMXXKLJSTLWLSQLYJZLLZJSSDPPMHNLZJCZYHMXXHGZCJMDHXTKGRMXFWMCGMWKDTKSXQMMMFZZYDKMSCLCMPCGMHSPXQPZDSSLCXKYXTWLWJYAHZJGZQMCSNXYYMMPMLKJXMHLMLQMXCTKZMJQYSZJSYSZHSYJZJCDAJZYBSDQJZGWZQQXFKDMSDJLFWEHKZQKJPEYPZYSZCDWYJFFMZZYLTTDZZEFMZLBNPPLPLPEPSZALLTYLKCKQZKGENQLWAGYXYDPXLHSXQQWQCQXQCLHYXXMLYCCWLYMQYSKGCHLCJNSZKPYZKCQZQLJPDMDZHLASXLBYDWQLWDNBQCRYDDZTJYBKBWSZDXDTNPJDTCTQDFXQQMGNXECLTTBKPWSLCTYQLPWYZZKLPYGZCQQPLLKCCYLPQMZCZQCLJSLQZDJXLDDHPZQDLJJXZQDXYZQKZLJCYQDYJPPYPQYKJYRMPCBYMCXKLLZLLFQPYLLLMBSGLCYSSLRSYSQTMXYXZQZFDZUYSYZTFFMZZSMZQHZSSCCMLYXWTPZGXZJGZGSJSGKDDHTQGGZLLBJDZLCBCHYXYZHZFYWXYZYMSDBZZYJGTSMTFXQYXQSTDGSLNXDLRYZZLRYYLXQHTXSRTZNGZXBNQQZFMYKMZJBZYMKBPNLYZPBLMCNQYZZZSJZHJCTZKHYZZJRDYZHNPXGLFZTLKGJTCTSSYLLGZRZBBQZZKLPKLCZYSSUYXBJFPNJZZXCDWXZYJXZZDJJKGGRSRJKMSMZJLSJYWQSKYHQJSXPJZZZLSNSHRNYPZTWCHKLPSRZLZXYJQXQKYSJYCZTLQZYBBYBWZPQDWWYZCYTJCJXCKCWDKKZXSGKDZXWWYYJQYYTCYTDLLXWKCZKKLCCLZCQQDZLQLCSFQCHQHSFSMQZZLNBJJZBSJHTSZDYSJQJPDLZCDCWJKJZZLPYCGMZWDJJBSJQZSYZYHHXJPBJYDSSXDZNCGLQMBTSFSBPDZDLZNFGFJGFSMPXJQLMBLGQCYYXBQKDJJQYRFKZTJDHCZKLBSDZCFJTPLLJGXHYXZCSSZZXSTJYGKGCKGYOQXJPLZPBPGTGYJZGHZQZZLBJLSQFZGKQQJZGYCZBZQTLDXRJXBSXXPZXHYZYCLWDXJJHXMFDZPFZHQHQMQGKSLYHTYCGFRZGNQXCLPDLBZCSCZQLLJBLHBZCYPZZPPDYMZZSGYHCKCPZJGSLJLNSCDSLDLXBMSTLDDFJMKDJDHZLZXLSZQPQPGJLLYBDSZGQLBZLSLKYYHZTTNTJYQTZZPSZQZTLLJTYYLLQLLQYZQLBDZLSLYYZYMDFSZSNHLXZNCZQZPBWSKRFBSYZMTHBLGJPMCZZLSTLXSHTCSYZLZBLFEQHLXFLCJLYLJQCBZLZJHHSSTBRMHXZHJZCLXFNBGXGTQJCZTMSFZKJMSSNXLJKBHSJXNTNLZDNTLMSJXGZJYJCZXYJYJWRWWQNZTNFJSZPZSHZJFYRDJSFSZJZBJFZQZZHZLXFYSBZQLZSGYFTZDCSZXZJBQMSZKJRHYJZCKMJKHCHGTXKXQGLXPXFXTRTYLXJXHDTSJXHJZJXZWZLCQSBTXWXGXTXXHXFTSDKFJHZYJFJXRZSDLLLTQSQQZQWZXSYQTWGWBZCGZLLYZBCLMQQTZHZXZXLJFRMYZFLXYSQXXJKXRMQDZDMMYYBSQBHGZMWFWXGMXLZPYYTGZYCCDXYZXYWGSYJYZNBHPZJSQSYXSXRTFYZGRHZTXSZZTHCBFCLSYXZLZQMZLMPLMXZJXSFLBYZMYQHXJSXRXSQZZZSSLYFRCZJRCRXHHZXQYDYHXSJJHZCXZBTYNSYSXJBQLPXZQPYMLXZKYXLXCJLCYSXXZZLXDLLLJJYHZXGYJWKJRWYHCPSGNRZLFZWFZZNSXGXFLZSXZZZBFCSYJDBRJKRDHHGXJLJJTGXJXXSTJTJXLYXQFCSGSWMSBCTLQZZWLZZKXJMLTMJYHSDDBXGZHDLBMYJFRZFSGCLYJBPMLYSMSXLSZJQQHJZFXGFQFQBPXZGYYQXGZTCQWYLTLGWSGWHRLFSFGZJMGMGBGTJFSYZZGZYZAFLSSPMLPFLCWBJZCLJJMZLPJJLYMQDMYYYFBGYGYZMLYZDXQYXRQQQHSYYYQXYLJTYXFSFSLLGNQCYHYCWFHCCCFXPYLYPLLZYXXXXXKQHHXSHJZCFZSCZJXCPZWHHHHHAPYLQALPQAFYHXDYLUKMZQGGGDDESRNNZLTZGCHYPPYSQJJHCLLJTOLNJPZLJLHYMHEYDYDSQYCDDHGZUNDZCLZYZLLZNTNYZGSLHSLPJJBDGWXPCDUTJCKLKCLWKLLCASSTKZZDNQNTTLYYZSSYSSZZRYLJQKCQDHHCRXRZYDGRGCWCGZQFFFPPJFZYNAKRGYWYQPQXXFKJTSZZXSWZDDFBBXTBGTZKZNPZZPZXZPJSZBMQHKCYXYLDKLJNYPKYGHGDZJXXEAHPNZKZTZCMXCXMMJXNKSZQNMNLWBWWXJKYHCPSTMCSQTZJYXTPCTPDTNNPGLLLZSJLSPBLPLQHDTNJNLYYRSZFFJFQWDPHZDWMRZCCLODAXNSSNYZRESTYJWJYJDBCFXNMWTTBYLWSTSZGYBLJPXGLBOCLHPCBJLTMXZLJYLZXCLTPNCLCKXTPZJSWCYXSFYSZDKNTLBYJCYJLLSTGQCBXRYZXBXKLYLHZLQZLNZCXWJZLJZJNCJHXMNZZGJZZXTZJXYCYYCXXJYYXJJXSSSJSTSSTTPPGQTCSXWZDCSYFPTFBFHFBBLZJCLZZDBXGCXLQPXKFZFLSYLTUWBMQJHSZBMDDBCYSCCLDXYCDDQLYJJWMQLLCSGLJJSYFPYYCCYLTJANTJJPWYCMMGQYYSXDXQMZHSZXPFTWWZQSWQRFKJLZJQQYFBRXJHHFWJJZYQAZMYFRHCYYBYQWLPEXCCZSTYRLTTDMQLYKMBBGMYYJPRKZNPBSXYXBHYZDJDNGHPMFSGMWFZMFQMMBCMZZCJJLCNUXYQLMLRYGQZCYXZLWJGCJCGGMCJNFYZZJHYCPRRCMTZQZXHFQGTJXCCJEAQCRJYHPLQLSZDJRBCQHQDYRHYLYXJSYMHZYDWLDFRYHBPYDTSSCNWBXGLPZMLZZTQSSCPJMXXYCSJYTYCGHYCJWYRXXLFEMWJNMKLLSWTXHYYYNCMMCWJDQDJZGLLJWJRKHPZGGFLCCSCZMCBLTBHBQJXQDSPDJZZGHGLFQYWBZYZJLTSTDHQHCTCBCHFLQMPWDSHYYTQWCNZZJTLBYMBPDYYYXSQKXWYYFLXXNCWCXYPMAELYKKJMZZZBRXYYQJFLJPFHHHYTZZXSGQQMHSPGDZQWBWPJHZJDYSCQWZKTXXSQLZYYMYSDZGRXCKKUJLWPYSYSCSYZLRMLQSYLJXBCXTLWDQZPCYCYKPPPNSXFYZJJRCEMHSZMSXLXGLRWGCSTLRSXBZGBZGZTCPLUJLSLYLYMTXMTZPALZXPXJTJWTCYYZLBLXBZLQMYLXPGHDSLSSDMXMBDZZSXWHAMLCZCPJMCNHJYSNSYGCHSKQMZZQDLLKABLWJXSFMOCDXJRRLYQZKJMYBYQLYHETFJZFRFKSRYXFJTWDSXXSYSQJYSLYXWJHSNLXYYXHBHAWHHJZXWMYLJCSSLKYDZTXBZSYFDXGXZJKHSXXYBSSXDPYNZWRPTQZCZENYGCXQFJYKJBZMLJCMQQXUOXSLYXXLYLLJDZBTYMHPFSTTQQWLHOKYBLZZALZXQLHZWRRQHLSTMYPYXJJXMQSJFNBXYXYJXXYQYLTHYLQYFMLKLJTMLLHSZWKZHLJMLHLJKLJSTLQXYLMBHHLNLZXQJHXCFXXLHYHJJGBYZZKBXSCQDJQDSUJZYYHZHHMGSXCSYMXFEBCQWWRBPYYJQTYZCYQYQQZYHMWFFHGZFRJFCDPXNTQYZPDYKHJLFRZXPPXZDBBGZQSTLGDGYLCQMLCHHMFYWLZYXKJLYPQHSYWMQQGQZMLZJNSQXJQSYJYCBEHSXFSZPXZWFLLBCYYJDYTDTHWZSFJMQQYJLMQXXLLDTTKHHYBFPWTYYSQQWNQWLGWDEBZWCMYGCULKJXTMXMYJSXHYBRWFYMWFRXYQMXYSZTZZTFYKMLDHQDXWYYNLCRYJBLPSXCXYWLSPRRJWXHQYPHTYDNXHHMMYWYTZCSQMTSSCCDALWZTCPQPYJLLQZYJSWXMZZMMYLMXCLMXCZMXMZSQTZPPQQBLPGXQZHFLJJHYTJSRXWZXSCCDLXTYJDCQJXSLQYCLZXLZZXMXQRJMHRHZJBHMFLJLMLCLQNLDXZLLLPYPSYJYSXCQQDCMQJZZXHNPNXZMEKMXHYKYQLXSXTXJYYHWDCWDZHQYYBGYBCYSCFGPSJNZDYZZJZXRZRQJJYMCANYRJTLDPPYZBSTJKXXZYPFDWFGZZRPYMTNGXZQBYXNBUFNQKRJQZMJEGRZGYCLKXZDSKKNSXKCLJSPJYYZLQQJYBZSSQLLLKJXTBKTYLCCDDBLSPPFYLGYDTZJYQGGKQTTFZXBDKTYYHYBBFYTYYBCLPDYTGDHRYRNJSPTCSNYJQHKLLLZSLYDXXWBCJQSPXBPJZJCJDZFFXXBRMLAZHCSNDLBJDSZBLPRZTSWSBXBCLLXXLZDJZSJPYLYXXYFTFFFBHJJXGBYXJPMMMPSSJZJMTLYZJXSWXTYLEDQPJMYGQZJGDJLQJWJQLLSJGJGYGMSCLJJXDTYGJQJQJCJZCJGDZZSXQGSJGGCXHQXSNQLZZBXHSGZXCXYLJXYXYYDFQQJHJFXDHCTXJYRXYSQTJXYEFYYSSYYJXNCYZXFXMSYSZXYYSCHSHXZZZGZZZGFJDLTYLNPZGYJYZYYQZPBXQBDZTZCZYXXYHHSQXSHDHGQHJHGYWSZTMZMLHYXGEBTYLZKQWYTJZRCLEKYSTDBCYKQQSAYXCJXWWGSBHJYZYDHCSJKQCXSWXFLTYNYZPZCCZJQTZWJQDZZZQZLJJXLSBHPYXXPSXSHHEZTXFPTLQYZZXHYTXNCFZYYHXGNXMYWXTZSJPTHHGYMXMXQZXTSBCZYJYXXTYYZYPCQLMMSZMJZZLLZXGXZAAJZYXJMZXWDXZSXZDZXLEYJJZQBHZWZZZQTZPSXZTDSXJJJZNYAZPHXYYSRNQDTHZHYYKYJHDZXZLSWCLYBZYECWCYCRYLCXNHZYDZYDYJDFRJJHTRSQTXYXJRJHOJYNXELXSFSFJZGHPZSXZSZDZCQZBYYKLSGSJHCZSHDGQGXYZGXCHXZJWYQWGYHKSSEQZZNDZFKWYSSTCLZSTSYMCDHJXXYWEYXCZAYDMPXMDSXYBSQMJMZJMTZQLPJYQZCGQHXJHHLXXHLHDLDJQCLDWBSXFZZYYSCHTYTYYBHECXHYKGJPXHHYZJFXHWHBDZFYZBCAPNPGNYDMSXHMMMMAMYNBYJTMPXYYMCTHJBZYFCGTYHWPHFTWZZEZSBZEGPFMTSKFTYCMHFLLHGPZJXZJGZJYXZSBBQSCZZLZCCSTPGXMJSFTCCZJZDJXCYBZLFCJSYZFGSZLYBCWZZBYZDZYPSWYJZXZBDSYUXLZZBZFYGCZXBZHZFTPBGZGEJBSTGKDMFHYZZJHZLLZZGJQZLSFDJSSCBZGPDLFZFZSZYZYZSYGCXSNXXCHCZXTZZLJFZGQSQYXZJQDCCZTQCDXZJYQJQCHXZTDLGSCXZSYQJQTZWLQDQZTQCHQQJZYEZZZPBWKDJFCJPZTYPQYQTTYNLMBDKTJZPQZQZZFPZSBNJLGYJDXJDZZKZGQKXDLPZJTCJDQBXDJQJSTCKNXBXZMSLYJCQMTJQWWCJQNJNLLLHJCWQTBZQYDZCZPZZDZYDDCYZZZCCJTTJFZDPRRTZTJDCQTQZDTJNPLZBCLLCTZSXKJZQZPZLBZRBTJDCXFCZDBCCJJLTQQPLDCGZDBBZJCQDCJWYNLLZYZCCDWLLXWZLXRXNTQQCZXKQLSGDFQTDDGLRLAJJTKUYMKQLLTZYTDYYCZGJWYXDXFRSKSTQTENQMRKQZHHQKDLDAZFKYPBGGPZREBZZYKZZSPEGJXGYKQZZZSLYSYYYZWFQZYLZZLZHWCHKYPQGNPGBLPLRRJYXCCSYYHSFZFYBZYYTGZXYLXCZWXXZJZBLFFLGSKHYJZEYJHLPLLLLCZGXDRZELRHGKLZZYHZLYQSZZJZQLJZFLNBHGWLCZCFJYSPYXZLZLXGCCPZBLLCYBBBBUBBCBPCRNNZCZYRBFSRLDCGQYYQXYGMQZWTZYTYJXYFWTEHZZJYWLCCNTZYJJZDEDPZDZTSYQJHDYMBJNYJZLXTSSTPHNDJXXBYXQTZQDDTJTDYYTGWSCSZQFLSHLGLBCZPHDLYZJYCKWTYTYLBNYTSDSYCCTYSZYYEBHEXHQDTWNYGYCLXTSZYSTQMYGZAZCCSZZDSLZCLZRQXYYELJSBYMXSXZTEMBBLLYYLLYTDQYSHYMRQWKFKBFXNXSBYCHXBWJYHTQBPBSBWDZYLKGZSKYHXQZJXHXJXGNLJKZLYYCDXLFYFGHLJGJYBXQLYBXQPQGZTZPLNCYPXDJYQYDYMRBESJYYHKXXSTMXRCZZYWXYQYBMCLLYZHQYZWQXDBXBZWZMSLPDMYSKFMZKLZCYQYCZLQXFZZYDQZPZYGYJYZMZXDZFYFYTTQTZHGSPCZMLCCYTZXJCYTJMKSLPZHYSNZLLYTPZCTZZCKTXDHXXTQCYFKSMQCCYYAZHTJPCYLZLYJBJXTPNYLJYYNRXSYLMMNXJSMYBCSYSYLZYLXJJQYLDZLPQBFZZBLFNDXQKCZFYWHGQMRDSXYCYTXNQQJZYYPFZXDYZFPRXEJDGYQBXRCNFYYQPGHYJDYZXGRHTKYLNWDZNTSMPKLBTHBPYSZBZTJZSZZJTYYXZPHSSZZBZCZPTQFZMYFLYPYBBJQXZMXXDJMTSYSKKBJZXHJCKLPSMKYJZCXTMLJYXRZZQSLXXQPYZXMKYXXXJCLJPRMYYGADYSKQLSNDHYZKQXZYZTCGHZTLMLWZYBWSYCTBHJHJFCWZTXWYTKZLXQSHLYJZJXTMPLPYCGLTBZZTLZJCYJGDTCLKLPLLQPJMZPAPXYZLKKTKDZCZZBNZDYDYQZJYJGMCTXLTGXSZLMLHBGLKFWNWZHDXUHLFMKYSLGXDTWWFRJEJZTZHYDXYKSHWFZCQSHKTMQQHTZHYMJDJSKHXZJZBZZXYMPAGQMSTPXLSKLZYNWRTSQLSZBPSPSGZWYHTLKSSSWHZZLYYTNXJGMJSZSUFWNLSOZTXGXLSAMMLBWLDSZYLAKQCQCTMYCFJBSLXCLZZCLXXKSBZQCLHJPSQPLSXXCKSLNHPSFQQYTXYJZLQLDXZQJZDYYDJNZPTUZDSKJFSLJHYLZSQZLBTXYDGTQFDBYAZXDZHZJNHHQBYKNXJJQCZMLLJZKSPLDYCLBBLXKLELXJLBQYCXJXGCNLCQPLZLZYJTZLJGYZDZPLTQCSXFDMNYCXGBTJDCZNBGBQYQJWGKFHTNPYQZQGBKPBBYZMTJDYTBLSQMPSXTBNPDXKLEMYYCJYNZCTLDYKZZXDDXHQSHDGMZSJYCCTAYRZLPYLTLKXSLZCGGEXCLFXLKJRTLQJAQZNCMBYDKKCXGLCZJZXJHPTDJJMZQYKQSECQZDSHHADMLZFMMZBGNTJNNLGBYJBRBTMLBYJDZXLCJLPLDLPCQDHLXZLYCBLCXZZJADJLNZMMSSSMYBHBSQKBHRSXXJMXSDZNZPXLGBRHWGGFCXGMSKLLTSJYYCQLTSKYWYYHYWXBXQYWPYWYKQLSQPTNTKHQCWDQKTWPXXHCPTHTWUMSSYHBWCRWXHJMKMZNGWTMLKFGHKJYLSYYCXWHYECLQHKQHTTQKHFZLDXQWYZYYDESBPKYRZPJFYYZJCEQDZZDLATZBBFJLLCXDLMJSSXEGYGSJQXCWBXSSZPDYZCXDNYXPPZYDLYJCZPLTXLSXYZYRXCYYYDYLWWNZSAHJSYQYHGYWWAXTJZDAXYSRLTDPSSYYFNEJDXYZHLXLLLZQZSJNYQYQQXYJGHZGZCYJCHZLYCDSHWSHJZYJXCLLNXZJJYYXNFXMWFPYLCYLLABWDDHWDXJMCXZTZPMLQZHSFHZYNZTLLDYWLSLXHYMMYLMBWWKYXYADTXYLLDJPYBPWUXJMWMLLSAFDLLYFLBHHHBQQLTZJCQJLDJTFFKMMMBYTHYGDCQRDDWRQJXNBYSNWZDBYYTBJHPYBYTTJXAAHGQDQTMYSTQXKBTZPKJLZRBEQQSSMJJBDJOTGTBXPGBKTLHQXJJJCTHXQDWJLWRFWQGWSHCKRYSWGFTGYGBXSDWDWRFHWYTJJXXXJYZYSLPYYYPAYXHYDQKXSHXYXGSKQHYWFDDDPPLCJLQQEEWXKSYYKDYPLTJTHKJLTCYYHHJTTPLTZZCDLTHQKZXQYSTEEYWYYZYXXYYSTTJKLLPZMCYHQGXYHSRMBXPLLNQYDQHXSXXWGDQBSHYLLPJJJTHYJKYPPTHYYKTYEZYENMDSHLCRPQFDGFXZPSFTLJXXJBSWYYSKSFLXLPPLBBBLBSFXFYZBSJSSYLPBBFFFFSSCJDSTZSXZRYYSYFFSYZYZBJTBCTSBSDHRTJJBYTCXYJEYLXCBNEBJDSYXYKGSJZBXBYTFZWGENYHHTHZHHXFWGCSTBGXKLSXYWMTMBYXJSTZSCDYQRCYTWXZFHMYMCXLZNSDJTTTXRYCFYJSBSDYERXJLJXBBDEYNJGHXGCKGSCYMBLXJMSZNSKGXFBNBPTHFJAAFXYXFPXMYPQDTZCXZZPXRSYWZDLYBBKTYQPQJPZYPZJZNJPZJLZZFYSBTTSLMPTZRTDXQSJEHBZYLZDHLJSQMLHTXTJECXSLZZSPKTLZKQQYFSYGYWPCPQFHQHYTQXZKRSGTTSQCZLPTXCDYYZXSQZSLXLZMYCPCQBZYXHBSXLZDLTCDXTYLZJYYZPZYZLTXJSJXHLPMYTXCQRBLZSSFJZZTNJYTXMYJHLHPPLCYXQJQQKZZSCPZKSWALQSBLCCZJSXGWWWYGYKTJBBZTDKHXHKGTGPBKQYSLPXPJCKBMLLXDZSTBKLGGQKQLSBKKTFXRMDKBFTPZFRTBBRFERQGXYJPZSSTLBZTPSZQZSJDHLJQLZBPMSMMSXLQQNHKNBLRDDNXXDHDDJCYYGYLXGZLXSYGMQQGKHBPMXYXLYTQWLWGCPBMQXCYZYDRJBHTDJYHQSHTMJSBYPLWHLZFFNYPMHXXHPLTBQPFBJWQDBYGPNZTPFZJGSDDTQSHZEAWZZYLLTYYBWJKXXGHLFKXDJTMSZSQYNZGGSWQSPHTLSSKMCLZXYSZQZXNCJDQGZDLFNYKLJCJLLZLMZZNHYDSSHTHZZLZZBBHQZWWYCRZHLYQQJBEYFXXXWHSRXWQHWPSLMSSKZTTYGYQQWRSLALHMJTQJSMXQBJJZJXZYZKXBYQXBJXSHZTSFJLXMXZXFGHKZSZGGYLCLSARJYHSLLLMZXELGLXYDJYTLFBHBPNLYZFBBHPTGJKWETZHKJJXZXXGLLJLSTGSHJJYQLQZFKCGNNDJSSZFDBCTWWSEQFHQJBSAQTGYPQLBXBMMYWXGSLZHGLZGQYFLZBYFZJFRYSFMBYZHQGFWZSYFYJJPHZBYYZFFWODGRLMFTWLBZGYCQXCDJYGZYYYYTYTYDWEGAZYHXJLZYYHLRMGRXXZCLHNELJJTJTPWJYBJJBXJJTJTEEKHWSLJPLPSFYZPQQBDLQJJTYYQLYZKDKSQJYYQZLDQTGJQYZJSUCMRYQTHTEJMFCTYHYPKMHYZWJDQFHYYXWSHCTXRLJHQXHCCYYYJLTKTTYTMXGTCJTZAYYOCZLYLBSZYWJYTSJYHBYSHFJLYGJXXTMZYYLTXXYPZLXYJZYZYYPNHMYMDYYLBLHLSYYQQLLNJJYMSOYQBZGDLYXYLCQYXTSZEGXHZGLHWBLJHEYXTWQMAKBPQCGYSHHEGQCMWYYWLJYJHYYZLLJJYLHZYHMGSLJLJXCJJYCLYCJPCPZJZJMMYLCQLNQLJQJSXYJMLSZLJQLYCMMHCFMMFPQQMFYLQMCFFQMMMMHMZNFHHJGTTHHKHSLNCHHYQDXTMMQDCYZYXYQMYQYLTDCYYYZAZZCYMZYDLZFFFMMYCQZWZZMABTBYZTDMNZZGGDFTYPCGQYTTSSFFWFDTZQSSYSTWXJHXYTSXXYLBYQHWWKXHZXWZNNZZJZJJQJCCCHYYXBZXZCYZTLLCQXYNJYCYYCYNZZQYYYEWYCZDCJYCCHYJLBTZYYCQWMPWPYMLGKDLDLGKQQBGYCHJXY"; + + // 此处收录了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", + 20315: "BF", + 20340: "NE", + 20375: "TD", + 20389: "YJ", + 20391: "CZ", + 20415: "PB", + 20446: "YS", + 20447: "SQ", + 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; + } + }; +})();_.extend(BI, { + $import: function () { + var _LOADED = {}; // alex:保存加载过的 + function loadReady (src, must) { + var $scripts = $("head script, body 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; + }; + + p.has = function (key) { + return this._keymap[key] != null; + }; +})(); +!(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.length = 0; + } + }; +})();!(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); + }); + } + }; +})(); +(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) && 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; + } + 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; + } + 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; + } +};/** + * 缓冲池 + * @type {{Buffer: {}}} + */ + +(function () { + var Buffer = {}; + var MODE = false;// 设置缓存模式为关闭 + + BI.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 = {}; + BI.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 && copy[args[i]]; + } + return copy; + }, + + get: function () { + return BI.deepClone(this.cat.apply(this, arguments)); + }, + + remove: function (key) { + delete _Shared[key]; + } + }; +})();BI.Req = { + +};