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