Browse Source

KERNEL-13972 refactor: base/collection、base/tree es6化和修改bi.xxx

es6
Joker.Wang-王顺 2 years ago
parent
commit
50db461708
  1. 347
      src/base/collection/collection.js
  2. 90
      src/base/grid/grid.js
  3. 12
      src/base/index.js
  4. 2
      src/base/layer/index.js
  5. 361
      src/base/layer/layer.drawer.js
  6. 358
      src/base/layer/layer.popover.js
  7. 639
      src/base/layer/layer.popup.js
  8. 193
      src/base/layer/layer.searcher.js
  9. 2
      src/base/list/index.js
  10. 166
      src/base/list/listview.js
  11. 285
      src/base/list/virtualgrouplist.js
  12. 325
      src/base/list/virtuallist.js
  13. 125
      src/base/pager/pager.js
  14. 36
      src/base/single/a/a.js
  15. 2
      src/base/single/index.js
  16. 24
      src/base/single/tip/0.tip.js
  17. 2
      src/base/single/tip/index.js
  18. 181
      src/base/single/tip/tip.toast.js
  19. 133
      src/base/single/tip/tip.tooltip.js
  20. 137
      src/base/tree/customtree.js
  21. 6
      src/core/index.js

347
src/base/collection/collection.js

@ -5,9 +5,12 @@
* @class BI.CollectionView * @class BI.CollectionView
* @extends BI.Widget * @extends BI.Widget
*/ */
BI.CollectionView = BI.inherit(BI.Widget, { import { Widget, shortcut, extend, emptyFn, debounce, _lazyCreateWidget, isFunction, SectionManager,
_defaultConfig: function () { isNull, each, clamp, toArray, invert, min, max, nextTick } from "../../core";
return BI.extend(BI.CollectionView.superclass._defaultConfig.apply(this, arguments), { @shortcut()
export class CollectionView extends Widget {
_defaultConfig() {
return extend(super._defaultConfig(...arguments), {
baseCls: "bi-collection", baseCls: "bi-collection",
// width: 400, //必设 // width: 400, //必设
// height: 300, //必设 // height: 300, //必设
@ -17,97 +20,100 @@ BI.CollectionView = BI.inherit(BI.Widget, {
overflowX: true, overflowX: true,
overflowY: true, overflowY: true,
el: { el: {
type: "bi.vertical" type: "bi.vertical",
}, },
cellSizeAndPositionGetter: BI.emptyFn, cellSizeAndPositionGetter: emptyFn,
horizontalOverscanSize: 0, horizontalOverscanSize: 0,
verticalOverscanSize: 0, verticalOverscanSize: 0,
scrollLeft: 0, scrollLeft: 0,
scrollTop: 0, scrollTop: 0,
items: [], items: [],
itemFormatter: function (item, index) { itemFormatter: (item, index) => item,
return item;
},
}); });
}, }
static EVENT_SCROLL = "EVENT_SCROLL";
static xtype = "bi.collection_view";
render: function () { render() {
var self = this, o = this.options; const o = this.options;
const { overflowX, overflowY, el } = this.options;
this.renderedCells = []; this.renderedCells = [];
this.renderedKeys = []; this.renderedKeys = [];
this.renderRange = {}; this.renderRange = {};
this._scrollLock = false; this._scrollLock = false;
this._debounceRelease = BI.debounce(function () { this._debounceRelease = debounce(() => {
self._scrollLock = false; this._scrollLock = false;
}, 1000 / 60); }, 1000 / 60);
this.container = BI._lazyCreateWidget({ this.container = _lazyCreateWidget({
type: "bi.absolute", type: "bi.absolute",
}); });
this.element.scroll(function () { this.element.scroll(() => {
if (self._scrollLock === true) { if (this._scrollLock === true) {
return; return;
} }
o.scrollLeft = self.element.scrollLeft(); o.scrollLeft = this.element.scrollLeft();
o.scrollTop = self.element.scrollTop(); o.scrollTop = this.element.scrollTop();
self._calculateChildrenToRender(); this._calculateChildrenToRender();
self.fireEvent(BI.CollectionView.EVENT_SCROLL, { this.fireEvent(CollectionView.EVENT_SCROLL, {
scrollLeft: o.scrollLeft, scrollLeft: o.scrollLeft,
scrollTop: o.scrollTop, scrollTop: o.scrollTop,
}); });
}); });
// 兼容一下 // 兼容一下
var scrollable = o.scrollable, scrollx = o.scrollx, scrolly = o.scrolly; let scrollable = o.scrollable;
if (o.overflowX === false) { const scrollx = o.scrollx, scrolly = o.scrolly;
if (o.overflowY === false) { if (overflowX === false) {
if (overflowY === false) {
scrollable = false; scrollable = false;
} else { } else {
scrollable = "y"; scrollable = "y";
} }
} else { } else {
if (o.overflowY === false) { if (overflowY === false) {
scrollable = "x"; scrollable = "x";
} }
} }
BI._lazyCreateWidget(o.el, { _lazyCreateWidget(el, {
type: "bi.vertical", type: "bi.vertical",
element: this, element: this,
scrollable: scrollable, scrollable,
scrolly: scrolly, scrolly,
scrollx: scrollx, scrollx,
items: [this.container], items: [this.container],
}); });
o.items = BI.isFunction(o.items) ? this.__watch(o.items, function (context, newValue) { o.items = isFunction(o.items) ? this.__watch(o.items, (context, newValue) => {
self.populate(newValue); this.populate(newValue);
}) : o.items; }) : o.items;
if (o.items.length > 0) { if (o.items.length > 0) {
this._calculateSizeAndPositionData(); this._calculateSizeAndPositionData();
this._populate(); this._populate();
} }
}, }
// mounted之后绑定事件 // mounted之后绑定事件
mounted: function () { mounted() {
var o = this.options; const { scrollLeft, scrollTop } = this.options;
if (o.scrollLeft !== 0 || o.scrollTop !== 0) { if (scrollLeft !== 0 || scrollTop !== 0) {
this.element.scrollTop(o.scrollTop); this.element.scrollTop(scrollTop);
this.element.scrollLeft(o.scrollLeft); this.element.scrollLeft(scrollLeft);
} }
}, }
_calculateSizeAndPositionData: function () { _calculateSizeAndPositionData() {
var o = this.options; const { items, cellSizeAndPositionGetter } = this.options;
var cellMetadata = []; const cellMetadata = [];
var sectionManager = new BI.SectionManager(); const sectionManager = new SectionManager();
var height = 0; let height = 0;
var width = 0; let width = 0;
for (var index = 0, len = o.items.length; index < len; index++) { for (let index = 0, len = items.length; index < len; index++) {
var cellMetadatum = o.cellSizeAndPositionGetter(index); const cellMetadatum = cellSizeAndPositionGetter(index);
if (BI.isNull(cellMetadatum.height) || isNaN(cellMetadatum.height) || if (isNull(cellMetadatum.height) || isNaN(cellMetadatum.height) ||
BI.isNull(cellMetadatum.width) || isNaN(cellMetadatum.width) || isNull(cellMetadatum.width) || isNaN(cellMetadatum.width) ||
BI.isNull(cellMetadatum.x) || isNaN(cellMetadatum.x) || isNull(cellMetadatum.x) || isNaN(cellMetadatum.x) ||
BI.isNull(cellMetadatum.y) || isNaN(cellMetadatum.y)) { isNull(cellMetadatum.y) || isNaN(cellMetadatum.y)) {
throw Error(); throw Error();
} }
@ -123,110 +129,110 @@ BI.CollectionView = BI.inherit(BI.Widget, {
this._sectionManager = sectionManager; this._sectionManager = sectionManager;
this._height = height; this._height = height;
this._width = width; this._width = width;
}, }
_cellRenderers: function (height, width, x, y) { _cellRenderers(height, width, x, y) {
this._lastRenderedCellIndices = this._sectionManager.getCellIndices(height, width, x, y); this._lastRenderedCellIndices = this._sectionManager.getCellIndices(height, width, x, y);
return this._cellGroupRenderer(); return this._cellGroupRenderer();
}, }
_cellGroupRenderer: function () { _cellGroupRenderer() {
var self = this; const rendered = [];
var rendered = []; each(this._lastRenderedCellIndices, (i, index) => {
BI.each(this._lastRenderedCellIndices, function (i, index) { const cellMetadata = this._sectionManager.getCellMetadata(index);
var cellMetadata = self._sectionManager.getCellMetadata(index);
rendered.push(cellMetadata); rendered.push(cellMetadata);
}); });
return rendered; return rendered;
}, }
_calculateChildrenToRender: function () { _calculateChildrenToRender() {
var self = this, o = this.options; const o = this.options;
var scrollLeft = BI.clamp(o.scrollLeft, 0, this._getMaxScrollLeft()); const { horizontalOverscanSize, verticalOverscanSize, width, height, itemFormatter, items } = this.options;
var scrollTop = BI.clamp(o.scrollTop, 0, this._getMaxScrollTop()); const scrollLeft = clamp(o.scrollLeft, 0, this._getMaxScrollLeft());
var left = Math.max(0, scrollLeft - o.horizontalOverscanSize); const scrollTop = clamp(o.scrollTop, 0, this._getMaxScrollTop());
var top = Math.max(0, scrollTop - o.verticalOverscanSize); const left = Math.max(0, scrollLeft - horizontalOverscanSize);
var right = Math.min(this._width, scrollLeft + o.width + o.horizontalOverscanSize); const top = Math.max(0, scrollTop - verticalOverscanSize);
var bottom = Math.min(this._height, scrollTop + o.height + o.verticalOverscanSize); const right = Math.min(this._width, scrollLeft + width + horizontalOverscanSize);
const bottom = Math.min(this._height, scrollTop + height + verticalOverscanSize);
if (right > 0 && bottom > 0) { if (right > 0 && bottom > 0) {
// 如果滚动的区间并没有超出渲染的范围 // 如果滚动的区间并没有超出渲染的范围
if (top >= this.renderRange.minY && bottom <= this.renderRange.maxY && left >= this.renderRange.minX && right <= this.renderRange.maxX) { if (top >= this.renderRange.minY && bottom <= this.renderRange.maxY && left >= this.renderRange.minX && right <= this.renderRange.maxX) {
return; return;
} }
var childrenToDisplay = this._cellRenderers(bottom - top, right - left, left, top); const childrenToDisplay = this._cellRenderers(bottom - top, right - left, left, top);
var renderedCells = [], renderedKeys = {}, renderedWidgets = {}; const renderedCells = [], renderedKeys = {}, renderedWidgets = {};
// 存储所有的left和top // 存储所有的left和top
var lefts = {}, tops = {}; let lefts = {}, tops = {};
for (var i = 0, len = childrenToDisplay.length; i < len; i++) { for (let i = 0, len = childrenToDisplay.length; i < len; i++) {
var datum = childrenToDisplay[i]; const datum = childrenToDisplay[i];
lefts[datum.x] = datum.x; lefts[datum.x] = datum.x;
lefts[datum.x + datum.width] = datum.x + datum.width; lefts[datum.x + datum.width] = datum.x + datum.width;
tops[datum.y] = datum.y; tops[datum.y] = datum.y;
tops[datum.y + datum.height] = datum.y + datum.height; tops[datum.y + datum.height] = datum.y + datum.height;
} }
lefts = BI.toArray(lefts); lefts = toArray(lefts);
tops = BI.toArray(tops); tops = toArray(tops);
var leftMap = BI.invert(lefts); const leftMap = invert(lefts);
var topMap = BI.invert(tops); const topMap = invert(tops);
// 存储上下左右四个边界 // 存储上下左右四个边界
var leftBorder = {}, rightBorder = {}, topBorder = {}, bottomBorder = {}; const leftBorder = {}, rightBorder = {}, topBorder = {}, bottomBorder = {};
function assertMinBorder(border, offset) { function assertMinBorder(border, offset) {
if (BI.isNull(border[offset])) { if (isNull(border[offset])) {
border[offset] = Number.MAX_VALUE; border[offset] = Number.MAX_VALUE;
} }
} }
function assertMaxBorder(border, offset) { function assertMaxBorder(border, offset) {
if (BI.isNull(border[offset])) { if (isNull(border[offset])) {
border[offset] = 0; border[offset] = 0;
} }
} }
for (var i = 0, len = childrenToDisplay.length; i < len; i++) { for (let i = 0, len = childrenToDisplay.length; i < len; i++) {
var datum = childrenToDisplay[i]; const datum = childrenToDisplay[i];
var index = this.renderedKeys[datum.index] && this.renderedKeys[datum.index][1]; const index = this.renderedKeys[datum.index] && this.renderedKeys[datum.index][1];
var child; let child;
if (index >= 0) { if (index >= 0) {
this.renderedCells[index].el.setWidth(datum.width); this.renderedCells[index].el.setWidth(datum.width);
this.renderedCells[index].el.setHeight(datum.height); this.renderedCells[index].el.setHeight(datum.height);
// 这里只使用px // 这里只使用px
this.renderedCells[index].el.element.css("left", datum.x + "px"); this.renderedCells[index].el.element.css("left", `${datum.x}px`);
this.renderedCells[index].el.element.css("top", datum.y + "px"); this.renderedCells[index].el.element.css("top", `${datum.y}px`);
renderedCells.push(child = this.renderedCells[index]); renderedCells.push(child = this.renderedCells[index]);
} else { } else {
var item = o.itemFormatter(o.items[datum.index], datum.index); const item = itemFormatter(items[datum.index], datum.index);
child = BI._lazyCreateWidget(BI.extend({ child = _lazyCreateWidget(extend({
type: "bi.label", type: "bi.label",
width: datum.width, width: datum.width,
height: datum.height, height: datum.height,
}, item, { }, item, {
cls: (item.cls || "") + " collection-cell" + (datum.y === 0 ? " first-row" : "") + (datum.x === 0 ? " first-col" : ""), cls: `${item.cls || ""} collection-cell${datum.y === 0 ? " first-row" : ""}${datum.x === 0 ? " first-col" : ""}`,
_left: datum.x, _left: datum.x,
_top: datum.y, _top: datum.y,
})); }));
renderedCells.push({ renderedCells.push({
el: child, el: child,
left: datum.x + "px", left: `${datum.x}px`,
top: datum.y + "px", top: `${datum.y}px`,
_left: datum.x, _left: datum.x,
_top: datum.y, _top: datum.y,
// _width: datum.width, // _width: datum.width,
// _height: datum.height // _height: datum.height
}); });
} }
var startTopIndex = topMap[datum.y] | 0; const startTopIndex = topMap[datum.y] | 0;
var endTopIndex = topMap[datum.y + datum.height] | 0; const endTopIndex = topMap[datum.y + datum.height] | 0;
for (var k = startTopIndex; k <= endTopIndex; k++) { for (let k = startTopIndex; k <= endTopIndex; k++) {
var t = tops[k]; const t = tops[k];
assertMinBorder(leftBorder, t); assertMinBorder(leftBorder, t);
assertMaxBorder(rightBorder, t); assertMaxBorder(rightBorder, t);
leftBorder[t] = Math.min(leftBorder[t], datum.x); leftBorder[t] = Math.min(leftBorder[t], datum.x);
rightBorder[t] = Math.max(rightBorder[t], datum.x + datum.width); rightBorder[t] = Math.max(rightBorder[t], datum.x + datum.width);
} }
var startLeftIndex = leftMap[datum.x] | 0; const startLeftIndex = leftMap[datum.x] | 0;
var endLeftIndex = leftMap[datum.x + datum.width] | 0; const endLeftIndex = leftMap[datum.x + datum.width] | 0;
for (var k = startLeftIndex; k <= endLeftIndex; k++) { for (let k = startLeftIndex; k <= endLeftIndex; k++) {
var l = lefts[k]; const l = lefts[k];
assertMinBorder(topBorder, l); assertMinBorder(topBorder, l);
assertMaxBorder(bottomBorder, l); assertMaxBorder(bottomBorder, l);
topBorder[l] = Math.min(topBorder[l], datum.y); topBorder[l] = Math.min(topBorder[l], datum.y);
@ -237,15 +243,15 @@ BI.CollectionView = BI.inherit(BI.Widget, {
renderedWidgets[i] = child; renderedWidgets[i] = child;
} }
// 已存在的, 需要添加的和需要删除的 // 已存在的, 需要添加的和需要删除的
var existSet = {}, addSet = {}, deleteArray = []; const existSet = {}, addSet = {}, deleteArray = [];
BI.each(renderedKeys, function (i, key) { each(renderedKeys, (i, key) => {
if (self.renderedKeys[i]) { if (this.renderedKeys[i]) {
existSet[i] = key; existSet[i] = key;
} else { } else {
addSet[i] = key; addSet[i] = key;
} }
}); });
BI.each(this.renderedKeys, function (i, key) { each(this.renderedKeys, (i, key) => {
if (existSet[i]) { if (existSet[i]) {
return; return;
} }
@ -254,12 +260,12 @@ BI.CollectionView = BI.inherit(BI.Widget, {
} }
deleteArray.push(key[1]); deleteArray.push(key[1]);
}); });
BI.each(deleteArray, function (i, index) { each(deleteArray, (i, index) => {
// 性能优化,不调用destroy方法防止触发destroy事件 // 性能优化,不调用destroy方法防止触发destroy事件
self.renderedCells[index].el._destroy(); this.renderedCells[index].el._destroy();
}); });
var addedItems = []; const addedItems = [];
BI.each(addSet, function (index, key) { each(addSet, (index, key) => {
addedItems.push(renderedCells[key[1]]); addedItems.push(renderedCells[key[1]]);
}); });
this.container.addItems(addedItems); this.container.addItems(addedItems);
@ -270,21 +276,22 @@ BI.CollectionView = BI.inherit(BI.Widget, {
this.renderedKeys = renderedKeys; this.renderedKeys = renderedKeys;
// Todo 左右比较特殊 // Todo 左右比较特殊
var minX = BI.min(leftBorder); const minX = min(leftBorder);
var maxX = BI.max(rightBorder); const maxX = max(rightBorder);
var minY = BI.max(topBorder); const minY = max(topBorder);
var maxY = BI.min(bottomBorder); const maxY = min(bottomBorder);
this.renderRange = { minX: minX, minY: minY, maxX: maxX, maxY: maxY }; this.renderRange = { minX, minY, maxX, maxY };
} }
}, }
_isOverflowX: function () { _isOverflowX() {
var o = this.options; const o = this.options;
const { overflowX } = this.options;
// 兼容一下 // 兼容一下
var scrollable = o.scrollable, scrollx = o.scrollx; const scrollable = o.scrollable, scrollx = o.scrollx;
if (o.overflowX === false) { if (overflowX === false) {
return false; return false;
} }
if (scrollx) { if (scrollx) {
@ -293,14 +300,16 @@ BI.CollectionView = BI.inherit(BI.Widget, {
if (scrollable === true || scrollable === "xy" || scrollable === "x") { if (scrollable === true || scrollable === "xy" || scrollable === "x") {
return true; return true;
} }
return false; return false;
}, }
_isOverflowY: function () { _isOverflowY() {
var o = this.options; const o = this.options;
const { overflowX } = this.options;
// 兼容一下 // 兼容一下
var scrollable = o.scrollable, scrolly = o.scrolly; const scrollable = o.scrollable, scrolly = o.scrolly;
if (o.overflowX === false) { if (overflowX === false) {
return false; return false;
} }
if (scrolly) { if (scrolly) {
@ -309,19 +318,20 @@ BI.CollectionView = BI.inherit(BI.Widget, {
if (scrollable === true || scrollable === "xy" || scrollable === "y") { if (scrollable === true || scrollable === "xy" || scrollable === "y") {
return true; return true;
} }
return false; return false;
}, }
_getMaxScrollLeft: function () { _getMaxScrollLeft() {
return Math.max(0, this._width - this.options.width + (this._isOverflowX() ? BI.DOM.getScrollWidth() : 0)); return Math.max(0, this._width - this.options.width + (this._isOverflowX() ? BI.DOM.getScrollWidth() : 0));
}, }
_getMaxScrollTop: function () { _getMaxScrollTop() {
return Math.max(0, this._height - this.options.height + (this._isOverflowY() ? BI.DOM.getScrollWidth() : 0)); return Math.max(0, this._height - this.options.height + (this._isOverflowY() ? BI.DOM.getScrollWidth() : 0));
}, }
_populate: function (items) { _populate(items) {
var o = this.options; const { scrollTop, scrollLeft } = this.options;
this._reRange(); this._reRange();
if (items && items !== this.options.items) { if (items && items !== this.options.items) {
this.options.items = items; this.options.items = items;
@ -333,83 +343,80 @@ BI.CollectionView = BI.inherit(BI.Widget, {
this._debounceRelease(); this._debounceRelease();
// 元素未挂载时不能设置scrollTop // 元素未挂载时不能设置scrollTop
try { try {
this.element.scrollTop(o.scrollTop); this.element.scrollTop(scrollTop);
this.element.scrollLeft(o.scrollLeft); this.element.scrollLeft(scrollLeft);
} catch (e) { } catch (e) {
} }
this._calculateChildrenToRender(); this._calculateChildrenToRender();
}, }
setScrollLeft(scrollLeft) {
setScrollLeft: function (scrollLeft) {
if (this.options.scrollLeft === scrollLeft) { if (this.options.scrollLeft === scrollLeft) {
return; return;
} }
this._scrollLock = true; this._scrollLock = true;
this.options.scrollLeft = BI.clamp(scrollLeft || 0, 0, this._getMaxScrollLeft()); this.options.scrollLeft = clamp(scrollLeft || 0, 0, this._getMaxScrollLeft());
this._debounceRelease(); this._debounceRelease();
this.element.scrollLeft(this.options.scrollLeft); this.element.scrollLeft(this.options.scrollLeft);
this._calculateChildrenToRender(); this._calculateChildrenToRender();
}, }
setScrollTop: function (scrollTop) { setScrollTop(scrollTop) {
if (this.options.scrollTop === scrollTop) { if (this.options.scrollTop === scrollTop) {
return; return;
} }
this._scrollLock = true; this._scrollLock = true;
this.options.scrollTop = BI.clamp(scrollTop || 0, 0, this._getMaxScrollTop()); this.options.scrollTop = clamp(scrollTop || 0, 0, this._getMaxScrollTop());
this._debounceRelease(); this._debounceRelease();
this.element.scrollTop(this.options.scrollTop); this.element.scrollTop(this.options.scrollTop);
this._calculateChildrenToRender(); this._calculateChildrenToRender();
}, }
setOverflowX: function (b) { setOverflowX(b) {
var self = this;
if (this.options.overflowX !== !!b) { if (this.options.overflowX !== !!b) {
this.options.overflowX = !!b; this.options.overflowX = !!b;
BI.nextTick(function () { nextTick(() => {
self.element.css({ overflowX: b ? "auto" : "hidden" }); this.element.css({ overflowX: b ? "auto" : "hidden" });
}); });
} }
}, }
setOverflowY: function (b) { setOverflowY(b) {
var self = this;
if (this.options.overflowY !== !!b) { if (this.options.overflowY !== !!b) {
this.options.overflowY = !!b; this.options.overflowY = !!b;
BI.nextTick(function () { nextTick(() => {
self.element.css({ overflowY: b ? "auto" : "hidden" }); this.element.css({ overflowY: b ? "auto" : "hidden" });
}); });
} }
}, }
getScrollLeft: function () { getScrollLeft() {
return this.options.scrollLeft; return this.options.scrollLeft;
}, }
getScrollTop: function () { getScrollTop() {
return this.options.scrollTop; return this.options.scrollTop;
}, }
getMaxScrollLeft: function () { getMaxScrollLeft() {
return this._getMaxScrollLeft(); return this._getMaxScrollLeft();
}, }
getMaxScrollTop: function () { getMaxScrollTop() {
return this._getMaxScrollTop(); return this._getMaxScrollTop();
}, }
// 重新计算children // 重新计算children
_reRange: function () { _reRange() {
this.renderRange = {}; this.renderRange = {};
}, }
_clearChildren: function () { _clearChildren() {
this.container._children = {}; this.container._children = {};
this.container.attr("items", []); this.container.attr("items", []);
}, }
restore: function () { restore() {
BI.each(this.renderedCells, function (i, cell) { each(this.renderedCells, (i, cell) => {
cell.el._destroy(); cell.el._destroy();
}); });
this._clearChildren(); this._clearChildren();
@ -417,14 +424,12 @@ BI.CollectionView = BI.inherit(BI.Widget, {
this.renderedKeys = []; this.renderedKeys = [];
this.renderRange = {}; this.renderRange = {};
this._scrollLock = false; this._scrollLock = false;
}, }
populate: function (items) { populate(items) {
if (items && items !== this.options.items) { if (items && items !== this.options.items) {
this.restore(); this.restore();
} }
this._populate(items); this._populate(items);
}, }
}); }
BI.CollectionView.EVENT_SCROLL = "EVENT_SCROLL";
BI.shortcut("bi.collection_view", BI.CollectionView);

90
src/base/grid/grid.js

@ -5,11 +5,12 @@
* @class BI.GridView * @class BI.GridView
* @extends BI.Widget * @extends BI.Widget
*/ */
import { Widget, shortcut } from "../../core"; import { Widget, shortcut, extend, emptyFn, debounce, _lazyCreateWidget,
isFunction, each, isNumber, ScalingCellSizeAndPositionManager, clamp, isEmpty, nextTick } from "../../core";
@shortcut() @shortcut()
export default class GridView extends Widget { export class GridView extends Widget {
_defaultConfig() { _defaultConfig() {
return BI.extend(super._defaultConfig(arguments), { return extend(super._defaultConfig(...arguments), {
baseCls: "bi-grid-view", baseCls: "bi-grid-view",
// width: 400, //必设 // width: 400, //必设
// height: 300, //必设 // height: 300, //必设
@ -19,20 +20,18 @@ export default class GridView extends Widget {
overflowX: true, overflowX: true,
overflowY: true, overflowY: true,
el: { el: {
type: "bi.vertical" type: "bi.vertical",
}, },
overscanColumnCount: 0, overscanColumnCount: 0,
overscanRowCount: 0, overscanRowCount: 0,
rowHeightGetter: BI.emptyFn, // number类型或function类型 rowHeightGetter: emptyFn, // number类型或function类型
columnWidthGetter: BI.emptyFn, // number类型或function类型 columnWidthGetter: emptyFn, // number类型或function类型
// estimatedColumnSize: 100, //columnWidthGetter为function时必设 // estimatedColumnSize: 100, //columnWidthGetter为function时必设
// estimatedRowSize: 30, //rowHeightGetter为function时必设 // estimatedRowSize: 30, //rowHeightGetter为function时必设
scrollLeft: 0, scrollLeft: 0,
scrollTop: 0, scrollTop: 0,
items: [], items: [],
itemFormatter: (item, row, col) => { itemFormatter: (item, row, col) => item,
return item;
},
}); });
} }
@ -46,10 +45,10 @@ export default class GridView extends Widget {
this.renderedKeys = []; this.renderedKeys = [];
this.renderRange = {}; this.renderRange = {};
this._scrollLock = false; this._scrollLock = false;
this._debounceRelease = BI.debounce(() => { this._debounceRelease = debounce(() => {
this._scrollLock = false; this._scrollLock = false;
}, 1000 / 60); }, 1000 / 60);
this.container = BI._lazyCreateWidget({ this.container = _lazyCreateWidget({
type: "bi.absolute", type: "bi.absolute",
}); });
this.element.scroll(() => { this.element.scroll(() => {
@ -65,7 +64,8 @@ export default class GridView extends Widget {
}); });
}); });
// 兼容一下 // 兼容一下
let scrollable = o.scrollable, scrollx = o.scrollx, scrolly = o.scrolly; let scrollable = o.scrollable;
const scrollx = o.scrollx, scrolly = o.scrolly;
if (overflowX === false) { if (overflowX === false) {
if (overflowY === false) { if (overflowY === false) {
scrollable = false; scrollable = false;
@ -77,15 +77,15 @@ export default class GridView extends Widget {
scrollable = "x"; scrollable = "x";
} }
} }
BI._lazyCreateWidget(el, { _lazyCreateWidget(el, {
type: "bi.vertical", type: "bi.vertical",
element: this, element: this,
scrollable: scrollable, scrollable,
scrolly: scrolly, scrolly,
scrollx: scrollx, scrollx,
items: [this.container], items: [this.container],
}); });
o.items = BI.isFunction(o.items) ? this.__watch(o.items, (context, newValue) => { o.items = isFunction(o.items) ? this.__watch(o.items, (context, newValue) => {
this.populate(newValue); this.populate(newValue);
}) : o.items; }) : o.items;
if (o.items.length > 0) { if (o.items.length > 0) {
@ -104,27 +104,27 @@ export default class GridView extends Widget {
} }
destroyed() { destroyed() {
BI.each(this.renderedCells, (i, cell) => { each(this.renderedCells, (i, cell) => {
cell.el._destroy(); cell.el._destroy();
}) });
} }
_calculateSizeAndPositionData() { _calculateSizeAndPositionData() {
const { columnCount, items, rowCount, columnWidthGetter, estimatedColumnSize, rowHeightGetter, estimatedRowSize } = this.options; const { columnCount, items, rowCount, columnWidthGetter, estimatedColumnSize, rowHeightGetter, estimatedRowSize } = this.options;
this.rowCount = 0; this.rowCount = 0;
this.columnCount = 0; this.columnCount = 0;
if (BI.isNumber(columnCount)) { if (isNumber(columnCount)) {
this.columnCount = columnCount; this.columnCount = columnCount;
} else if (items.length > 0) { } else if (items.length > 0) {
this.columnCount = items[0].length; this.columnCount = items[0].length;
} }
if (BI.isNumber(rowCount)) { if (isNumber(rowCount)) {
this.rowCount = rowCount; this.rowCount = rowCount;
} else { } else {
this.rowCount = items.length; this.rowCount = items.length;
} }
this._columnSizeAndPositionManager = new BI.ScalingCellSizeAndPositionManager(this.columnCount, columnWidthGetter, estimatedColumnSize); this._columnSizeAndPositionManager = new ScalingCellSizeAndPositionManager(this.columnCount, columnWidthGetter, estimatedColumnSize);
this._rowSizeAndPositionManager = new BI.ScalingCellSizeAndPositionManager(this.rowCount, rowHeightGetter, estimatedRowSize); this._rowSizeAndPositionManager = new ScalingCellSizeAndPositionManager(this.rowCount, rowHeightGetter, estimatedRowSize);
} }
_getOverscanIndices(cellCount, overscanCellsCount, startIndex, stopIndex) { _getOverscanIndices(cellCount, overscanCellsCount, startIndex, stopIndex) {
@ -139,8 +139,8 @@ export default class GridView extends Widget {
const { itemFormatter, items } = this.options; const { itemFormatter, items } = this.options;
const width = o.width, height = o.height, scrollLeft = BI.clamp(o.scrollLeft, 0, this._getMaxScrollLeft()), const width = o.width, height = o.height, scrollLeft = clamp(o.scrollLeft, 0, this._getMaxScrollLeft()),
scrollTop = BI.clamp(o.scrollTop, 0, this._getMaxScrollTop()), scrollTop = clamp(o.scrollTop, 0, this._getMaxScrollTop()),
overscanColumnCount = o.overscanColumnCount, overscanRowCount = o.overscanRowCount; overscanColumnCount = o.overscanColumnCount, overscanRowCount = o.overscanRowCount;
if (height > 0 && width > 0) { if (height > 0 && width > 0) {
@ -150,7 +150,7 @@ export default class GridView extends Widget {
const renderedCells = [], renderedKeys = {}, renderedWidgets = {}; const renderedCells = [], renderedKeys = {}, renderedWidgets = {};
let minX = this._getMaxScrollLeft(), minY = this._getMaxScrollTop(), maxX = 0, maxY = 0; let minX = this._getMaxScrollLeft(), minY = this._getMaxScrollTop(), maxX = 0, maxY = 0;
// 没有可见的单元格就干掉所有渲染过的 // 没有可见的单元格就干掉所有渲染过的
if (!BI.isEmpty(visibleColumnIndices) && !BI.isEmpty(visibleRowIndices)) { if (!isEmpty(visibleColumnIndices) && !isEmpty(visibleRowIndices)) {
const horizontalOffsetAdjustment = this._columnSizeAndPositionManager.getOffsetAdjustment(width, scrollLeft); const horizontalOffsetAdjustment = this._columnSizeAndPositionManager.getOffsetAdjustment(width, scrollLeft);
const verticalOffsetAdjustment = this._rowSizeAndPositionManager.getOffsetAdjustment(height, scrollTop); const verticalOffsetAdjustment = this._rowSizeAndPositionManager.getOffsetAdjustment(height, scrollTop);
@ -187,7 +187,7 @@ export default class GridView extends Widget {
const rowDatum = this._rowSizeAndPositionManager.getSizeAndPositionOfCell(rowIndex); const rowDatum = this._rowSizeAndPositionManager.getSizeAndPositionOfCell(rowIndex);
for (let columnIndex = columnStartIndex; columnIndex <= columnStopIndex; columnIndex++) { for (let columnIndex = columnStartIndex; columnIndex <= columnStopIndex; columnIndex++) {
const key = rowIndex + "-" + columnIndex; const key = `${rowIndex}-${columnIndex}`;
const columnDatum = this._columnSizeAndPositionManager.getSizeAndPositionOfCell(columnIndex); const columnDatum = this._columnSizeAndPositionManager.getSizeAndPositionOfCell(columnIndex);
const index = this.renderedKeys[key] && this.renderedKeys[key][2]; const index = this.renderedKeys[key] && this.renderedKeys[key][2];
@ -196,18 +196,18 @@ export default class GridView extends Widget {
this.renderedCells[index].el.setWidth(columnDatum.size); this.renderedCells[index].el.setWidth(columnDatum.size);
this.renderedCells[index].el.setHeight(rowDatum.size); this.renderedCells[index].el.setHeight(rowDatum.size);
// 这里只使用px // 这里只使用px
this.renderedCells[index].el.element.css("left", columnDatum.offset + horizontalOffsetAdjustment + "px"); this.renderedCells[index].el.element.css("left", `${columnDatum.offset + horizontalOffsetAdjustment}px`);
this.renderedCells[index].el.element.css("top", rowDatum.offset + verticalOffsetAdjustment + "px"); this.renderedCells[index].el.element.css("top", `${rowDatum.offset + verticalOffsetAdjustment}px`);
child = this.renderedCells[index].el; child = this.renderedCells[index].el;
renderedCells.push(this.renderedCells[index]); renderedCells.push(this.renderedCells[index]);
} else { } else {
const item = itemFormatter(items[rowIndex][columnIndex], rowIndex, columnIndex); const item = itemFormatter(items[rowIndex][columnIndex], rowIndex, columnIndex);
child = BI._lazyCreateWidget(BI.extend({ child = _lazyCreateWidget(extend({
type: "bi.label", type: "bi.label",
width: columnDatum.size, width: columnDatum.size,
height: rowDatum.size, height: rowDatum.size,
}, item, { }, item, {
cls: (item.cls || "") + " grid-cell" + (rowIndex === 0 ? " first-row" : "") + (columnIndex === 0 ? " first-col" : ""), cls: `${item.cls || ""} grid-cell${rowIndex === 0 ? " first-row" : ""}${columnIndex === 0 ? " first-col" : ""}`,
_rowIndex: rowIndex, _rowIndex: rowIndex,
_columnIndex: columnIndex, _columnIndex: columnIndex,
_left: columnDatum.offset + horizontalOffsetAdjustment, _left: columnDatum.offset + horizontalOffsetAdjustment,
@ -215,8 +215,8 @@ export default class GridView extends Widget {
}), this); }), this);
renderedCells.push({ renderedCells.push({
el: child, el: child,
left: columnDatum.offset + horizontalOffsetAdjustment + "px", left: `${columnDatum.offset + horizontalOffsetAdjustment}px`,
top: rowDatum.offset + verticalOffsetAdjustment + "px", top: `${rowDatum.offset + verticalOffsetAdjustment}px`,
_left: columnDatum.offset + horizontalOffsetAdjustment, _left: columnDatum.offset + horizontalOffsetAdjustment,
_top: rowDatum.offset + verticalOffsetAdjustment, _top: rowDatum.offset + verticalOffsetAdjustment,
// _width: columnDatum.size, // _width: columnDatum.size,
@ -235,14 +235,14 @@ export default class GridView extends Widget {
} }
// 已存在的, 需要添加的和需要删除的 // 已存在的, 需要添加的和需要删除的
const existSet = {}, addSet = {}, deleteArray = []; const existSet = {}, addSet = {}, deleteArray = [];
BI.each(renderedKeys, (i, key) => { each(renderedKeys, (i, key) => {
if (this.renderedKeys[i]) { if (this.renderedKeys[i]) {
existSet[i] = key; existSet[i] = key;
} else { } else {
addSet[i] = key; addSet[i] = key;
} }
}); });
BI.each(this.renderedKeys, (i, key) => { each(this.renderedKeys, (i, key) => {
if (existSet[i]) { if (existSet[i]) {
return; return;
} }
@ -251,12 +251,12 @@ export default class GridView extends Widget {
} }
deleteArray.push(key[2]); deleteArray.push(key[2]);
}); });
BI.each(deleteArray, (i, index) => { each(deleteArray, (i, index) => {
// 性能优化,不调用destroy方法防止触发destroy事件 // 性能优化,不调用destroy方法防止触发destroy事件
this.renderedCells[index].el._destroy(); this.renderedCells[index].el._destroy();
}); });
const addedItems = []; const addedItems = [];
BI.each(addSet, (index, key) => { each(addSet, (index, key) => {
addedItems.push(renderedCells[key[2]]); addedItems.push(renderedCells[key[2]]);
}); });
// 与listview一样, 给上下文 // 与listview一样, 给上下文
@ -266,12 +266,12 @@ export default class GridView extends Widget {
this.container.attr("items", renderedCells); this.container.attr("items", renderedCells);
this.renderedCells = renderedCells; this.renderedCells = renderedCells;
this.renderedKeys = renderedKeys; this.renderedKeys = renderedKeys;
this.renderRange = { minX: minX, minY: minY, maxX: maxX, maxY: maxY }; this.renderRange = { minX, minY, maxX, maxY };
} }
} }
_isOverflowX() { _isOverflowX() {
const { scrollable, scrollx, overflowX } = this.options; const { scrollable, scrollx, overflowX } = this.options;
// 兼容一下 // 兼容一下
if (overflowX === false) { if (overflowX === false) {
return false; return false;
@ -282,6 +282,7 @@ export default class GridView extends Widget {
if (scrollable === true || scrollable === "xy" || scrollable === "x") { if (scrollable === true || scrollable === "xy" || scrollable === "x") {
return true; return true;
} }
return false; return false;
} }
@ -298,6 +299,7 @@ export default class GridView extends Widget {
if (scrollable === true || scrollable === "xy" || scrollable === "y") { if (scrollable === true || scrollable === "xy" || scrollable === "y") {
return true; return true;
} }
return false; return false;
} }
@ -342,7 +344,7 @@ export default class GridView extends Widget {
return; return;
} }
this._scrollLock = true; this._scrollLock = true;
this.options.scrollLeft = BI.clamp(scrollLeft || 0, 0, this._getMaxScrollLeft()); this.options.scrollLeft = clamp(scrollLeft || 0, 0, this._getMaxScrollLeft());
this._debounceRelease(); this._debounceRelease();
this.element.scrollLeft(this.options.scrollLeft); this.element.scrollLeft(this.options.scrollLeft);
this._calculateChildrenToRender(); this._calculateChildrenToRender();
@ -353,7 +355,7 @@ export default class GridView extends Widget {
return; return;
} }
this._scrollLock = true; this._scrollLock = true;
this.options.scrollTop = BI.clamp(scrollTop || 0, 0, this._getMaxScrollTop()); this.options.scrollTop = clamp(scrollTop || 0, 0, this._getMaxScrollTop());
this._debounceRelease(); this._debounceRelease();
this.element.scrollTop(this.options.scrollTop); this.element.scrollTop(this.options.scrollTop);
this._calculateChildrenToRender(); this._calculateChildrenToRender();
@ -370,7 +372,7 @@ export default class GridView extends Widget {
setOverflowX(b) { setOverflowX(b) {
if (this.options.overflowX !== !!b) { if (this.options.overflowX !== !!b) {
this.options.overflowX = !!b; this.options.overflowX = !!b;
BI.nextTick(() => { nextTick(() => {
this.element.css({ overflowX: b ? "auto" : "hidden" }); this.element.css({ overflowX: b ? "auto" : "hidden" });
}); });
} }
@ -379,7 +381,7 @@ export default class GridView extends Widget {
setOverflowY(b) { setOverflowY(b) {
if (this.options.overflowY !== !!b) { if (this.options.overflowY !== !!b) {
this.options.overflowY = !!b; this.options.overflowY = !!b;
BI.nextTick(() => { nextTick(() => {
this.element.css({ overflowY: b ? "auto" : "hidden" }); this.element.css({ overflowY: b ? "auto" : "hidden" });
}); });
} }
@ -418,7 +420,7 @@ export default class GridView extends Widget {
} }
restore() { restore() {
BI.each(this.renderedCells, (i, cell) => { each(this.renderedCells, (i, cell) => {
cell.el._destroy(); cell.el._destroy();
}); });
this._clearChildren(); this._clearChildren();

12
src/base/index.js

@ -2,11 +2,13 @@ import { Pane } from "./1.pane";
import * as single from "./single"; import * as single from "./single";
import * as layer from "./layer"; import * as layer from "./layer";
import * as list from "./list"; import * as list from "./list";
import GridView from "./grid/grid"; import { GridView } from "./grid/grid";
import Pager from "./pager/pager"; import { Pager } from "./pager/pager";
import * as combination from "./combination"; import * as combination from "./combination";
import { Msg } from "./foundation/message"; import { Msg } from "./foundation/message";
import * as base from "./0.base"; import * as base from "./0.base";
import { CollectionView } from "./collection/collection";
import { CustomTree } from "./tree/customtree";
Object.assign(BI, { Object.assign(BI, {
Pane, Pane,
@ -18,6 +20,8 @@ Object.assign(BI, {
...combination, ...combination,
Msg, Msg,
...base, ...base,
CollectionView,
CustomTree,
}); });
export * from "./0.base"; export * from "./0.base";
@ -30,4 +34,6 @@ export {
GridView, GridView,
Pager, Pager,
Msg, Msg,
} CollectionView,
CustomTree
};

2
src/base/layer/index.js

@ -1,4 +1,4 @@
export { Drawer } from "./layer.drawer"; export { Drawer } from "./layer.drawer";
export { Popover, BarPopover } from "./layer.popover"; export { Popover, BarPopover } from "./layer.popover";
export { PopupView } from "./layer.popup"; export { PopupView } from "./layer.popup";
export { SearcherView } from "./layer.searcher"; export { SearcherView } from "./layer.searcher";

361
src/base/layer/layer.drawer.js

@ -4,13 +4,13 @@
* @extends BI.Widget * @extends BI.Widget
*/ */
import { Widget, shortcut } from "../../core"; import { Widget, shortcut, isPlainObject, extend } from "../../core";
@shortcut() @shortcut()
export class Drawer extends Widget { export class Drawer extends Widget {
SIZE = { SIZE = {
SMALL: "small", SMALL: "small",
NORMAL: "normal", NORMAL: "normal",
BIG: "big", BIG: "big",
} }
props = { props = {
baseCls: "bi-drawer bi-card", baseCls: "bi-drawer bi-card",
@ -28,202 +28,202 @@ export class Drawer extends Widget {
static EVENT_CLOSE = "EVENT_CLOSE"; static EVENT_CLOSE = "EVENT_CLOSE";
static EVENT_OPEN = "EVENT_OPEN"; static EVENT_OPEN = "EVENT_OPEN";
_getSuitableSize() { _getSuitableSize() {
const { size, height, placement, width } = this.options; const { size, height, placement, width } = this.options;
let sizeValue = 0; let sizeValue = 0;
switch (size) { switch (size) {
case "big": case "big":
sizeValue = 736; sizeValue = 736;
break; break;
case "small": case "small":
sizeValue = 200; sizeValue = 200;
break; break;
case "normal": case "normal":
default: default:
sizeValue = 378; sizeValue = 378;
break; break;
} }
if (placement === "top" || placement === "bottom") { if (placement === "top" || placement === "bottom") {
return { return {
height: height || sizeValue, height: height || sizeValue,
}; };
} }
if (placement === "left" || placement === "right") { if (placement === "left" || placement === "right") {
return { return {
width: width || sizeValue, width: width || sizeValue,
}; };
} }
} }
render() { render() {
const { header, headerHeight, closable, body, bodyHgap, bodyTgap, bodyBgap } = this.options; const { header, headerHeight, closable, body, bodyHgap, bodyTgap, bodyBgap } = this.options;
const items = [{ const items = [{
el: { el: {
type: "bi.htape", type: "bi.htape",
cls: "bi-message-title bi-header-background", cls: "bi-message-title bi-header-background",
items: [{ items: [{
type: "bi.absolute", type: "bi.absolute",
items: [{ items: [{
el: BI.isPlainObject(header) ? BI.extend({}, header, { el: isPlainObject(header) ? extend({}, header, {
extraCls: "bi-font-bold", extraCls: "bi-font-bold",
}) : { }) : {
type: "bi.label", type: "bi.label",
cls: "bi-font-bold", cls: "bi-font-bold",
height: headerHeight, height: headerHeight,
text: header, text: header,
title: header, title: header,
textAlign: "left", textAlign: "left",
}, },
left: 20, left: 20,
top: 0, top: 0,
right: 0, right: 0,
bottom: 0, bottom: 0,
}], }],
}, { }, {
el: closable ? { el: closable ? {
type: "bi.icon_button", type: "bi.icon_button",
cls: "bi-message-close close-font", cls: "bi-message-close close-font",
height: headerHeight, height: headerHeight,
handler: () => { handler: () => {
this.close(); this.close();
}, },
} : { } : {
type: "bi.layout", type: "bi.layout",
}, },
width: 56, width: 56,
}], }],
height: headerHeight, height: headerHeight,
}, },
height: headerHeight, height: headerHeight,
}, { }, {
el: { el: {
type: "bi.vertical", type: "bi.vertical",
scrolly: true, scrolly: true,
cls: "drawer-body", cls: "drawer-body",
ref: (_ref) => { ref: _ref => {
this.body = _ref; this.body = _ref;
}, },
items: [{ items: [{
el: body, el: body,
}], }],
}, },
hgap: bodyHgap, hgap: bodyHgap,
tgap: bodyTgap, tgap: bodyTgap,
bgap: bodyBgap, bgap: bodyBgap,
}]; }];
return BI.extend({ return extend({
type: "bi.vtape", type: "bi.vtape",
items: items, items,
}, this._getSuitableSize()); }, this._getSuitableSize());
} }
mounted() { mounted() {
const { placement } = this.options; const { placement } = this.options;
switch (placement) { switch (placement) {
case "right": case "right":
this.element.css({ this.element.css({
top: 0, top: 0,
left: "100%", left: "100%",
bottom: 0, bottom: 0,
}); });
break; break;
case "left": case "left":
this.element.css({ this.element.css({
top: 0, top: 0,
right: "100%", right: "100%",
bottom: 0, bottom: 0,
}); });
break; break;
case "top": case "top":
this.element.css({ this.element.css({
left: 0, left: 0,
right: 0, right: 0,
bottom: "100%", bottom: "100%",
}); });
break; break;
case "bottom": case "bottom":
this.element.css({ this.element.css({
left: 0, left: 0,
right: 0, right: 0,
top: "100%", top: "100%",
}); });
break; break;
default: default:
break; break;
} }
} }
show(callback) { show(callback) {
const { placement } = this.options; const { placement } = this.options;
requestAnimationFrame(() => { requestAnimationFrame(() => {
const size = this._getSuitableSize(); const size = this._getSuitableSize();
switch (placement) { switch (placement) {
case "right": case "right":
this.element.css({ this.element.css({
left: "calc(100% - " + size.width + "px)", left: `calc(100% - ${size.width}px)`,
}); });
break; break;
case "left": case "left":
this.element.css({ this.element.css({
right: "calc(100% - " + size.width + "px)", right: `calc(100% - ${size.width}px)`,
}); });
break; break;
case "top": case "top":
this.element.css({ this.element.css({
bottom: "calc(100% - " + size.height + "px)", bottom: `calc(100% - ${size.height}px)`,
}); });
break; break;
case "bottom": case "bottom":
this.element.css({ this.element.css({
top: "calc(100% - " + size.height + "px)", top: `calc(100% - ${size.height}px)`,
}); });
break; break;
default: default:
break; break;
} }
callback && callback(); callback && callback();
}); });
} }
hide(callback) { hide(callback) {
const { placement } = this.options; const { placement } = this.options;
requestAnimationFrame(() => { requestAnimationFrame(() => {
switch (placement) { switch (placement) {
case "right": case "right":
this.element.css({ this.element.css({
left: "100%", left: "100%",
}); });
break; break;
case "left": case "left":
this.element.css({ this.element.css({
right: "100%", right: "100%",
}); });
break; break;
case "top": case "top":
this.element.css({ this.element.css({
bottom: "100%", bottom: "100%",
}); });
break; break;
case "bottom": case "bottom":
this.element.css({ this.element.css({
top: "100%", top: "100%",
}); });
break; break;
default: default:
break; break;
} }
setTimeout(callback, 300); setTimeout(callback, 300);
}); });
} }
open() { open() {
this.show(() => { this.show(() => {
this.fireEvent(Drawer.EVENT_OPEN); this.fireEvent(Drawer.EVENT_OPEN);
}); });
} }
close() { close() {
this.hide(() => { this.hide(() => {
this.fireEvent(Drawer.EVENT_CLOSE); this.fireEvent(Drawer.EVENT_CLOSE);
}); });
} }
setZindex(zindex) { setZindex(zindex) {
@ -232,6 +232,5 @@ export class Drawer extends Widget {
destroyed() { destroyed() {
} }
} }

358
src/base/layer/layer.popover.js

@ -4,7 +4,7 @@
* @extends BI.Widget * @extends BI.Widget
*/ */
import { Widget, shortcut } from "../../core"; import { Widget, shortcut, clamp, isPlainObject, extend, isNotNull } from "../../core";
@shortcut() @shortcut()
export class Popover extends Widget { export class Popover extends Widget {
_constant = { _constant = {
@ -41,182 +41,182 @@ export class Popover extends Widget {
static EVENT_CONFIRM = "EVENT_CONFIRM"; static EVENT_CONFIRM = "EVENT_CONFIRM";
render() { render() {
// var self = this; // var self = this;
const { header, headerHeight, closable, logic, footer, footerHeight, body, bodyTgap, bodyHgap } = this.options; const { header, headerHeight, closable, logic, footer, footerHeight, body, bodyTgap, bodyHgap } = this.options;
const c = this._constant; const c = this._constant;
this.startX = 0; this.startX = 0;
this.startY = 0; this.startY = 0;
const size = this._calculateSize(); const size = this._calculateSize();
this.tracker = new BI.MouseMoveTracker((deltaX, deltaY) => { this.tracker = new BI.MouseMoveTracker((deltaX, deltaY) => {
const W = BI.Widget._renderEngine.createElement("body").width(); const W = Widget._renderEngine.createElement("body").width();
const H = BI.Widget._renderEngine.createElement("body").height(); const H = Widget._renderEngine.createElement("body").height();
this.startX += deltaX; this.startX += deltaX;
this.startY += deltaY; this.startY += deltaY;
this.element.css({ this.element.css({
left: BI.clamp(this.startX, 0, W - this.element.width()) + "px", left: `${clamp(this.startX, 0, W - this.element.width())}px`,
top: BI.clamp(this.startY, 0, H - this.element.height()) + "px", top: `${clamp(this.startY, 0, H - this.element.height())}px`,
}); });
// BI-12134 没有什么特别好的方法 // BI-12134 没有什么特别好的方法
BI.Resizers._resize({ BI.Resizers._resize({
target: this.element[0], target: this.element[0],
}); });
}, () => { }, () => {
this.tracker.releaseMouseMoves(); this.tracker.releaseMouseMoves();
}, _global); }, _global);
const items = [{ const items = [{
el: { el: {
type: "bi.htape", type: "bi.htape",
cls: "bi-message-title bi-header-background", cls: "bi-message-title bi-header-background",
items: [{ items: [{
el: { el: {
type: "bi.absolute", type: "bi.absolute",
ref: (_ref) => { ref: _ref => {
this.dragger = _ref; this.dragger = _ref;
}, },
items: [{ items: [{
el: BI.isPlainObject(header) ? BI.extend({}, header, { el: isPlainObject(header) ? extend({}, header, {
extraCls: "bi-font-bold", extraCls: "bi-font-bold",
}) : { }) : {
type: "bi.label", type: "bi.label",
cls: "bi-font-bold", cls: "bi-font-bold",
height: headerHeight, height: headerHeight,
text: header, text: header,
title: header, title: header,
textAlign: "left", textAlign: "left",
}, },
top: 0, top: 0,
bottom: 0, bottom: 0,
left: BI.SIZE_CONSANTS.H_GAP_SIZE, left: BI.SIZE_CONSANTS.H_GAP_SIZE,
right: closable ? 0 : BI.SIZE_CONSANTS.H_GAP_SIZE, right: closable ? 0 : BI.SIZE_CONSANTS.H_GAP_SIZE,
}], }],
}, },
}, closable ? { }, closable ? {
el: { el: {
type: "bi.icon_button", type: "bi.icon_button",
cls: "bi-message-close close-font", cls: "bi-message-close close-font",
height: headerHeight, height: headerHeight,
handler: () => { handler: () => {
this.close(); this.close();
}, },
}, },
width: 56, width: 56,
} : null], } : null],
height: headerHeight, height: headerHeight,
}, },
height: headerHeight, height: headerHeight,
}, logic.dynamic ? { }, logic.dynamic ? {
el: { el: {
type: "bi.vertical", type: "bi.vertical",
scrolly: true, scrolly: true,
cls: "popover-body", cls: "popover-body",
ref: (_ref) => { ref: _ref => {
this.body = _ref; this.body = _ref;
}, },
css: { css: {
"max-height": this._getSuitableBodyHeight(c.MAX_HEIGHT - headerHeight - (footer ? footerHeight : 0) - bodyTgap), "max-height": this._getSuitableBodyHeight(c.MAX_HEIGHT - headerHeight - (footer ? footerHeight : 0) - bodyTgap),
"min-height": this._getSuitableBodyHeight(size.height - headerHeight - (footer ? footerHeight : 0) - bodyTgap), "min-height": this._getSuitableBodyHeight(size.height - headerHeight - (footer ? footerHeight : 0) - bodyTgap),
}, },
items: [{ items: [{
el: body, el: body,
}], }],
hgap: bodyHgap, hgap: bodyHgap,
tgap: bodyTgap, tgap: bodyTgap,
}, },
} : { } : {
el: { el: {
type: "bi.absolute", type: "bi.absolute",
items: [{ items: [{
el: body, el: body,
left: bodyHgap, left: bodyHgap,
top: bodyTgap, top: bodyTgap,
right: bodyHgap, right: bodyHgap,
bottom: 0, bottom: 0,
}], }],
}, },
}]; }];
if (footer) { if (footer) {
items.push({ items.push({
el: { el: {
type: "bi.absolute", type: "bi.absolute",
items: [{ items: [{
el: footer, el: footer,
left: BI.SIZE_CONSANTS.H_GAP_SIZE, left: BI.SIZE_CONSANTS.H_GAP_SIZE,
top: 0, top: 0,
right: BI.SIZE_CONSANTS.H_GAP_SIZE, right: BI.SIZE_CONSANTS.H_GAP_SIZE,
bottom: 0, bottom: 0,
}], }],
height: footerHeight, height: footerHeight,
}, },
height: footerHeight, height: footerHeight,
}); });
} }
return BI.extend({ return extend({
items: items, items,
width: this._getSuitableWidth(size.width), width: this._getSuitableWidth(size.width),
}, logic.dynamic ? { }, logic.dynamic ? {
type: "bi.vertical", type: "bi.vertical",
scrolly: false, scrolly: false,
} : { } : {
type: "bi.vtape", type: "bi.vtape",
height: this._getSuitableHeight(size.height), height: this._getSuitableHeight(size.height),
}); });
} }
// mounted之后绑定事件 // mounted之后绑定事件
mounted() { mounted() {
this.dragger.element.mousedown((e) => { this.dragger.element.mousedown(e => {
if (this.options.draggable !== false) { if (this.options.draggable !== false) {
this.startX = this.element[0].offsetLeft; this.startX = this.element[0].offsetLeft;
this.startY = this.element[0].offsetTop; this.startY = this.element[0].offsetTop;
this.tracker.captureMouseMoves(e); this.tracker.captureMouseMoves(e);
} }
}); });
} }
_getSuitableBodyHeight(height) { _getSuitableBodyHeight(height) {
const { headerHeight, footer, footerHeight, bodyTgap } = this.options; const { headerHeight, footer, footerHeight, bodyTgap } = this.options;
return BI.clamp(height, 0, BI.Widget._renderEngine.createElement("body")[0].clientHeight - headerHeight - (footer ? footerHeight : 0) - bodyTgap); return clamp(height, 0, Widget._renderEngine.createElement("body")[0].clientHeight - headerHeight - (footer ? footerHeight : 0) - bodyTgap);
} }
_getSuitableHeight(height) { _getSuitableHeight(height) {
return BI.clamp(height, 0, BI.Widget._renderEngine.createElement("body")[0].clientHeight); return clamp(height, 0, Widget._renderEngine.createElement("body")[0].clientHeight);
} }
_getSuitableWidth(width) { _getSuitableWidth(width) {
return BI.clamp(width, 0, BI.Widget._renderEngine.createElement("body").width()); return clamp(width, 0, Widget._renderEngine.createElement("body").width());
} }
_calculateSize() { _calculateSize() {
const { size, width, height } = this.options; const { size, width, height } = this.options;
const sizeValue = {}; const sizeValue = {};
if (BI.isNotNull(size)) { if (isNotNull(size)) {
switch (size) { switch (size) {
case this._constant.SIZE.SMALL: case this._constant.SIZE.SMALL:
sizeValue.width = 450; sizeValue.width = 450;
sizeValue.height = 200; sizeValue.height = 200;
sizeValue.type = "small"; sizeValue.type = "small";
break; break;
case this._constant.SIZE.BIG: case this._constant.SIZE.BIG:
sizeValue.width = 900; sizeValue.width = 900;
sizeValue.height = 500; sizeValue.height = 500;
sizeValue.type = "big"; sizeValue.type = "big";
break; break;
default: default:
sizeValue.width = 550; sizeValue.width = 550;
sizeValue.height = 500; sizeValue.height = 500;
sizeValue.type = "default"; sizeValue.type = "default";
} }
} }
return { return {
width: width || sizeValue.width, width: width || sizeValue.width,
height: height || sizeValue.height, height: height || sizeValue.height,
type: sizeValue.type || "default", type: sizeValue.type || "default",
}; };
} }
setDraggable(b) { setDraggable(b) {
this.options.draggable = b; this.options.draggable = b;
} }
hide() { hide() {
@ -224,13 +224,13 @@ export class Popover extends Widget {
} }
open() { open() {
this.show(); this.show();
this.fireEvent(Popover.EVENT_OPEN, arguments); this.fireEvent(Popover.EVENT_OPEN, arguments);
} }
close() { close() {
this.hide(); this.hide();
this.fireEvent(Popover.EVENT_CLOSE, arguments); this.fireEvent(Popover.EVENT_CLOSE, arguments);
} }
setZindex(zindex) { setZindex(zindex) {
@ -243,36 +243,36 @@ export class BarPopover extends Popover {
static xtype = "bi.bar_popover"; static xtype = "bi.bar_popover";
_defaultConfig() { _defaultConfig() {
return BI.extend(super._defaultConfig(arguments), { return extend(super._defaultConfig(arguments), {
btns: [BI.i18nText("BI-Basic_OK"), BI.i18nText("BI-Basic_Cancel")], btns: [BI.i18nText("BI-Basic_OK"), BI.i18nText("BI-Basic_Cancel")],
}); });
} }
beforeCreate() { beforeCreate() {
const { footer, warningTitle } = this.options; const { footer, warningTitle } = this.options;
footer || (this.options.footer = { footer || (this.options.footer = {
type: "bi.right_vertical_adapt", type: "bi.right_vertical_adapt",
lgap: 10, lgap: 10,
items: [{ items: [{
type: "bi.button", type: "bi.button",
text: this.options.btns[1], text: this.options.btns[1],
value: 1, value: 1,
level: "ignore", level: "ignore",
handler: (v) => { handler: v => {
this.fireEvent(Popover.EVENT_CANCEL, v); this.fireEvent(Popover.EVENT_CANCEL, v);
this.close(v); this.close(v);
}, },
}, { }, {
type: "bi.button", type: "bi.button",
text: this.options.btns[0], text: this.options.btns[0],
warningTitle: warningTitle, warningTitle,
value: 0, value: 0,
handler: (v) => { handler: v => {
this.fireEvent(Popover.EVENT_CONFIRM, v); this.fireEvent(Popover.EVENT_CONFIRM, v);
this.close(v); this.close(v);
}, },
}], }],
}); });
} }
} }

639
src/base/layer/layer.popup.js

@ -4,19 +4,19 @@
* @extends BI.Widget * @extends BI.Widget
*/ */
import { Widget, shortcut } from "../../core"; import { Widget, shortcut, extend, Controller, createWidget, createItems, clamp } from "../../core";
@shortcut() @shortcut()
export class PopupView extends Widget { export class PopupView extends Widget {
_const = { _const = {
TRIANGLE_LENGTH: 12, TRIANGLE_LENGTH: 12,
} }
static xtype = "bi.popup_view"; static xtype = "bi.popup_view";
static EVENT_CHANGE = "EVENT_CHANGE"; static EVENT_CHANGE = "EVENT_CHANGE";
_defaultConfig(props) { _defaultConfig(props) {
return BI.extend(super._defaultConfig(arguments), { return extend(super._defaultConfig(arguments), {
_baseCls: "bi-popup-view" + (props.primary ? " bi-primary" : ""), _baseCls: `bi-popup-view${props.primary ? " bi-primary" : ""}`,
// 品牌色 // 品牌色
primary: false, primary: false,
maxWidth: "auto", maxWidth: "auto",
@ -55,100 +55,100 @@ export class PopupView extends Widget {
}); });
} }
render() { render() {
const { minWidth, maxWidth, stopPropagation, stopEvent, const { minWidth, maxWidth, stopPropagation, stopEvent,
direction, logic, lgap, rgap, tgap, bgap, vgap, hgap, primary, showArrow } = this.options; direction, logic, lgap, rgap, tgap, bgap, vgap, hgap, primary, showArrow } = this.options;
function fn (e) { function fn (e) {
e.stopPropagation(); e.stopPropagation();
} }
function stop (e) { function stop (e) {
e.stopEvent(); e.stopEvent();
return false; return false;
} }
this.element.css({ this.element.css({
"z-index": BI.zIndex_popup, "z-index": BI.zIndex_popup,
"min-width": BI.pixFormat(minWidth), "min-width": BI.pixFormat(minWidth),
"max-width": BI.pixFormat(maxWidth), "max-width": BI.pixFormat(maxWidth),
}).bind({ click: fn }); }).bind({ click: fn });
this.element.bind("mousewheel", fn); this.element.bind("mousewheel", fn);
stopPropagation && this.element.bind({ mousedown: fn, mouseup: fn, mouseover: fn }); stopPropagation && this.element.bind({ mousedown: fn, mouseup: fn, mouseover: fn });
stopEvent && this.element.bind({ mousedown: stop, mouseup: stop, mouseover: stop }); stopEvent && this.element.bind({ mousedown: stop, mouseup: stop, mouseover: stop });
this.tool = this._createTool(); this.tool = this._createTool();
this.tab = this._createTab(); this.tab = this._createTab();
this.view = this._createView(); this.view = this._createView();
this.toolbar = this._createToolBar(); this.toolbar = this._createToolBar();
this.view.on(BI.Controller.EVENT_CHANGE, (type, ...args) => { this.view.on(Controller.EVENT_CHANGE, (type, ...args) => {
this.fireEvent.apply(this, [BI.Controller.EVENT_CHANGE, type, ...args]); this.fireEvent(Controller.EVENT_CHANGE, type, ...args);
if (type === BI.Events.CLICK) { if (type === BI.Events.CLICK) {
this.fireEvent(PopupView.EVENT_CHANGE); this.fireEvent(PopupView.EVENT_CHANGE);
} }
}); });
BI.createWidget(BI.extend({ createWidget(extend({
element: this, element: this,
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(direction), BI.extend({}, logic, { }, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(direction), extend({}, logic, {
scrolly: false, scrolly: false,
lgap, lgap,
rgap, rgap,
tgap, tgap,
bgap, bgap,
vgap, vgap,
hgap, hgap,
items: BI.LogicFactory.createLogicItemsByDirection(direction, BI.extend({ items: BI.LogicFactory.createLogicItemsByDirection(direction, extend({
cls: "list-view-outer bi-card list-view-shadow" + (primary ? " bi-primary" : ""), cls: `list-view-outer bi-card list-view-shadow${primary ? " bi-primary" : ""}`,
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(direction), BI.extend({}, logic, { }, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(direction), extend({}, logic, {
items: BI.LogicFactory.createLogicItemsByDirection(direction, this.tool, this.tab, this.view, this.toolbar), items: BI.LogicFactory.createLogicItemsByDirection(direction, this.tool, this.tab, this.view, this.toolbar),
}))) })))
), ),
})))); }))));
if (showArrow) { if (showArrow) {
this.arrow = BI.createWidget({ this.arrow = createWidget({
type: "bi.absolute", type: "bi.absolute",
cls: "bi-bubble-arrow", cls: "bi-bubble-arrow",
items: [{ items: [{
type: "bi.layout", type: "bi.layout",
cls: "bubble-arrow", cls: "bubble-arrow",
}], }],
}); });
this.arrowWrapper = BI.createWidget({ this.arrowWrapper = createWidget({
type: "bi.absolute", type: "bi.absolute",
cls: "bi-bubble-arrow-wrapper", cls: "bi-bubble-arrow-wrapper",
items: [{ items: [{
el: this.arrow, el: this.arrow,
}], }],
}); });
// 因为三角符号的原因位置变大了,需要占位 // 因为三角符号的原因位置变大了,需要占位
this.placeholder = BI.createWidget({ this.placeholder = createWidget({
type: "bi.layout", type: "bi.layout",
}); });
BI.createWidget({ createWidget({
type: "bi.absolute", type: "bi.absolute",
element: this, element: this,
items: [{ items: [{
el: this.arrowWrapper, el: this.arrowWrapper,
left: 0, left: 0,
top: 0, top: 0,
}, { }, {
el: this.placeholder, el: this.placeholder,
}], }],
}); });
} }
} }
_createView() { _createView() {
const { el, value, minHeight, innerVgap, innerHgap } = this.options; const { el, value, minHeight, innerVgap, innerHgap } = this.options;
this.button_group = BI.createWidget(el, { type: "bi.button_group", value: value }); this.button_group = createWidget(el, { type: "bi.button_group", value });
this.button_group.element.css({ this.button_group.element.css({
"min-height": BI.pixFormat(minHeight), "min-height": BI.pixFormat(minHeight),
"padding-top": BI.pixFormat(innerVgap), "padding-top": BI.pixFormat(innerVgap),
"padding-bottom": BI.pixFormat(innerVgap), "padding-bottom": BI.pixFormat(innerVgap),
"padding-left": BI.pixFormat(innerHgap), "padding-left": BI.pixFormat(innerHgap),
"padding-right": BI.pixFormat(innerHgap), "padding-right": BI.pixFormat(innerHgap),
}); });
return this.button_group; return this.button_group;
} }
_createTool() { _createTool() {
@ -157,7 +157,7 @@ export class PopupView extends Widget {
return; return;
} }
return BI.createWidget(tool); return createWidget(tool);
} }
_createTab() { _createTab() {
@ -166,268 +166,267 @@ export class PopupView extends Widget {
return; return;
} }
return BI.createWidget({ return createWidget({
type: "bi.center", type: "bi.center",
cls: "list-view-tab", cls: "list-view-tab",
height: 25, height: 25,
items: tabs, items: tabs,
value: value, value,
}); });
} }
_createToolBar() { _createToolBar() {
const { buttons } = this.options; const { buttons } = this.options;
if (buttons.length === 0) { if (buttons.length === 0) {
return; return;
} }
return BI.createWidget({ return createWidget({
type: "bi.center", type: "bi.center",
cls: "list-view-toolbar bi-high-light bi-split-top", cls: "list-view-toolbar bi-high-light bi-split-top",
height: 24, height: 24,
items: BI.createItems(buttons, { items: createItems(buttons, {
once: false, once: false,
shadow: true, shadow: true,
isShadowShowingOnSelected: true, isShadowShowingOnSelected: true,
}), }),
}); });
} }
setDirection(direction, position) { setDirection(direction, position) {
const { showArrow, tgap, vgap, bgap, rgap, hgap, lgap } = this.options; const { showArrow, tgap, vgap, bgap, rgap, hgap, lgap } = this.options;
if (showArrow) { if (showArrow) {
let style = {}, wrapperStyle = {}, placeholderStyle = {}; let style = {}, wrapperStyle = {}, placeholderStyle = {};
const adjustXOffset = position.adjustXOffset || 0; const adjustXOffset = position.adjustXOffset || 0;
const adjustYOffset = position.adjustYOffset || 0; const adjustYOffset = position.adjustYOffset || 0;
const bodyBounds = BI.Widget._renderEngine.createElement("body").bounds(); const bodyBounds = Widget._renderEngine.createElement("body").bounds();
const bodyWidth = bodyBounds.width; const bodyWidth = bodyBounds.width;
const bodyHeight = bodyBounds.height; const bodyHeight = bodyBounds.height;
const popupWidth = this.element.outerWidth(); const popupWidth = this.element.outerWidth();
const popupHeight = this.element.outerHeight(); const popupHeight = this.element.outerHeight();
const offset = position.offset; const offset = position.offset;
const offsetStyle = position.offsetStyle; const offsetStyle = position.offsetStyle;
const middle = offsetStyle === "center" || offsetStyle === "middle"; const middle = offsetStyle === "center" || offsetStyle === "middle";
const minLeft = Math.max(4, offset.left + 4 + popupWidth - bodyWidth); const minLeft = Math.max(4, offset.left + 4 + popupWidth - bodyWidth);
const minRight = Math.max(4, popupWidth - (offset.left + 4)); const minRight = Math.max(4, popupWidth - (offset.left + 4));
const minTop = Math.max(4, offset.top + 4 + popupHeight - bodyHeight); const minTop = Math.max(4, offset.top + 4 + popupHeight - bodyHeight);
const minBottom = Math.max(4, popupHeight - (offset.top + 4)); const minBottom = Math.max(4, popupHeight - (offset.top + 4));
const maxLeft = Math.min(popupWidth - 16 - 4, offset.left + position.width - 16 - 4); const maxLeft = Math.min(popupWidth - 16 - 4, offset.left + position.width - 16 - 4);
const maxRight = Math.min(popupWidth - 16 - 4, bodyWidth - (offset.left + position.width - 16 - 4)); const maxRight = Math.min(popupWidth - 16 - 4, bodyWidth - (offset.left + position.width - 16 - 4));
const maxTop = Math.min(popupHeight - 16 - 4, offset.top + position.height - 16 - 4); const maxTop = Math.min(popupHeight - 16 - 4, offset.top + position.height - 16 - 4);
const maxBottom = Math.min(popupHeight - 16 - 4, bodyHeight - (offset.top + position.height - 16 - 4)); const maxBottom = Math.min(popupHeight - 16 - 4, bodyHeight - (offset.top + position.height - 16 - 4));
switch (direction) { switch (direction) {
case "bottom": case "bottom":
case "bottom,right": case "bottom,right":
direction = "bottom"; direction = "bottom";
style = { style = {
// 5表示留出一定的空间 // 5表示留出一定的空间
left: BI.clamp(((middle ? popupWidth : position.width) - adjustXOffset) / 2 - 8, minLeft, maxLeft), left: clamp(((middle ? popupWidth : position.width) - adjustXOffset) / 2 - 8, minLeft, maxLeft),
}; };
wrapperStyle = { wrapperStyle = {
top: tgap + vgap, top: tgap + vgap,
left: 0, left: 0,
right: "", right: "",
bottom: "", bottom: "",
}; };
placeholderStyle = { placeholderStyle = {
left: 0, left: 0,
right: 0, right: 0,
height: this._const.TRIANGLE_LENGTH, height: this._const.TRIANGLE_LENGTH,
top: -this._const.TRIANGLE_LENGTH, top: -this._const.TRIANGLE_LENGTH,
bottom: "", bottom: "",
}; };
break; break;
case "bottom,left": case "bottom,left":
direction = "bottom"; direction = "bottom";
style = { style = {
right: BI.clamp(((middle ? popupWidth : position.width) + adjustXOffset) / 2 - 8, minRight, maxRight), right: clamp(((middle ? popupWidth : position.width) + adjustXOffset) / 2 - 8, minRight, maxRight),
}; };
wrapperStyle = { wrapperStyle = {
top: bgap + vgap, top: bgap + vgap,
left: "", left: "",
right: 0, right: 0,
bottom: "", bottom: "",
}; };
placeholderStyle = { placeholderStyle = {
left: 0, left: 0,
right: 0, right: 0,
height: this._const.TRIANGLE_LENGTH, height: this._const.TRIANGLE_LENGTH,
top: -this._const.TRIANGLE_LENGTH, top: -this._const.TRIANGLE_LENGTH,
bottom: "", bottom: "",
}; };
break; break;
case "top": case "top":
case "top,right": case "top,right":
direction = "top"; direction = "top";
style = { style = {
left: BI.clamp(((middle ? popupWidth : position.width) - adjustXOffset) / 2 - 8, minLeft, maxLeft), left: clamp(((middle ? popupWidth : position.width) - adjustXOffset) / 2 - 8, minLeft, maxLeft),
}; };
wrapperStyle = { wrapperStyle = {
bottom: bgap + vgap, bottom: bgap + vgap,
left: 0, left: 0,
right: "", right: "",
top: "", top: "",
}; };
placeholderStyle = { placeholderStyle = {
left: 0, left: 0,
right: 0, right: 0,
height: this._const.TRIANGLE_LENGTH, height: this._const.TRIANGLE_LENGTH,
top: "", top: "",
bottom: -this._const.TRIANGLE_LENGTH, bottom: -this._const.TRIANGLE_LENGTH,
}; };
break; break;
case "top,left": case "top,left":
direction = "top"; direction = "top";
style = { style = {
right: BI.clamp(((middle ? popupWidth : position.width) + adjustXOffset) / 2 - 8, minRight, maxRight), right: clamp(((middle ? popupWidth : position.width) + adjustXOffset) / 2 - 8, minRight, maxRight),
}; };
wrapperStyle = { wrapperStyle = {
bottom: bgap + vgap, bottom: bgap + vgap,
right: 0, right: 0,
left: "", left: "",
top: "", top: "",
}; };
placeholderStyle = { placeholderStyle = {
left: 0, left: 0,
right: 0, right: 0,
height: this._const.TRIANGLE_LENGTH, height: this._const.TRIANGLE_LENGTH,
top: "", top: "",
bottom: -this._const.TRIANGLE_LENGTH, bottom: -this._const.TRIANGLE_LENGTH,
}; };
break; break;
case "left": case "left":
case "left,bottom": case "left,bottom":
direction = "left"; direction = "left";
style = { style = {
top: BI.clamp(((middle ? popupHeight : position.height) - adjustYOffset) / 2 - 8, minTop, maxTop), top: clamp(((middle ? popupHeight : position.height) - adjustYOffset) / 2 - 8, minTop, maxTop),
}; };
wrapperStyle = { wrapperStyle = {
right: rgap + hgap, right: rgap + hgap,
top: 0, top: 0,
bottom: "", bottom: "",
left: "", left: "",
}; };
placeholderStyle = { placeholderStyle = {
top: 0, top: 0,
bottom: 0, bottom: 0,
width: this._const.TRIANGLE_LENGTH, width: this._const.TRIANGLE_LENGTH,
right: -this._const.TRIANGLE_LENGTH, right: -this._const.TRIANGLE_LENGTH,
left: "", left: "",
}; };
break; break;
case "left,top": case "left,top":
direction = "left"; direction = "left";
style = { style = {
bottom: BI.clamp(((middle ? popupHeight : position.height) + adjustYOffset) / 2 - 8, minBottom, maxBottom), bottom: clamp(((middle ? popupHeight : position.height) + adjustYOffset) / 2 - 8, minBottom, maxBottom),
}; };
wrapperStyle = { wrapperStyle = {
right: rgap + hgap, right: rgap + hgap,
bottom: 0, bottom: 0,
top: "", top: "",
left: "", left: "",
}; };
placeholderStyle = { placeholderStyle = {
top: 0, top: 0,
bottom: 0, bottom: 0,
width: this._const.TRIANGLE_LENGTH, width: this._const.TRIANGLE_LENGTH,
right: -this._const.TRIANGLE_LENGTH, right: -this._const.TRIANGLE_LENGTH,
left: "", left: "",
}; };
break; break;
case "right": case "right":
case "right,bottom": case "right,bottom":
direction = "right"; direction = "right";
style = { style = {
top: BI.clamp(((middle ? popupHeight : position.height) - adjustYOffset) / 2 - 8, minTop, maxTop), top: clamp(((middle ? popupHeight : position.height) - adjustYOffset) / 2 - 8, minTop, maxTop),
}; };
wrapperStyle = { wrapperStyle = {
left: lgap + hgap, left: lgap + hgap,
top: 0, top: 0,
bottom: "", bottom: "",
right: "", right: "",
}; };
placeholderStyle = { placeholderStyle = {
top: 0, top: 0,
bottom: 0, bottom: 0,
width: this._const.TRIANGLE_LENGTH, width: this._const.TRIANGLE_LENGTH,
left: -this._const.TRIANGLE_LENGTH, left: -this._const.TRIANGLE_LENGTH,
right: "", right: "",
}; };
break; break;
case "right,top": case "right,top":
direction = "right"; direction = "right";
style = { style = {
bottom: BI.clamp(((middle ? popupHeight : position.height) + adjustYOffset) / 2 - 8, minBottom, maxBottom), bottom: clamp(((middle ? popupHeight : position.height) + adjustYOffset) / 2 - 8, minBottom, maxBottom),
}; };
wrapperStyle = { wrapperStyle = {
left: lgap + hgap, left: lgap + hgap,
bottom: 0, bottom: 0,
top: "", top: "",
right: "", right: "",
}; };
placeholderStyle = { placeholderStyle = {
top: 0, top: 0,
bottom: 0, bottom: 0,
width: this._const.TRIANGLE_LENGTH, width: this._const.TRIANGLE_LENGTH,
left: -this._const.TRIANGLE_LENGTH, left: -this._const.TRIANGLE_LENGTH,
right: "", right: "",
}; };
break; break;
case "right,innerRight": case "right,innerRight":
break; break;
case "right,innerLeft": case "right,innerLeft":
break; break;
case "innerRight": case "innerRight":
break; break;
case "innerLeft": case "innerLeft":
break; break;
default: default:
break; break;
} }
this.element this.element
.removeClass("left") .removeClass("left")
.removeClass("right") .removeClass("right")
.removeClass("top") .removeClass("top")
.removeClass("bottom") .removeClass("bottom")
.addClass(direction); .addClass(direction);
this.arrow.element.css(style); this.arrow.element.css(style);
this.arrowWrapper.element.css(wrapperStyle); this.arrowWrapper.element.css(wrapperStyle);
this.placeholder.element.css(placeholderStyle); this.placeholder.element.css(placeholderStyle);
} }
} }
getView() { getView() {
return this.view; return this.view;
} }
populate(items) { populate(items) {
this.view.populate.apply(this.view, arguments); this.view.populate(...arguments);
} }
resetWidth(w) { resetWidth(w) {
this.options.width = w; this.options.width = w;
this.element.width(w); this.element.width(w);
} }
resetHeight(h) { resetHeight(h) {
const tbHeight = this.toolbar ? (this.toolbar.attr("height") || 24) : 0, const tbHeight = this.toolbar ? (this.toolbar.attr("height") || 24) : 0,
tabHeight = this.tab ? (this.tab.attr("height") || 24) : 0, tabHeight = this.tab ? (this.tab.attr("height") || 24) : 0,
toolHeight = ((this.tool && this.tool.attr("height")) || 24) * ((this.tool && this.tool.isVisible()) ? 1 : 0); toolHeight = ((this.tool && this.tool.attr("height")) || 24) * ((this.tool && this.tool.isVisible()) ? 1 : 0);
const resetHeight = h - tbHeight - tabHeight - toolHeight - 2 * this.options.innerVgap; const resetHeight = h - tbHeight - tabHeight - toolHeight - 2 * this.options.innerVgap;
this.view.resetHeight ? this.view.resetHeight(resetHeight) : this.view.resetHeight ? this.view.resetHeight(resetHeight) :
this.view.element.css({ "max-height": BI.pixFormat(resetHeight) }); this.view.element.css({ "max-height": BI.pixFormat(resetHeight) });
} }
setValue(selectedValues) { setValue(selectedValues) {
this.tab && this.tab.setValue(selectedValues); this.tab && this.tab.setValue(selectedValues);
this.view.setValue(selectedValues); this.view.setValue(selectedValues);
} }
getValue() { getValue() {
return this.view.getValue(); return this.view.getValue();
} }
} }

193
src/base/layer/layer.searcher.js

@ -6,106 +6,97 @@
* @extends BI.Pane * @extends BI.Pane
*/ */
import { shortcut } from "../../core"; import { shortcut, extend, createWidget, Controller, isNotEmptyArray } from "../../core";
import { Pane } from "../1.pane"; import { Pane } from "../1.pane";
@shortcut() @shortcut()
export class SearcherView extends Pane { export class SearcherView extends Pane {
static xtype = "bi.searcher_view"; static xtype = "bi.searcher_view";
static EVENT_CHANGE = "EVENT_CHANGE"; static EVENT_CHANGE = "EVENT_CHANGE";
_defaultConfig() { _defaultConfig() {
const conf = super._defaultConfig(arguments); const conf = super._defaultConfig(arguments);
return BI.extend(conf, { return extend(conf, {
baseCls: (conf.baseCls || "") + " bi-searcher-view bi-card", baseCls: `${conf.baseCls || ""} bi-searcher-view bi-card`,
tipText: BI.i18nText("BI-No_Select"), tipText: BI.i18nText("BI-No_Select"),
chooseType: BI.Selection.Single, chooseType: BI.Selection.Single,
matcher: { // 完全匹配的构造器 matcher: { // 完全匹配的构造器
type: "bi.button_group", type: "bi.button_group",
behaviors: { behaviors: {
redmark: () => { redmark: () => true,
return true; },
}, items: [],
}, layouts: [{
items: [], type: "bi.vertical",
layouts: [{ }],
type: "bi.vertical", },
}], searcher: {
}, type: "bi.button_group",
searcher: { behaviors: {
type: "bi.button_group", redmark: () => true,
behaviors: { },
redmark: () => { items: [],
return true; layouts: [{
}, type: "bi.vertical",
}, }],
items: [], },
layouts: [{ });
type: "bi.vertical",
}],
},
});
} }
render() { render() {
const { matcher, chooseType, value, searcher } = this.options; const { matcher, chooseType, value, searcher } = this.options;
this.matcher = BI.createWidget(matcher, { this.matcher = createWidget(matcher, {
type: "bi.button_group", type: "bi.button_group",
chooseType, chooseType,
behaviors: { behaviors: {
redmark: () => { redmark: () => true,
return true; },
}, layouts: [{
}, type: "bi.vertical",
layouts: [{ }],
type: "bi.vertical", value,
}], });
value, this.matcher.on(Controller.EVENT_CHANGE, (type, val, ob, ...args) => {
}); this.fireEvent(Controller.EVENT_CHANGE, type, val, ob, ...args);
this.matcher.on(BI.Controller.EVENT_CHANGE, (type, val, ob, ...args) => { if (type === BI.Events.CLICK) {
this.fireEvent.apply(this, [BI.Controller.EVENT_CHANGE, type, val, ob, ...args]); this.fireEvent(SearcherView.EVENT_CHANGE, val, ob);
if (type === BI.Events.CLICK) { }
this.fireEvent(SearcherView.EVENT_CHANGE, val, ob); });
} this.spliter = createWidget({
}); type: "bi.vertical",
this.spliter = BI.createWidget({ height: 1,
type: "bi.vertical", hgap: 10,
height: 1, items: [{
hgap: 10, type: "bi.layout",
items: [{ height: 1,
type: "bi.layout", cls: "searcher-view-spliter bi-background",
height: 1, }],
cls: "searcher-view-spliter bi-background", });
}], this.searcher = createWidget(searcher, {
}); type: "bi.button_group",
this.searcher = BI.createWidget(searcher, { chooseType,
type: "bi.button_group", behaviors: {
chooseType, redmark: () => true,
behaviors: { },
redmark: () => { layouts: [{
return true; type: "bi.vertical",
}, }],
}, value,
layouts: [{ });
type: "bi.vertical", this.searcher.on(Controller.EVENT_CHANGE, (type, val, ob, ...args) => {
}], this.fireEvent(Controller.EVENT_CHANGE, type, val, ob, ...args);
value, if (type === BI.Events.CLICK) {
}); this.fireEvent(BI.SearcherView.EVENT_CHANGE, val, ob);
this.searcher.on(BI.Controller.EVENT_CHANGE, (type, val, ob, ...args) => { }
this.fireEvent.apply(this, [BI.Controller.EVENT_CHANGE, type, val, ob, ...args]); });
if (type === BI.Events.CLICK) {
this.fireEvent(BI.SearcherView.EVENT_CHANGE, val, ob); createWidget({
} type: "bi.vertical",
}); element: this,
items: [this.matcher, this.spliter, this.searcher],
BI.createWidget({ });
type: "bi.vertical",
element: this,
items: [this.matcher, this.spliter, this.searcher],
});
} }
startSearch() { startSearch() {
@ -117,30 +108,30 @@ export class SearcherView extends Pane {
} }
setValue(v) { setValue(v) {
this.matcher.setValue(v); this.matcher.setValue(v);
this.searcher.setValue(v); this.searcher.setValue(v);
} }
getValue() { getValue() {
return this.matcher.getValue().concat(this.searcher.getValue()); return this.matcher.getValue().concat(this.searcher.getValue());
} }
populate(searchResult, matchResult, keyword) { populate(searchResult, matchResult, keyword) {
searchResult || (searchResult = []); searchResult || (searchResult = []);
matchResult || (matchResult = []); matchResult || (matchResult = []);
this.setTipVisible(searchResult.length + matchResult.length === 0); this.setTipVisible(searchResult.length + matchResult.length === 0);
this.spliter.setVisible(BI.isNotEmptyArray(matchResult) && BI.isNotEmptyArray(searchResult)); this.spliter.setVisible(isNotEmptyArray(matchResult) && isNotEmptyArray(searchResult));
this.matcher.populate(matchResult, keyword); this.matcher.populate(matchResult, keyword);
this.searcher.populate(searchResult, keyword); this.searcher.populate(searchResult, keyword);
} }
empty() { empty() {
this.searcher.empty(); this.searcher.empty();
this.matcher.empty(); this.matcher.empty();
} }
hasMatched() { hasMatched() {
return this.matcher.getAllButtons().length > 0; return this.matcher.getAllButtons().length > 0;
} }
} }

2
src/base/list/index.js

@ -1,3 +1,3 @@
export { ListView } from "./listview"; export { ListView } from "./listview";
export { VirtualGroupList } from "./virtualgrouplist"; export { VirtualGroupList } from "./virtualgrouplist";
export { VirtualList } from "./virtuallist"; export { VirtualList } from "./virtuallist";

166
src/base/list/listview.js

@ -5,27 +5,25 @@
* @class BI.ListView * @class BI.ListView
* @extends BI.Widget * @extends BI.Widget
*/ */
import { Widget, shortcut } from "../../core"; import { Widget, shortcut, extend, isFunction } from "../../core";
@shortcut() @shortcut()
export class ListView extends Widget { export class ListView extends Widget {
props() { props() {
return { return {
baseCls: "bi-list-view", baseCls: "bi-list-view",
overscanHeight: 100, overscanHeight: 100,
blockSize: 10, blockSize: 10,
scrollTop: 0, scrollTop: 0,
el: {}, el: {},
items: [], items: [],
itemFormatter: (item, index) => { itemFormatter: (item, index) => item,
return item; };
}, }
};
}
init() { init() {
this.renderedIndex = -1; this.renderedIndex = -1;
this.cache = {}; this.cache = {};
} }
static xtype = "bi.list_view"; static xtype = "bi.list_view";
@ -34,10 +32,10 @@ export class ListView extends Widget {
return { return {
type: "bi.vertical", type: "bi.vertical",
items: [BI.extend({ items: [extend({
type: "bi.vertical", type: "bi.vertical",
scrolly: false, scrolly: false,
ref: (_ref) => { ref: _ref => {
this.container = _ref; this.container = _ref;
}, },
}, el)], }, el)],
@ -47,69 +45,66 @@ export class ListView extends Widget {
// mounted之后绑定事件 // mounted之后绑定事件
mounted() { mounted() {
const o = this.options; const o = this.options;
// 这里无法进行结构,因为存在赋值操作,如果使用结构则this.options的值不会跟随变化 // 这里无法进行结构,因为存在赋值操作,如果使用结构则this.options的值不会跟随变化
o.items = BI.isFunction(o.items) ? this.__watch(o.items, (context, newValue) => { o.items = isFunction(o.items) ? this.__watch(o.items, (context, newValue) => {
this.populate(newValue); this.populate(newValue);
}) : o.items; }) : o.items;
this._populate(); this._populate();
this.element.scroll((e) => { this.element.scroll(e => {
o.scrollTop = this.element.scrollTop(); o.scrollTop = this.element.scrollTop();
this._calculateBlocksToRender(); this._calculateBlocksToRender();
}); });
let lastWidth = this.element.width(), let lastWidth = this.element.width(),
lastHeight = this.element.height(); lastHeight = this.element.height();
BI.ResizeDetector.addResizeListener(this, () => { BI.ResizeDetector.addResizeListener(this, () => {
if (!this.element.is(":visible")) { if (!this.element.is(":visible")) {
return; return;
} }
const width = this.element.width(), const width = this.element.width(),
height = this.element.height(); height = this.element.height();
if (width !== lastWidth || height !== lastHeight) { if (width !== lastWidth || height !== lastHeight) {
lastWidth = width; lastWidth = width;
lastHeight = height; lastHeight = height;
this._calculateBlocksToRender(); this._calculateBlocksToRender();
} }
}); });
} }
_renderMoreIf() { _renderMoreIf() {
const { scrollTop, overscanHeight, blockSize, items, itemFormatter } = this.options; const { scrollTop, overscanHeight, blockSize, items, itemFormatter } = this.options;
const height = this.element.height(); const height = this.element.height();
const minContentHeight = scrollTop + height + overscanHeight; const minContentHeight = scrollTop + height + overscanHeight;
let index = (this.cache[this.renderedIndex] && (this.cache[this.renderedIndex].index + blockSize)) || 0; let index = (this.cache[this.renderedIndex] && (this.cache[this.renderedIndex].index + blockSize)) || 0;
let cnt = this.renderedIndex + 1; let cnt = this.renderedIndex + 1;
let lastHeight; let lastHeight;
const getElementHeight = () => { const getElementHeight = () => this.container.element.height();
return this.container.element.height();
}
lastHeight = getElementHeight(); lastHeight = getElementHeight();
while ((lastHeight) < minContentHeight && index < items.length) { while ((lastHeight) < minContentHeight && index < items.length) {
const itemsArr = items.slice(index, index + blockSize); const itemsArr = items.slice(index, index + blockSize);
this.container.addItems(itemsArr.map((item, i) => { // eslint-disable-next-line no-loop-func
return itemFormatter(item, index + i); this.container.addItems(itemsArr.map((item, i) => itemFormatter(item, index + i)), this);
}), this); const addedHeight = getElementHeight() - lastHeight;
const addedHeight = getElementHeight() - lastHeight; this.cache[cnt] = {
this.cache[cnt] = { index,
index: index, scrollTop: lastHeight,
scrollTop: lastHeight, height: addedHeight,
height: addedHeight, };
}; this.renderedIndex = cnt;
this.renderedIndex = cnt; cnt++;
cnt++; index += blockSize;
index += blockSize; lastHeight = getElementHeight();
lastHeight = getElementHeight(); }
}
} }
_calculateBlocksToRender() { _calculateBlocksToRender() {
// BI-115750 不可见状态下依赖元素实际尺寸构造的线段树会分段错误,所以不进行后续计算和线段树的初始化。 // BI-115750 不可见状态下依赖元素实际尺寸构造的线段树会分段错误,所以不进行后续计算和线段树的初始化。
// 这样从不可见状态变为可见状态能够重新触发线段树初始化 // 这样从不可见状态变为可见状态能够重新触发线段树初始化
if (!this.element.is(":visible")) { if (!this.element.is(":visible")) {
return; return;
} }
this._renderMoreIf(); this._renderMoreIf();
} }
_populate(items) { _populate(items) {
@ -128,22 +123,21 @@ export class ListView extends Widget {
} }
scrollTo(scrollTop) { scrollTo(scrollTop) {
this.options.scrollTop = scrollTop; this.options.scrollTop = scrollTop;
this._calculateBlocksToRender(); this._calculateBlocksToRender();
this.element.scrollTop(scrollTop); this.element.scrollTop(scrollTop);
} }
populate(items) { populate(items) {
if (items && this.options.items !== items) { if (items && this.options.items !== items) {
this.restore(); this.restore();
} }
this._populate(items); this._populate(items);
} }
beforeDestroy() { beforeDestroy() {
BI.ResizeDetector.removeResizeListener(this); BI.ResizeDetector.removeResizeListener(this);
this.restore(); this.restore();
} }
} }

285
src/base/list/virtualgrouplist.js

@ -6,196 +6,187 @@
* @extends BI.Widget * @extends BI.Widget
*/ */
import { Widget, shortcut } from "../../core"; import { Widget, shortcut, extend, isFunction, isNumber, PrefixIntervalTree } from "../../core";
@shortcut() @shortcut()
export class VirtualGroupList extends Widget { export class VirtualGroupList extends Widget {
props() { props() {
return { return {
baseCls: "bi-virtual-group-list", baseCls: "bi-virtual-group-list",
overscanHeight: 100, overscanHeight: 100,
blockSize: 10, blockSize: 10,
scrollTop: 0, scrollTop: 0,
rowHeight: "auto", rowHeight: "auto",
items: [], items: [],
el: {}, el: {},
itemFormatter: (item, index) => { itemFormatter: (item, index) => item,
return item; };
}, }
};
}
init() { init() {
this.renderedIndex = -1; this.renderedIndex = -1;
} }
static xtype = "bi.virtual_group_list"; static xtype = "bi.virtual_group_list";
render() { render() {
const { rowHeight, items, el } = this.options; const { rowHeight, items, el } = this.options;
return { return {
type: "bi.vertical", type: "bi.vertical",
items: [{ items: [{
type: "bi.layout", type: "bi.layout",
ref: () => { ref: () => {
this.topBlank = this; this.topBlank = this;
}, },
}, { }, {
type: "bi.virtual_group", type: "bi.virtual_group",
height: rowHeight * items.length, height: rowHeight * items.length,
ref: () => { ref: () => {
this.container = this; this.container = this;
}, },
layouts: [BI.extend({ layouts: [extend({
type: "bi.vertical", type: "bi.vertical",
scrolly: false, scrolly: false,
}, el)], }, el)],
}, { }, {
type: "bi.layout", type: "bi.layout",
ref: () => { ref: () => {
this.bottomBlank = this; this.bottomBlank = this;
}, },
}], }],
element: this, element: this,
}; };
} }
// mounted之后绑定事件 // mounted之后绑定事件
mounted() { mounted() {
// 这里无法进行结构,因为存在赋值操作,如果使用结构则this.options的值不会跟随变化 // 这里无法进行结构,因为存在赋值操作,如果使用结构则this.options的值不会跟随变化
const o = this.options; const o = this.options;
o.items = BI.isFunction(o.items) ? this.__watch(o.items, (context, newValue) => { o.items = isFunction(o.items) ? this.__watch(o.items, (context, newValue) => {
this.populate(newValue); this.populate(newValue);
}) : o.items; }) : o.items;
this._populate(); this._populate();
this.ticking = false; this.ticking = false;
this.element.scroll(() => { this.element.scroll(() => {
o.scrollTop = this.element.scrollTop(); o.scrollTop = this.element.scrollTop();
if (!this.ticking) { if (!this.ticking) {
requestAnimationFrame(() => { requestAnimationFrame(() => {
this._calculateBlocksToRender();
this.ticking = false;
});
this.ticking = true;
}
});
BI.ResizeDetector.addResizeListener(this, () => {
if (this.element.is(":visible")) {
this._calculateBlocksToRender(); this._calculateBlocksToRender();
this.ticking = false; }
}); });
this.ticking = true;
}
});
BI.ResizeDetector.addResizeListener(this, () => {
if (this.element.is(":visible")) {
this._calculateBlocksToRender();
}
});
} }
_isAutoHeight() { _isAutoHeight() {
return !BI.isNumber(this.options.rowHeight); return !isNumber(this.options.rowHeight);
} }
_renderMoreIf() { _renderMoreIf() {
const { scrollTop, overscanHeight, blockSize, items, itemFormatter } = this.options; const { scrollTop, overscanHeight, blockSize, items, itemFormatter } = this.options;
const height = this.element.height(); const height = this.element.height();
const minContentHeight = scrollTop + height + overscanHeight; const minContentHeight = scrollTop + height + overscanHeight;
let index = (this.renderedIndex + 1) * blockSize, cnt = this.renderedIndex + 1; let index = (this.renderedIndex + 1) * blockSize, cnt = this.renderedIndex + 1;
let lastHeight; let lastHeight;
const getElementHeight = () => { const getElementHeight = () => this.container.element.height() + this.topBlank.element.height() + this.bottomBlank.element.height();
return this.container.element.height() + this.topBlank.element.height() + this.bottomBlank.element.height(); lastHeight = this.renderedIndex === -1 ? 0 : getElementHeight();
} while (lastHeight < minContentHeight && index < items.length) {
lastHeight = this.renderedIndex === -1 ? 0 : getElementHeight(); const itemsArr = items.slice(index, index + blockSize);
while (lastHeight < minContentHeight && index < items.length) { // eslint-disable-next-line no-loop-func
const itemsArr = items.slice(index, index + blockSize); this.container[this.renderedIndex === -1 ? "populate" : "addItems"](itemsArr.map((item, i) => itemFormatter(item, index + i)), this);
this.container[this.renderedIndex === -1 ? "populate" : "addItems"](itemsArr.map((item, i) => { const elementHeight = getElementHeight();
return itemFormatter(item, index + i); const addedHeight = elementHeight - lastHeight;
}), this); this.tree.set(cnt, addedHeight);
const elementHeight = getElementHeight(); this.renderedIndex = cnt;
const addedHeight = elementHeight - lastHeight; cnt++;
this.tree.set(cnt, addedHeight); index += blockSize;
this.renderedIndex = cnt; lastHeight = this.renderedIndex === -1 ? 0 : elementHeight;
cnt++; }
index += blockSize;
lastHeight = this.renderedIndex === -1 ? 0 : elementHeight;
}
} }
_calculateBlocksToRender() { _calculateBlocksToRender() {
// BI-115750 不可见状态下依赖元素实际尺寸构造的线段树会分段错误,所以不进行后续计算和线段树的初始化。 // BI-115750 不可见状态下依赖元素实际尺寸构造的线段树会分段错误,所以不进行后续计算和线段树的初始化。
// 这样从不可见状态变为可见状态能够重新触发线段树初始化 // 这样从不可见状态变为可见状态能够重新触发线段树初始化
if (!this.element.is(":visible")) { if (!this.element.is(":visible")) {
return; return;
}
const { scrollTop, overscanHeight, blockSize, items, itemFormatter, rowHeight } = this.options;
this._isAutoHeight() && this._renderMoreIf();
const height = this.element.height();
const minContentHeightFrom = scrollTop - overscanHeight;
const minContentHeightTo = scrollTop + height + overscanHeight;
const start = this.tree.greatestLowerBound(minContentHeightFrom);
const end = this.tree.leastUpperBound(minContentHeightTo);
const itemsArr = [];
const topHeight = this.tree.sumTo(Math.max(-1, start - 1));
this.topBlank.setHeight(topHeight + "px");
if (this._isAutoHeight()) {
for (let i = (start < 0 ? 0 : start); i <= end && i <= this.renderedIndex; i++) {
const index = i * blockSize;
for (let j = index; j < index + blockSize && j < items.length; j++) {
itemsArr.push(items[j]);
}
} }
this.bottomBlank.setHeight(this.tree.sumTo(this.renderedIndex) - this.tree.sumTo(Math.min(end, this.renderedIndex)) + "px"); const { scrollTop, overscanHeight, blockSize, items, itemFormatter, rowHeight } = this.options;
this.container.populate(itemsArr.map((item, i) => { this._isAutoHeight() && this._renderMoreIf();
return itemFormatter(item, (start < 0 ? 0 : start) * blockSize + i); const height = this.element.height();
})); const minContentHeightFrom = scrollTop - overscanHeight;
} else { const minContentHeightTo = scrollTop + height + overscanHeight;
for (let i = (start < 0 ? 0 : start); i <= end; i++) { const start = this.tree.greatestLowerBound(minContentHeightFrom);
const index = i * blockSize; const end = this.tree.leastUpperBound(minContentHeightTo);
for (let j = index; j < index + blockSize && j < items.length; j++) { const itemsArr = [];
itemsArr.push(items[j]); const topHeight = this.tree.sumTo(Math.max(-1, start - 1));
this.topBlank.setHeight(`${topHeight}px`);
if (this._isAutoHeight()) {
for (let i = (start < 0 ? 0 : start); i <= end && i <= this.renderedIndex; i++) {
const index = i * blockSize;
for (let j = index; j < index + blockSize && j < items.length; j++) {
itemsArr.push(items[j]);
}
} }
this.bottomBlank.setHeight(`${this.tree.sumTo(this.renderedIndex) - this.tree.sumTo(Math.min(end, this.renderedIndex))}px`);
this.container.populate(itemsArr.map((item, i) => itemFormatter(item, (start < 0 ? 0 : start) * blockSize + i)));
} else {
for (let i = (start < 0 ? 0 : start); i <= end; i++) {
const index = i * blockSize;
for (let j = index; j < index + blockSize && j < items.length; j++) {
itemsArr.push(items[j]);
}
}
this.container.element.height(rowHeight * items.length - topHeight);
this.container.populate(itemsArr.map((item, i) => itemFormatter(item, (start < 0 ? 0 : start) * blockSize + i)));
} }
this.container.element.height(rowHeight * items.length - topHeight);
this.container.populate(itemsArr.map((item, i) => {
return itemFormatter(item, (start < 0 ? 0 : start) * blockSize + i);
}));
}
} }
_populate(items) { _populate(items) {
const { blockSize, rowHeight, scrollTop } = this.options; const { blockSize, rowHeight, scrollTop } = this.options;
if (items && this.options.items !== items) { if (items && this.options.items !== items) {
// 重新populate一组items,需要重新对线段树分块 // 重新populate一组items,需要重新对线段树分块
this.options.items = items; this.options.items = items;
this._restore(); this._restore();
} }
this.tree = BI.PrefixIntervalTree.uniform(Math.ceil(this.options.items.length / blockSize), this._isAutoHeight() ? 0 : rowHeight * blockSize); this.tree = PrefixIntervalTree.uniform(Math.ceil(this.options.items.length / blockSize), this._isAutoHeight() ? 0 : rowHeight * blockSize);
this._calculateBlocksToRender(); this._calculateBlocksToRender();
try { try {
this.element.scrollTop(scrollTop); this.element.scrollTop(scrollTop);
} catch (e) { } catch (e) {
} }
} }
_restore() { _restore() {
this.renderedIndex = -1; this.renderedIndex = -1;
// 依赖于cache的占位元素也要初始化 // 依赖于cache的占位元素也要初始化
this.topBlank.setHeight(0); this.topBlank.setHeight(0);
this.bottomBlank.setHeight(0); this.bottomBlank.setHeight(0);
} }
// 暂时只支持固定行高的场景 // 暂时只支持固定行高的场景
scrollTo(scrollTop) { scrollTo(scrollTop) {
this.options.scrollTop = scrollTop; this.options.scrollTop = scrollTop;
this._calculateBlocksToRender(); this._calculateBlocksToRender();
this.element.scrollTop(scrollTop); this.element.scrollTop(scrollTop);
} }
restore() { restore() {
this.options.scrollTop = 0; this.options.scrollTop = 0;
this._restore(); this._restore();
} }
populate(items) { populate(items) {
this._populate(items); this._populate(items);
} }
beforeDestroy() { beforeDestroy() {
BI.ResizeDetector.removeResizeListener(this); BI.ResizeDetector.removeResizeListener(this);
this.restore(); this.restore();
} }
} }

325
src/base/list/virtuallist.js

@ -6,7 +6,7 @@
* @extends BI.Widget * @extends BI.Widget
*/ */
import { Widget, shortcut } from "../../core"; import { Widget, shortcut, isFunction, each, PrefixIntervalTree } from "../../core";
@shortcut() @shortcut()
export class VirtualList extends Widget { export class VirtualList extends Widget {
props() { props() {
@ -16,9 +16,7 @@ export class VirtualList extends Widget {
blockSize: 10, blockSize: 10,
scrollTop: 0, scrollTop: 0,
items: [], items: [],
itemFormatter: (item, index) => { itemFormatter: (item, index) => item,
return item;
},
}; };
} }
@ -30,189 +28,186 @@ export class VirtualList extends Widget {
static xtype = "bi.virtual_list"; static xtype = "bi.virtual_list";
render() { render() {
return { return {
type: "bi.vertical", type: "bi.vertical",
items: [{ items: [{
type: "bi.layout", type: "bi.layout",
ref: (_ref) => { ref: _ref => {
this.topBlank = _ref; this.topBlank = _ref;
}, },
}, { }, {
type: "bi.vertical", type: "bi.vertical",
scrolly: false, scrolly: false,
ref: (_ref) => { ref: _ref => {
this.container = _ref; this.container = _ref;
}, },
}, { }, {
type: "bi.layout", type: "bi.layout",
ref: (_ref) => { ref: _ref => {
this.bottomBlank = _ref; this.bottomBlank = _ref;
}, },
}], }],
}; };
} }
// mounted之后绑定事件 // mounted之后绑定事件
mounted() { mounted() {
// 这里无法进行结构,因为存在赋值操作,如果使用结构则this.options的值不会跟随变化 // 这里无法进行结构,因为存在赋值操作,如果使用结构则this.options的值不会跟随变化
const o = this.options; const o = this.options;
o.items = BI.isFunction(o.items) ? this.__watch(o.items, (context, newValue) => { o.items = isFunction(o.items) ? this.__watch(o.items, (context, newValue) => {
this.populate(newValue); this.populate(newValue);
}) : o.items; }) : o.items;
this._populate(); this._populate();
this.element.scroll((e) => { this.element.scroll(e => {
o.scrollTop = this.element.scrollTop(); o.scrollTop = this.element.scrollTop();
this._calculateBlocksToRender(); this._calculateBlocksToRender();
}); });
BI.ResizeDetector.addResizeListener(this, () => { BI.ResizeDetector.addResizeListener(this, () => {
if (this.element.is(":visible")) { if (this.element.is(":visible")) {
this._calculateBlocksToRender(); this._calculateBlocksToRender();
} }
}); });
} }
_renderMoreIf() { _renderMoreIf() {
const { scrollTop, overscanHeight, blockSize, items, itemFormatter } = this.options; const { scrollTop, overscanHeight, blockSize, items, itemFormatter } = this.options;
const height = this.element.height(); const height = this.element.height();
const minContentHeight = scrollTop + height + overscanHeight; const minContentHeight = scrollTop + height + overscanHeight;
let index = (this.renderedIndex + 1) * blockSize, cnt = this.renderedIndex + 1; let index = (this.renderedIndex + 1) * blockSize, cnt = this.renderedIndex + 1;
let lastHeight; let lastHeight;
const getElementHeight = () => { const getElementHeight = () => this.container.element.height() + this.topBlank.element.height() + this.bottomBlank.element.height();
return this.container.element.height() + this.topBlank.element.height() + this.bottomBlank.element.height(); lastHeight = getElementHeight();
} while (lastHeight < minContentHeight && index < items.length) {
lastHeight = getElementHeight(); const itemsArr = items.slice(index, index + blockSize);
while (lastHeight < minContentHeight && index < items.length) { // eslint-disable-next-line no-loop-func
const itemsArr = items.slice(index, index + blockSize); this.container.addItems(itemsArr.map((item, i) => itemFormatter(item, index + i)), this);
this.container.addItems(itemsArr.map((item, i) => { const addedHeight = getElementHeight() - lastHeight;
return itemFormatter(item, index + i); this.tree.set(cnt, addedHeight);
}), this); this.renderedIndex = cnt;
const addedHeight = getElementHeight() - lastHeight; cnt++;
this.tree.set(cnt, addedHeight); index += blockSize;
this.renderedIndex = cnt; lastHeight = getElementHeight();
cnt++; }
index += blockSize;
lastHeight = getElementHeight();
}
}
_calculateBlocksToRender() {
const { scrollTop, overscanHeight, blockSize, items, itemFormatter } = this.options;
// BI-115750 不可见状态下依赖元素实际尺寸构造的线段树会分段错误,所以不进行后续计算和线段树的初始化。
// 这样从不可见状态变为可见状态能够重新触发线段树初始化
if (!this.element.is(":visible")) {
return;
} }
this._renderMoreIf();
const height = this.element.height(); _calculateBlocksToRender() {
const minContentHeightFrom = scrollTop - overscanHeight; const { scrollTop, overscanHeight, blockSize, items, itemFormatter } = this.options;
const minContentHeightTo = scrollTop + height + overscanHeight; // BI-115750 不可见状态下依赖元素实际尺寸构造的线段树会分段错误,所以不进行后续计算和线段树的初始化。
const start = this.tree.greatestLowerBound(minContentHeightFrom); // 这样从不可见状态变为可见状态能够重新触发线段树初始化
const end = this.tree.leastUpperBound(minContentHeightTo); if (!this.element.is(":visible")) {
const needDestroyed = [], needMount = []; return;
for (let i = 0; i < start; i++) {
let index = i * blockSize;
if (!this.cache[i]) {
this.cache[i] = {};
} }
if (!this.cache[i].destroyed) { this._renderMoreIf();
for (let j = index; j < index + blockSize && j < items.length; j++) { const height = this.element.height();
needDestroyed.push(this.container._children[j]); const minContentHeightFrom = scrollTop - overscanHeight;
this.container._children[j] = null; const minContentHeightTo = scrollTop + height + overscanHeight;
const start = this.tree.greatestLowerBound(minContentHeightFrom);
const end = this.tree.leastUpperBound(minContentHeightTo);
const needDestroyed = [], needMount = [];
for (let i = 0; i < start; i++) {
const index = i * blockSize;
if (!this.cache[i]) {
this.cache[i] = {};
}
if (!this.cache[i].destroyed) {
for (let j = index; j < index + blockSize && j < items.length; j++) {
needDestroyed.push(this.container._children[j]);
this.container._children[j] = null;
}
this.cache[i].destroyed = true;
} }
this.cache[i].destroyed = true;
} }
} for (let i = end + 1; i <= this.renderedIndex; i++) {
for (let i = end + 1; i <= this.renderedIndex; i++) { const index = i * blockSize;
let index = i * blockSize; if (!this.cache[i]) {
if (!this.cache[i]) { this.cache[i] = {};
this.cache[i] = {}; }
} if (!this.cache[i].destroyed) {
if (!this.cache[i].destroyed) { for (let j = index; j < index + blockSize && j < items.length; j++) {
for (let j = index; j < index + blockSize && j < items.length; j++) { needDestroyed.push(this.container._children[j]);
needDestroyed.push(this.container._children[j]); this.container._children[j] = null;
this.container._children[j] = null; }
this.cache[i].destroyed = true;
}
} }
this.cache[i].destroyed = true; const firstFragment = Widget._renderEngine.createFragment(),
} lastFragment = Widget._renderEngine.createFragment();
} let currentFragment = firstFragment;
const firstFragment = BI.Widget._renderEngine.createFragment(), for (let i = (start < 0 ? 0 : start); i <= end && i <= this.renderedIndex; i++) {
lastFragment = BI.Widget._renderEngine.createFragment(); const index = i * blockSize;
let currentFragment = firstFragment; if (!this.cache[i]) {
for (let i = (start < 0 ? 0 : start); i <= end && i <= this.renderedIndex; i++) { this.cache[i] = {};
const index = i * blockSize; }
if (!this.cache[i]) { if (!this.cache[i].destroyed) {
this.cache[i] = {}; currentFragment = lastFragment;
}
if (this.cache[i].destroyed === true) {
for (let j = index; j < index + blockSize && j < items.length; j++) {
const w = this.container._addElement(j, itemFormatter(items[j], j), this);
needMount.push(w);
currentFragment.appendChild(w.element[0]);
}
this.cache[i].destroyed = false;
}
} }
if (!this.cache[i].destroyed) { this.container.element.prepend(firstFragment);
currentFragment = lastFragment; this.container.element.append(lastFragment);
this.topBlank.setHeight(`${this.tree.sumTo(Math.max(-1, start - 1))}px`);
this.bottomBlank.setHeight(`${this.tree.sumTo(this.renderedIndex) - this.tree.sumTo(Math.min(end, this.renderedIndex))}px`);
each(needMount, (i, child) => {
child && child._mount();
});
each(needDestroyed, (i, child) => {
child && child._destroy();
});
}
_populate(items) {
const { blockSize, scrollTop } = this.options;
if (items && this.options.items !== items) {
this.options.items = items;
} }
if (this.cache[i].destroyed === true) { this.tree = PrefixIntervalTree.empty(Math.ceil(this.options.items.length / blockSize));
for (let j = index; j < index + blockSize && j < items.length; j++) {
const w = this.container._addElement(j, itemFormatter(items[j], j), this); this._calculateBlocksToRender();
needMount.push(w); try {
currentFragment.appendChild(w.element[0]); this.element.scrollTop(scrollTop);
} } catch (e) {
this.cache[i].destroyed = false;
} }
} }
this.container.element.prepend(firstFragment);
this.container.element.append(lastFragment); _clearChildren() {
this.topBlank.setHeight(this.tree.sumTo(Math.max(-1, start - 1)) + "px"); each(this.container._children, (i, cell) => {
this.bottomBlank.setHeight(this.tree.sumTo(this.renderedIndex) - this.tree.sumTo(Math.min(end, this.renderedIndex)) + "px"); cell && cell._destroy();
BI.each(needMount, (i, child) => { });
child && child._mount(); this.container._children = {};
}); this.container.attr("items", []);
BI.each(needDestroyed, (i, child) => {
child && child._destroy();
});
}
_populate(items) {
const { blockSize, scrollTop } = this.options;
if (items && this.options.items !== items) {
this.options.items = items;
} }
this.tree = BI.PrefixIntervalTree.empty(Math.ceil(this.options.items.length / blockSize));
this._calculateBlocksToRender(); scrollTo(scrollTop) {
try { this.options.scrollTop = scrollTop;
this._calculateBlocksToRender();
this.element.scrollTop(scrollTop); this.element.scrollTop(scrollTop);
} catch (e) {
} }
}
_clearChildren() {
BI.each(this.container._children, (i, cell) => {
cell && cell._destroy();
});
this.container._children = {};
this.container.attr("items", []);
}
scrollTo(scrollTop) { restore() {
this.options.scrollTop = scrollTop; this.renderedIndex = -1;
this._calculateBlocksToRender(); this._clearChildren();
this.element.scrollTop(scrollTop); this.cache = {};
} this.options.scrollTop = 0;
// 依赖于cache的占位元素也要初始化
this.topBlank.setHeight(0);
this.bottomBlank.setHeight(0);
}
restore() { populate(items) {
this.renderedIndex = -1; if (items && this.options.items !== items) {
this._clearChildren(); this.restore();
this.cache = {}; }
this.options.scrollTop = 0; this._populate(items);
// 依赖于cache的占位元素也要初始化 }
this.topBlank.setHeight(0);
this.bottomBlank.setHeight(0);
}
populate(items) { beforeDestroy() {
if (items && this.options.items !== items) { BI.ResizeDetector.removeResizeListener(this);
this.restore(); this.restore();
} }
this._populate(items);
}
beforeDestroy() {
BI.ResizeDetector.removeResizeListener(this);
this.restore();
}
} }

125
src/base/pager/pager.js

@ -5,11 +5,11 @@
* @class BI.Pager * @class BI.Pager
* @extends BI.Widget * @extends BI.Widget
*/ */
import { Widget, shortcut } from "../../core"; import { Widget, shortcut, extend, emptyFn, result, isKey, createWidget, map, stripEL, formatEL, Controller } from "../../core";
@shortcut() @shortcut()
export default class Pager extends Widget { export class Pager extends Widget {
_defaultConfig() { _defaultConfig() {
return BI.extend(super._defaultConfig(arguments), { return extend(super._defaultConfig(...arguments), {
baseCls: "bi-pager", baseCls: "bi-pager",
behaviors: {}, behaviors: {},
layouts: [{ layouts: [{
@ -23,22 +23,19 @@ export default class Pager extends Widget {
dynamicShowFirstLast: false, // 是否动态显示首页、尾页 dynamicShowFirstLast: false, // 是否动态显示首页、尾页
dynamicShowPrevNext: false, // 是否动态显示上一页、下一页 dynamicShowPrevNext: false, // 是否动态显示上一页、下一页
pages: false, // 总页数 pages: false, // 总页数
curr: () => { curr: () => 1, // 初始化当前页
return 1;
}, // 初始化当前页
groups: 0, // 连续显示分页数 groups: 0, // 连续显示分页数
jump: BI.emptyFn, // 分页的回调函数 jump: emptyFn, // 分页的回调函数
first: false, // 是否显示首页 first: false, // 是否显示首页
last: false, // 是否显示尾页 last: false, // 是否显示尾页
prev: "上一页", prev: "上一页",
next: "下一页", next: "下一页",
firstPage: 1, firstPage: 1,
lastPage: () => { // 在万不得已时才会调用这个函数获取最后一页的页码, 主要作用于setValue方法 lastPage: () => // 在万不得已时才会调用这个函数获取最后一页的页码, 主要作用于setValue方法
return 1; 1,
}, hasPrev: emptyFn, // pages不可用时有效
hasPrev: BI.emptyFn, // pages不可用时有效 hasNext: emptyFn, // pages不可用时有效
hasNext: BI.emptyFn, // pages不可用时有效
}); });
} }
@ -46,7 +43,7 @@ export default class Pager extends Widget {
static EVENT_CHANGE = "EVENT_CHANGE"; static EVENT_CHANGE = "EVENT_CHANGE";
static EVENT_AFTER_POPULATE = "EVENT_AFTER_POPULATE"; static EVENT_AFTER_POPULATE = "EVENT_AFTER_POPULATE";
render() { render() {
this.currPage = BI.result(this.options, "curr"); this.currPage = result(this.options, "curr");
// 翻页太灵敏 // 翻页太灵敏
// this._lock = false; // this._lock = false;
// this._debouce = BI.debounce(function () { // this._debouce = BI.debounce(function () {
@ -59,13 +56,13 @@ export default class Pager extends Widget {
const o = this.options, view = [], dict = {}; const o = this.options, view = [], dict = {};
const { dynamicShow, dynamicShowPrevNext, hasPrev, dynamicShowFirstLast, hasNext, behaviors, layouts, jump } = this.options; const { dynamicShow, dynamicShowPrevNext, hasPrev, dynamicShowFirstLast, hasNext, behaviors, layouts, jump } = this.options;
this.empty(); this.empty();
const pages = BI.result(o, "pages"); const pages = result(o, "pages");
const curr = BI.result(this, "currPage"); const curr = result(this, "currPage");
let groups = BI.result(o, "groups"); let groups = result(o, "groups");
let first = BI.result(o, "first"); let first = result(o, "first");
let last = BI.result(o, "last"); let last = result(o, "last");
const prev = BI.result(o, "prev"); const prev = result(o, "prev");
const next = BI.result(o, "next"); const next = result(o, "next");
if (pages === false) { if (pages === false) {
groups = 0; groups = 0;
@ -80,7 +77,7 @@ export default class Pager extends Widget {
// 当前页非首页,则输出上一页 // 当前页非首页,则输出上一页
if (((!dynamicShow && !dynamicShowPrevNext) || curr > 1) && prev !== false) { if (((!dynamicShow && !dynamicShowPrevNext) || curr > 1) && prev !== false) {
if (BI.isKey(prev)) { if (isKey(prev)) {
view.push({ view.push({
text: prev, text: prev,
value: "prev", value: "prev",
@ -88,7 +85,7 @@ export default class Pager extends Widget {
}); });
} else { } else {
view.push({ view.push({
el: BI.extend({ el: extend({
disabled: pages === false ? hasPrev(curr) === false : !(curr > 1 && prev !== false), disabled: pages === false ? hasPrev(curr) === false : !(curr > 1 && prev !== false),
}, prev), }, prev),
}); });
@ -162,7 +159,7 @@ export default class Pager extends Widget {
dict.flow = !prev && groups === 0; dict.flow = !prev && groups === 0;
if (((!dynamicShow && !dynamicShowPrevNext) && next) || (curr !== pages && next || dict.flow)) { if (((!dynamicShow && !dynamicShowPrevNext) && next) || (curr !== pages && next || dict.flow)) {
view.push((function () { view.push((function () {
if (BI.isKey(next)) { if (isKey(next)) {
if (pages === false) { if (pages === false) {
return { text: next, value: "next", disabled: hasNext(curr) === false }; return { text: next, value: "next", disabled: hasNext(curr) === false };
} }
@ -175,62 +172,62 @@ export default class Pager extends Widget {
} }
return { return {
el: BI.extend({ el: extend({
disabled: pages === false ? hasNext(curr) === false : !(curr !== pages && next || dict.flow), disabled: pages === false ? hasNext(curr) === false : !(curr !== pages && next || dict.flow),
}, next), }, next),
}; };
}())); }()));
} }
this.button_group = BI.createWidget({ this.button_group = createWidget({
type: "bi.button_group", type: "bi.button_group",
element: this, element: this,
items: BI.map(view, (idx, v) => { items: map(view, (idx, v) => {
v = BI.extend({ v = extend({
cls: "bi-list-item-select bi-border-radius", cls: "bi-list-item-select bi-border-radius",
height: 23, height: 23,
hgap: v.el ? 0 : 10, hgap: v.el ? 0 : 10,
stopPropagation: true, stopPropagation: true,
}, BI.stripEL(v)); }, stripEL(v));
return BI.formatEL(v); return formatEL(v);
}), }),
behaviors, behaviors,
layouts, layouts,
}); });
this.button_group.on(BI.Controller.EVENT_CHANGE, (type, value, obj, ...args) => { this.button_group.on(Controller.EVENT_CHANGE, (type, value, obj, ...args) => {
// if (self._lock === true) { // if (self._lock === true) {
// return; // return;
// } // }
// self._lock = true; // self._lock = true;
// self._debouce(); // self._debouce();
if (type === BI.Events.CLICK) { if (type === BI.Events.CLICK) {
var v = this.button_group.getValue()[0]; const v = this.button_group.getValue()[0];
switch (v) { switch (v) {
case "first": case "first":
this.currPage = 1; this.currPage = 1;
break; break;
case "last": case "last":
this.currPage = pages; this.currPage = pages;
break; break;
case "prev": case "prev":
this.currPage--; this.currPage--;
break; break;
case "next": case "next":
this.currPage++; this.currPage++;
break; break;
default: default:
this.currPage = v; this.currPage = v;
break; break;
} }
jump.apply(this, [{ jump.apply(this, [{
pages: pages, pages,
curr: this.currPage, curr: this.currPage,
}]); }]);
this._populate(); this._populate();
this.fireEvent(Pager.EVENT_CHANGE, obj); this.fireEvent(Pager.EVENT_CHANGE, obj);
} }
this.fireEvent.apply(this, [BI.Controller.EVENT_CHANGE, type, value, obj, ...args]); this.fireEvent(Controller.EVENT_CHANGE, type, value, obj, ...args);
}); });
this.fireEvent(Pager.EVENT_AFTER_POPULATE); this.fireEvent(Pager.EVENT_AFTER_POPULATE);
} }
@ -254,6 +251,7 @@ export default class Pager extends Widget {
hasNext(v) { hasNext(v) {
v || (v = 1); v || (v = 1);
const { pages, hasNext } = this.options; const { pages, hasNext } = this.options;
return pages === false ? hasNext(v) : v < pages; return pages === false ? hasNext(v) : v < pages;
} }
@ -263,8 +261,9 @@ export default class Pager extends Widget {
v = v || 0; v = v || 0;
v = v < 1 ? 1 : v; v = v < 1 ? 1 : v;
if (pages === false) { if (pages === false) {
var lastPage = BI.result(o, "lastPage"), firstPage = 1; const lastPage = result(o, "lastPage");
this.currPage = v > lastPage ? lastPage : ((firstPage = BI.result(o, "firstPage")), (v < firstPage ? firstPage : v)); let firstPage = 1;
this.currPage = v > lastPage ? lastPage : ((firstPage = result(o, "firstPage")), (v < firstPage ? firstPage : v));
} else { } else {
v = v > pages ? pages : v; v = v > pages ? pages : v;
this.currPage = v; this.currPage = v;
@ -275,27 +274,27 @@ export default class Pager extends Widget {
getValue() { getValue() {
const val = this.button_group.getValue()[0]; const val = this.button_group.getValue()[0];
switch (val) { switch (val) {
case "prev": case "prev":
return -1; return -1;
case "next": case "next":
return 1; return 1;
case "first": case "first":
return BI.MIN; return BI.MIN;
case "last": case "last":
return BI.MAX; return BI.MAX;
default: default:
return val; return val;
} }
} }
attr(key, value) { attr(key, value) {
super.attr(arguments); super.attr(...arguments);
if (key === "curr") { if (key === "curr") {
this.currPage = BI.result(this.options, "curr"); this.currPage = result(this.options, "curr");
} }
} }
populate() { populate() {
this._populate(); this._populate();
} }
} }

36
src/base/single/a/a.js

@ -6,32 +6,32 @@
* @extends BI.Text * @extends BI.Text
* @abstract * @abstract
*/ */
import { shortcut } from "../../../core"; import { shortcut, extend, createWidget } from "../../../core";
import { Text } from "../1.text"; import { Text } from "../1.text";
@shortcut() @shortcut()
export class A extends Text { export class A extends Text {
static xtype = "bi.a"; static xtype = "bi.a";
_defaultConfig() { _defaultConfig() {
const conf = super._defaultConfig(arguments); const conf = super._defaultConfig(arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-a display-block", return extend(conf, {
href: "", baseCls: `${conf.baseCls || ""} bi-a display-block`,
target: "_blank", href: "",
el: null, target: "_blank",
tagName: "a", el: null,
}); tagName: "a",
});
} }
render() { render() {
const { href, target, el} = this.options; const { href, target, el } = this.options;
super.render(); super.render();
this.element.attr({ href, target }); this.element.attr({ href, target });
if (el) { if (el) {
BI.createWidget(el, { createWidget(el, {
element: this, element: this,
}); });
} }
} }
} }

2
src/base/single/index.js

@ -8,4 +8,4 @@ export * from "./tip";
export * from "./label"; export * from "./label";
export * from "./input"; export * from "./input";
export * from "./editor"; export * from "./editor";
export * from "./button" export * from "./button";

24
src/base/single/tip/0.tip.js

@ -8,18 +8,20 @@
*/ */
import { Single } from "../0.single"; import { Single } from "../0.single";
import { extend } from "../../../core";
export class Tip extends Single { export class Tip extends Single {
_defaultConfig() { _defaultConfig() {
const conf = super._defaultConfig(arguments); const conf = super._defaultConfig(arguments);
return BI.extend(conf, {
_baseCls: (conf._baseCls || "") + " bi-tip", return extend(conf, {
zIndex: BI.zIndex_tip, _baseCls: `${conf._baseCls || ""} bi-tip`,
}); zIndex: BI.zIndex_tip,
} });
}
_init() { _init() {
super._init(); super._init();
this.element.css({ zIndex: this.options.zIndex }); this.element.css({ zIndex: this.options.zIndex });
} }
} }

2
src/base/single/tip/index.js

@ -1,3 +1,3 @@
export { Tip } from "./0.tip"; export { Tip } from "./0.tip";
export { Toast } from "./tip.toast"; export { Toast } from "./tip.toast";
export { Tooltip } from "./tip.tooltip"; export { Tooltip } from "./tip.tooltip";

181
src/base/single/tip/tip.toast.js

@ -6,7 +6,7 @@
* @extends BI.Tip * @extends BI.Tip
*/ */
import { shortcut } from "../../../core"; import { shortcut, extend, isPlainObject } from "../../../core";
import { Tip } from "./0.tip"; import { Tip } from "./0.tip";
@shortcut() @shortcut()
export class Toast extends Tip { export class Toast extends Tip {
@ -21,107 +21,106 @@ export class Toast extends Tip {
static xtype = "bi.toast"; static xtype = "bi.toast";
_defaultConfig() { _defaultConfig() {
return BI.extend(super._defaultConfig(arguments), { return extend(super._defaultConfig(arguments), {
extraCls: "bi-toast", extraCls: "bi-toast",
text: "", text: "",
level: "success", // success或warning level: "success", // success或warning
autoClose: true, autoClose: true,
closable: null, closable: null,
textHeight: 20, textHeight: 20,
vgap: 10, vgap: 10,
innerHgap: 4, innerHgap: 4,
hgap: 8, hgap: 8,
}); });
} }
render() { render() {
const { closable, level, autoClose, textHeight, text, hgap, vgap, innerHgap } = this.options; const { closable, level, autoClose, textHeight, text, hgap, vgap, innerHgap } = this.options;
const { closableMinWidth, minWidth, maxWidth, closableMaxWidth } = this._const; const { closableMinWidth, minWidth, maxWidth, closableMaxWidth } = this._const;
this.element.css({ this.element.css({
minWidth: BI.pixFormat(closable ? closableMinWidth : minWidth), minWidth: BI.pixFormat(closable ? closableMinWidth : minWidth),
maxWidth: BI.pixFormat(closable ? closableMaxWidth : maxWidth), maxWidth: BI.pixFormat(closable ? closableMaxWidth : maxWidth),
}); });
this.element.addClass("toast-" + level); this.element.addClass(`toast-${level}`);
function fn(e) { function fn(e) {
e.stopPropagation(); e.stopPropagation();
e.stopEvent(); e.stopEvent();
return false; return false;
} }
this.element.bind({ this.element.bind({
click: fn, click: fn,
mousedown: fn, mousedown: fn,
mouseup: fn, mouseup: fn,
mouseover: fn, mouseover: fn,
mouseenter: fn, mouseenter: fn,
mouseleave: fn, mouseleave: fn,
mousemove: fn, mousemove: fn,
}); });
let cls; let cls;
switch (level) { switch (level) {
case "success": case "success":
cls = "toast-success-font"; cls = "toast-success-font";
break; break;
case "error": case "error":
cls = "toast-error-font"; cls = "toast-error-font";
break; break;
case "warning": case "warning":
cls = "toast-warning-font"; cls = "toast-warning-font";
break; break;
case "loading": case "loading":
cls = "toast-loading-font anim-rotate"; cls = "toast-loading-font anim-rotate";
break; break;
case "normal": case "normal":
default: default:
cls = "toast-message-font"; cls = "toast-message-font";
break; break;
} }
function hasCloseIcon() { function hasCloseIcon() {
return closable === true || (closable === null && autoClose === false); return closable === true || (closable === null && autoClose === false);
} }
const items = [{ const items = [{
type: "bi.icon_label", type: "bi.icon_label",
cls: cls + " toast-icon", cls: `${cls} toast-icon`,
height: textHeight, height: textHeight,
}, { }, {
el: BI.isPlainObject(text) ? text : { el: isPlainObject(text) ? text : {
type: "bi.label", type: "bi.label",
whiteSpace: "normal", whiteSpace: "normal",
text: text, text,
textHeight: textHeight, textHeight,
textAlign: "left", textAlign: "left",
}, },
}]; }];
const columnSize = ["", "fill"]; const columnSize = ["", "fill"];
if (hasCloseIcon()) { if (hasCloseIcon()) {
items.push({ items.push({
type: "bi.icon_button", type: "bi.icon_button",
cls: "close-font toast-icon", cls: "close-font toast-icon",
handler: () => { handler: () => {
this.destroy(); this.destroy();
}, },
height: textHeight, height: textHeight,
}); });
columnSize.push(""); columnSize.push("");
} }
return { return {
type: "bi.horizontal", type: "bi.horizontal",
horizontalAlign: BI.HorizontalAlign.Stretch, horizontalAlign: BI.HorizontalAlign.Stretch,
items: items, items,
hgap: hgap, hgap,
vgap: vgap, vgap,
innerHgap: innerHgap, innerHgap,
columnSize: columnSize, columnSize,
}; };
} }
beforeDestroy() { beforeDestroy() {
this.fireEvent(Toast.EVENT_DESTORY); this.fireEvent(Toast.EVENT_DESTORY);
} }
} }

133
src/base/single/tip/tip.tooltip.js

@ -6,7 +6,7 @@
* @extends BI.Tip * @extends BI.Tip
*/ */
import { shortcut } from "../../../core"; import { shortcut, extend, createWidget, map } from "../../../core";
import { Tip } from "./0.tip"; import { Tip } from "./0.tip";
@shortcut() @shortcut()
export class Tooltip extends Tip { export class Tooltip extends Tip {
@ -17,77 +17,76 @@ export class Tooltip extends Tip {
static xtype = "bi.tooltip"; static xtype = "bi.tooltip";
_defaultConfig() { _defaultConfig() {
return BI.extend(super._defaultConfig(arguments), { return extend(super._defaultConfig(arguments), {
extraCls: "bi-tooltip", extraCls: "bi-tooltip",
text: "", text: "",
level: "success", // success或warning level: "success", // success或warning
stopEvent: false, stopEvent: false,
stopPropagation: false, stopPropagation: false,
textAlign: "left", textAlign: "left",
}); });
} }
render () { render () {
const { level, stopPropagation, stopEvent, text, textAlign } = this.options; const { level, stopPropagation, stopEvent, text, textAlign } = this.options;
this.element.addClass("tooltip-" + level); this.element.addClass(`tooltip-${level}`);
function fn(e) { function fn(e) {
stopPropagation && e.stopPropagation(); stopPropagation && e.stopPropagation();
stopEvent && e.stopEvent(); stopEvent && e.stopEvent();
} }
this.element.bind({ this.element.bind({
click: fn, click: fn,
mousedown: fn, mousedown: fn,
mouseup: fn, mouseup: fn,
mouseover: fn, mouseover: fn,
mouseenter: fn, mouseenter: fn,
mouseleave: fn, mouseleave: fn,
mousemove: fn, mousemove: fn,
}); });
const texts = (text + "").split("\n");
if (texts.length > 1) {
BI.createWidget({
type: "bi.vertical",
element: this,
hgap: this._const.hgap,
innerVgap: this._const.vgap,
items: BI.map(texts, (i, text) => {
return {
type: "bi.label",
textAlign: textAlign,
whiteSpace: "normal",
text: text,
textHeight: 18,
title: null,
};
}),
});
} else {
this.text = BI.createWidget({
type: "bi.label",
element: this,
textAlign: textAlign,
whiteSpace: "normal",
text: text,
title: null,
textHeight: 18,
hgap: this._const.hgap,
vgap: this._const.vgap,
});
}
}
setWidth(width) { const texts = (`${text}`).split("\n");
this.element.width(BI.pixFormat(width - 2 * this._const.hgap)); if (texts.length > 1) {
} createWidget({
type: "bi.vertical",
element: this,
hgap: this._const.hgap,
innerVgap: this._const.vgap,
items: map(texts, (i, text) => {
return {
type: "bi.label",
textAlign,
whiteSpace: "normal",
text,
textHeight: 18,
title: null,
};
}),
});
} else {
this.text = createWidget({
type: "bi.label",
element: this,
textAlign,
whiteSpace: "normal",
text,
title: null,
textHeight: 18,
hgap: this._const.hgap,
vgap: this._const.vgap,
});
}
}
setText(text) { setWidth(width) {
this.text && this.text.setText(text); this.element.width(BI.pixFormat(width - 2 * this._const.hgap));
} }
setLevel(level) { setText(text) {
this.element.removeClass("tooltip-success").removeClass("tooltip-warning"); this.text && this.text.setText(text);
this.element.addClass("tooltip-" + level); }
}
setLevel(level) {
this.element.removeClass("tooltip-success").removeClass("tooltip-warning");
this.element.addClass(`tooltip-${level}`);
}
} }

137
src/base/tree/customtree.js

@ -6,9 +6,15 @@
* @class BI.CustomTree * @class BI.CustomTree
* @extends BI.Single * @extends BI.Single
*/ */
BI.CustomTree = BI.inherit(BI.Widget, { import { Widget, shortcut, extend, emptyFn, Tree, each, isNotEmptyArray, deepClone, stripEL, isWidget,
_defaultConfig: function () { clone, isNotNull, isNull, createWidget, Controller } from "../../core";
return BI.extend(BI.CustomTree.superclass._defaultConfig.apply(this, arguments), { @shortcut()
export class CustomTree extends Widget {
static xtype = "bi.custom_tree";
static EVENT_CHANGE = "EVENT_CHANGE";
_defaultConfig() {
return extend(super._defaultConfig(...arguments), {
baseCls: "bi-custom-tree", baseCls: "bi-custom-tree",
expander: { expander: {
el: {}, el: {},
@ -18,7 +24,7 @@ BI.CustomTree = BI.inherit(BI.Widget, {
}, },
items: [], items: [],
itemsCreator: BI.emptyFn, itemsCreator: emptyFn,
el: { el: {
type: "bi.button_tree", type: "bi.button_tree",
@ -28,50 +34,49 @@ BI.CustomTree = BI.inherit(BI.Widget, {
}], }],
}, },
}); });
}, }
_init() {
_init: function () { super._init(...arguments);
BI.CustomTree.superclass._init.apply(this, arguments);
this.initTree(this.options.items); this.initTree(this.options.items);
}, }
_formatItems: function (nodes) { _formatItems(nodes) {
var self = this, o = this.options; const { expander, itemsCreator } = this.options;
nodes = BI.Tree.transformToTreeFormat(nodes); nodes = Tree.transformToTreeFormat(nodes);
var items = []; const items = [];
BI.each(nodes, function (i, node) { each(nodes, (i, node) => {
if (BI.isNotEmptyArray(node.children) || node.isParent === true) { if (isNotEmptyArray(node.children) || node.isParent === true) {
var item = BI.extend({ const item = extend({
type: "bi.expander", type: "bi.expander",
el: { el: {
value: node.value, value: node.value,
}, },
popup: { type: "bi.custom_tree" }, popup: { type: "bi.custom_tree" },
}, BI.deepClone(o.expander), { }, deepClone(expander), {
id: node.id, id: node.id,
pId: node.pId, pId: node.pId,
}); });
var el = BI.stripEL(node); let el = stripEL(node);
if (!BI.isWidget(el)) { if (!isWidget(el)) {
el = BI.clone(el); el = clone(el);
delete el.children; delete el.children;
BI.extend(item.el, el); extend(item.el, el);
} else { } else {
item.el = el; item.el = el;
} }
item.popup.expander = BI.deepClone(o.expander); item.popup.expander = deepClone(expander);
item.items = item.popup.items = node.children; item.items = item.popup.items = node.children;
item.itemsCreator = item.popup.itemsCreator = function (op) { item.itemsCreator = item.popup.itemsCreator = (op, ...arg) => {
if (BI.isNotNull(op.node)) {// 从子节点传过来的itemsCreator直接向上传递 if (isNotNull(op.node)) {// 从子节点传过来的itemsCreator直接向上传递
return o.itemsCreator.apply(self, arguments); return itemsCreator(op, ...arg);
} }
var args = Array.prototype.slice.call(arguments, 0); const args = Array.prototype.slice.call([op, ...arg], 0);
args[0].node = node; args[0].node = node;
return o.itemsCreator.apply(self, args); return itemsCreator.apply(this, args);
}; };
BI.isNull(item.popup.el) && (item.popup.el = BI.deepClone(o.el)); isNull(item.popup.el) && (item.popup.el = deepClone(this.options.el));
items.push(item); items.push(item);
} else { } else {
items.push(node); items.push(node);
@ -79,72 +84,68 @@ BI.CustomTree = BI.inherit(BI.Widget, {
}); });
return items; return items;
}, }
// 构造树结构, // 构造树结构,
initTree: function (nodes) { initTree(nodes) {
var self = this, o = this.options; const { el, itemsCreator, value } = this.options;
this.tree = BI.createWidget(o.el, { this.tree = createWidget(el, {
element: this, element: this,
items: this._formatItems(nodes), items: this._formatItems(nodes),
itemsCreator: function (op, callback) { itemsCreator: (op, callback) => {
o.itemsCreator.apply(this, [op, function (items) { itemsCreator.apply(this, [op, items => {
var args = Array.prototype.slice.call(arguments, 0); const args = Array.prototype.slice.call(arguments, 0);
args[0] = self._formatItems(items); args[0] = this._formatItems(items);
callback.apply(null, args); callback(...args);
}]); }]);
}, },
value: o.value, value,
}); });
this.tree.on(BI.Controller.EVENT_CHANGE, function (type, val, obj) { this.tree.on(Controller.EVENT_CHANGE, (type, val, obj, ...args) => {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); this.fireEvent(Controller.EVENT_CHANGE, type, val, obj, ...args);
if (type === BI.Events.CLICK) { if (type === BI.Events.CLICK) {
self.fireEvent(BI.CustomTree.EVENT_CHANGE, val, obj); this.fireEvent(CustomTree.EVENT_CHANGE, val, obj);
} }
}); });
}, }
// 生成树方法 // 生成树方法
stroke: function (nodes) { stroke(nodes) {
this.populate.apply(this, arguments); this.populate(...arguments);
}, }
populate: function (nodes) { populate(nodes) {
var args = Array.prototype.slice.call(arguments, 0); const args = Array.prototype.slice.call(arguments, 0);
if (arguments.length > 0) { if (arguments.length > 0) {
args[0] = this._formatItems(nodes); args[0] = this._formatItems(nodes);
} }
this.tree.populate.apply(this.tree, args); this.tree.populate(...args);
}, }
setValue: function (v) { setValue(v) {
this.tree && this.tree.setValue(v); this.tree && this.tree.setValue(v);
}, }
getValue: function () { getValue() {
return this.tree ? this.tree.getValue() : []; return this.tree ? this.tree.getValue() : [];
}, }
getAllButtons: function () { getAllButtons() {
return this.tree ? this.tree.getAllButtons() : []; return this.tree ? this.tree.getAllButtons() : [];
}, }
getAllLeaves: function () { getAllLeaves() {
return this.tree ? this.tree.getAllLeaves() : []; return this.tree ? this.tree.getAllLeaves() : [];
}, }
getNodeById: function (id) { getNodeById(id) {
return this.tree && this.tree.getNodeById(id); return this.tree && this.tree.getNodeById(id);
}, }
getNodeByValue: function (id) { getNodeByValue(id) {
return this.tree && this.tree.getNodeByValue(id); return this.tree && this.tree.getNodeByValue(id);
}, }
empty: function () { empty() {
this.tree.empty(); this.tree.empty();
}, }
}); }
BI.CustomTree.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.custom_tree", BI.CustomTree);

6
src/core/index.js

@ -7,10 +7,10 @@ import * as behavior from "./behavior";
import * as controllers from "./controller"; import * as controllers from "./controller";
import * as func from "./func"; import * as func from "./func";
import * as structure from "./structure"; import * as structure from "./structure";
import {StyleLoaderManager} from "./loader/loader.style"; import { StyleLoaderManager } from "./loader/loader.style";
import "./h"; import "./h";
import {ShowListener} from "./listener/listener.show"; import { ShowListener } from "./listener/listener.show";
import {shortcut} from "./decorator"; import { shortcut } from "./decorator";
export * from "./2.base"; export * from "./2.base";
export * from "./3.ob"; export * from "./3.ob";

Loading…
Cancel
Save