diff --git a/demo/js/west.js b/demo/js/west.js index d4cc9d59b..d2cd70109 100644 --- a/demo/js/west.js +++ b/demo/js/west.js @@ -9,6 +9,10 @@ Demo.West = BI.inherit(BI.Widget, { render: function () { var self = this; + + + var selectedId = BI.Router.$router.currentRoute.params?.componentId; + return { type: "bi.vtape", items: [{ @@ -60,7 +64,7 @@ Demo.West = BI.inherit(BI.Widget, { self.fireEvent(Demo.West.EVENT_VALUE_CHANGE, v); } }], - value: Demo.showIndex, + value: selectedId || Demo.showIndex, items: Demo.CONFIG, ref: function (ref) { self.tree = ref; @@ -70,4 +74,4 @@ Demo.West = BI.inherit(BI.Widget, { } }); Demo.West.EVENT_VALUE_CHANGE = "EVENT_VALUE_CHANGE"; -BI.shortcut("demo.west", Demo.West); \ No newline at end of file +BI.shortcut("demo.west", Demo.West); diff --git a/src/base/combination/bubble.js b/src/base/combination/bubble.js index 1af43b79c..7b5f57736 100644 --- a/src/base/combination/bubble.js +++ b/src/base/combination/bubble.js @@ -106,7 +106,8 @@ _initPullDownAction: function () { var self = this, o = this.options; var evs = (this.options.trigger || "").split(","); - function st (e) { + + function st(e) { if (o.stopEvent) { e.stopEvent(); } @@ -268,7 +269,7 @@ BI.createWidget({ type: "bi.vertical", scrolly: false, - element: this.options.container || this, + element: BI.isFunction(this.options.container) ? this.options.container() : (this.options.container || this), items: [ { el: this.popupView } ], @@ -344,14 +345,16 @@ if (this.popper) { this.popper.destroy(); } - var modifiers = [{ - name: "offset", - options: { - offset: function () { - return [o.adjustXOffset, (o.showArrow ? 12 : 0) + (o.adjustYOffset + o.adjustLength)]; + var modifiers = [ + { + name: "offset", + options: { + offset: function () { + return [o.adjustXOffset, (o.showArrow ? 12 : 0) + (o.adjustYOffset + o.adjustLength)]; + }, }, - }, - }]; + } + ]; if (this.options.showArrow) { modifiers.push({ name: "arrow", diff --git a/src/base/combination/combo.js b/src/base/combination/combo.js index 7abbf77eb..02f838877 100644 --- a/src/base/combination/combo.js +++ b/src/base/combination/combo.js @@ -38,6 +38,7 @@ adjustLength: 0, // 调整的距离 adjustXOffset: 0, adjustYOffset: 0, + supportCSSTransform: false, hideChecker: BI.emptyFn, offsetStyle: "left", // left,right,center el: {}, @@ -218,46 +219,47 @@ }, }, } : this.combo; + var positionRelativeElement = o.supportCSSTransform ? BI.DOM.getPositionRelativeContainingBlock(BI.Widget._renderEngine.createElement(BI.isFunction(o.container) ? o.container() : o.container)[0]) : null; switch (o.direction) { case "bottom": case "bottom,right": - p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset, (o.adjustYOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.isNeedAdjustHeight, ["bottom", "top", "right", "left"], o.offsetStyle); + p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset, (o.adjustYOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.isNeedAdjustHeight, ["bottom", "top", "right", "left"], o.offsetStyle, positionRelativeElement); break; case "top": case "top,right": - p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset, (o.adjustYOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.isNeedAdjustHeight, ["top", "bottom", "right", "left"], o.offsetStyle); + p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset, (o.adjustYOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.isNeedAdjustHeight, ["top", "bottom", "right", "left"], o.offsetStyle, positionRelativeElement); break; case "left": case "left,bottom": - p = BI.DOM.getComboPosition(combo, this.popupView, (o.adjustXOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.adjustYOffset, o.isNeedAdjustHeight, ["left", "right", "bottom", "top"], o.offsetStyle); + p = BI.DOM.getComboPosition(combo, this.popupView, (o.adjustXOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.adjustYOffset, o.isNeedAdjustHeight, ["left", "right", "bottom", "top"], o.offsetStyle, positionRelativeElement); break; case "right": case "right,bottom": - p = BI.DOM.getComboPosition(combo, this.popupView, (o.adjustXOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.adjustYOffset, o.isNeedAdjustHeight, ["right", "left", "bottom", "top"], o.offsetStyle); + p = BI.DOM.getComboPosition(combo, this.popupView, (o.adjustXOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.adjustYOffset, o.isNeedAdjustHeight, ["right", "left", "bottom", "top"], o.offsetStyle, positionRelativeElement); break; case "top,left": - p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset, (o.adjustYOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.isNeedAdjustHeight, ["top", "bottom", "left", "right"], o.offsetStyle); + p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset, (o.adjustYOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.isNeedAdjustHeight, ["top", "bottom", "left", "right"], o.offsetStyle, positionRelativeElement); break; case "bottom,left": - p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset, (o.adjustYOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.isNeedAdjustHeight, ["bottom", "top", "left", "right"], o.offsetStyle); + p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset, (o.adjustYOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.isNeedAdjustHeight, ["bottom", "top", "left", "right"], o.offsetStyle, positionRelativeElement); break; case "left,top": - p = BI.DOM.getComboPosition(combo, this.popupView, (o.adjustXOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.adjustYOffset, o.isNeedAdjustHeight, ["left", "right", "top", "bottom"], o.offsetStyle); + p = BI.DOM.getComboPosition(combo, this.popupView, (o.adjustXOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.adjustYOffset, o.isNeedAdjustHeight, ["left", "right", "top", "bottom"], o.offsetStyle, positionRelativeElement); break; case "right,top": - p = BI.DOM.getComboPosition(combo, this.popupView, (o.adjustXOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.adjustYOffset, o.isNeedAdjustHeight, ["right", "left", "top", "bottom"], o.offsetStyle); + p = BI.DOM.getComboPosition(combo, this.popupView, (o.adjustXOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.adjustYOffset, o.isNeedAdjustHeight, ["right", "left", "top", "bottom"], o.offsetStyle, positionRelativeElement); break; case "right,innerRight": - p = BI.DOM.getComboPosition(combo, this.popupView, (o.adjustXOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.adjustYOffset, o.isNeedAdjustHeight, ["right", "left", "innerRight", "innerLeft", "bottom", "top"], o.offsetStyle); + p = BI.DOM.getComboPosition(combo, this.popupView, (o.adjustXOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.adjustYOffset, o.isNeedAdjustHeight, ["right", "left", "innerRight", "innerLeft", "bottom", "top"], o.offsetStyle, positionRelativeElement); break; case "right,innerLeft": - p = BI.DOM.getComboPosition(combo, this.popupView, (o.adjustXOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.adjustYOffset, o.isNeedAdjustHeight, ["right", "left", "innerLeft", "innerRight", "bottom", "top"], o.offsetStyle); + p = BI.DOM.getComboPosition(combo, this.popupView, (o.adjustXOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.adjustYOffset, o.isNeedAdjustHeight, ["right", "left", "innerLeft", "innerRight", "bottom", "top"], o.offsetStyle, positionRelativeElement); break; case "innerRight": - p = BI.DOM.getComboPosition(combo, this.popupView, (o.adjustXOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.adjustYOffset, o.isNeedAdjustHeight, ["innerRight", "innerLeft", "right", "left", "bottom", "top"], o.offsetStyle); + p = BI.DOM.getComboPosition(combo, this.popupView, (o.adjustXOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.adjustYOffset, o.isNeedAdjustHeight, ["innerRight", "innerLeft", "right", "left", "bottom", "top"], o.offsetStyle, positionRelativeElement); break; case "innerLeft": - p = BI.DOM.getComboPosition(combo, this.popupView, (o.adjustXOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.adjustYOffset, o.isNeedAdjustHeight, ["innerLeft", "innerRight", "left", "right", "bottom", "top"], o.offsetStyle); + p = BI.DOM.getComboPosition(combo, this.popupView, (o.adjustXOffset + o.adjustLength) + (o.showArrow ? this._const.TRIANGLE_LENGTH : 0), o.adjustYOffset, o.isNeedAdjustHeight, ["innerLeft", "innerRight", "left", "right", "bottom", "top"], o.offsetStyle, positionRelativeElement); break; case "top,custom": case "custom,top": @@ -290,6 +292,7 @@ if ("adaptHeight" in p) { this.resetListHeight(p.adaptHeight); } + var width = this.combo.element.outerWidth(); var height = this.combo.element.outerHeight(); this.popupView.setDirection && this.popupView.setDirection(p.dir, { @@ -300,6 +303,18 @@ adjustYOffset: o.adjustYOffset, offset: this.combo.element.offset(), }); + + if (o.supportCSSTransform) { + + var positonedRect = positionRelativeElement.getBoundingClientRect(); + + var scaleX = positonedRect.width / positionRelativeElement.offsetWidth; + var scaleY = positonedRect.height / positionRelativeElement.offsetHeight; + + p.top && (p.top = p.top / scaleY); + p.left && (p.left = p.left / scaleX); + } + if ("left" in p) { this.popupView.element.css({ left: p.left, diff --git a/src/core/platform/web/dom.js b/src/core/platform/web/dom.js index 05757959d..bab3d7042 100644 --- a/src/core/platform/web/dom.js +++ b/src/core/platform/web/dom.js @@ -56,7 +56,7 @@ preloadImages: function (srcArray, onload) { var count = 0, images = []; - function complete () { + function complete() { count++; if (count >= srcArray.length) { onload(); @@ -151,9 +151,15 @@ BI.extend(BI.DOM, { - getLeftPosition: function (combo, popup, extraWidth) { + getLeftPosition: function (combo, popup, extraWidth, container) { + var el = combo.element; + var popupEl = popup.element; + var elRect = el[0].getBoundingClientRect(); + var popupElRect = popupEl[0].getBoundingClientRect(); + var containerRect = container ? container.getBoundingClientRect() : { left: 0 }; + return { - left: combo.element.offset().left - popup.element.outerWidth() - (extraWidth || 0) + left: elRect.left - containerRect.left - popupElRect.width - (extraWidth || 0) }; }, @@ -163,10 +169,13 @@ }; }, - getRightPosition: function (combo, popup, extraWidth) { + getRightPosition: function (combo, popup, extraWidth, container) { var el = combo.element; + var elRect = el[0].getBoundingClientRect(); + var containerRect = container ? container.getBoundingClientRect() : { left: 0 }; + return { - left: el.offset().left + el.outerWidth() + (extraWidth || 0) + left: elRect.left + elRect.width - containerRect.left + (extraWidth || 0) }; }, @@ -177,16 +186,25 @@ }; }, - getTopPosition: function (combo, popup, extraHeight) { + getTopPosition: function (combo, popup, extraHeight, container) { + var el = combo.element; + var popupEl = popup.element; + var elRect = el[0].getBoundingClientRect(); + var popupElRect = popupEl[0].getBoundingClientRect(); + var containerRect = container ? container.getBoundingClientRect() : { top: 0 }; + return { - top: combo.element.offset().top - popup.element.outerHeight() - (extraHeight || 0) + top: elRect.top - containerRect.top - popupElRect.height - (extraHeight || 0) }; }, - getBottomPosition: function (combo, popup, extraHeight) { + getBottomPosition: function (combo, popup, extraHeight, container) { var el = combo.element; + var elRect = el[0].getBoundingClientRect(); + var containerRect = container ? container.getBoundingClientRect() : { top: 0 }; + return { - top: el.offset().top + el.outerHeight() + (extraHeight || 0) + top: elRect.top - containerRect.top + elRect.height + (extraHeight || 0) }; }, @@ -230,18 +248,19 @@ return windowBounds.height - combo.element.offset().top - combo.element.bounds().height >= combo.element.offset().top; }, - _getLeftAlignPosition: function (combo, popup, extraWidth) { + _getLeftAlignPosition: function (combo, popup, extraWidth, container) { var viewBounds = popup.element.bounds(), windowBounds = BI.Widget._renderEngine.createElement("body").bounds(); - var left = combo.element.offset().left + extraWidth; + var left = combo.element.offset().left - (container ? container.getBoundingClientRect().left : 0) + extraWidth; + if (left + viewBounds.width > windowBounds.width) { left = windowBounds.width - viewBounds.width; } return left; }, - getLeftAlignPosition: function (combo, popup, extraWidth) { - var left = this._getLeftAlignPosition(combo, popup, extraWidth); + getLeftAlignPosition: function (combo, popup, extraWidth, container) { + var left = this._getLeftAlignPosition(combo, popup, extraWidth, container); var dir = ""; // 如果放不下,优先使用RightAlign, 如果RightAlign也放不下, 再使用left=0 if (left < 0) { @@ -297,13 +316,14 @@ }; }, - getTopAlignPosition: function (combo, popup, extraHeight, needAdaptHeight) { + getTopAlignPosition: function (combo, popup, extraHeight, needAdaptHeight, container) { var comboOffset = combo.element.offset(); var comboBounds = combo.element.bounds(), popupBounds = popup.element.bounds(), - windowBounds = BI.Widget._renderEngine.createElement("body").bounds(); + windowBounds = BI.Widget._renderEngine.createElement("body").bounds(), + containerBounds = container ? container.getBoundingClientRect() : { top: 0 }; var top, adaptHeight, dir; if (BI.DOM.isBottomSpaceEnough(combo, popup, -1 * comboBounds.height + extraHeight)) { - top = comboOffset.top + extraHeight; + top = comboOffset.top - containerBounds.top + extraHeight; } else if (needAdaptHeight) { top = comboOffset.top + extraHeight; adaptHeight = windowBounds.height - top; @@ -353,13 +373,15 @@ }; }, - getBottomAlignPosition: function (combo, popup, extraHeight, needAdaptHeight) { + getBottomAlignPosition: function (combo, popup, extraHeight, needAdaptHeight, container) { var comboOffset = combo.element.offset(); - var comboBounds = combo.element.bounds(), popupBounds = popup.element.bounds(), - windowBounds = BI.Widget._renderEngine.createElement("body").bounds(); + var comboBounds = combo.element[0].getBoundingClientRect(), + popupBounds = popup.element[0].getBoundingClientRect(), + windowBounds = BI.Widget._renderEngine.createElement("body").bounds(), + containerBounds = container ? container.getBoundingClientRect() : { top: 0 }; var top, adaptHeight, dir; if (BI.DOM.isTopSpaceEnough(combo, popup, -1 * comboBounds.height + extraHeight)) { - top = comboOffset.top + comboBounds.height - popupBounds.height - extraHeight; + top = comboOffset.top + comboBounds.height - containerBounds.top - popupBounds.height; } else if (needAdaptHeight) { top = 0; adaptHeight = comboOffset.top + comboBounds.height - extraHeight; @@ -446,7 +468,7 @@ }; }, - getComboPositionByDirections: function (combo, popup, extraWidth, extraHeight, needAdaptHeight, directions) { + getComboPositionByDirections: function (combo, popup, extraWidth, extraHeight, needAdaptHeight, directions, container) { extraWidth || (extraWidth = 0); extraHeight || (extraHeight = 0); var i, direct; @@ -483,11 +505,11 @@ if (!isNeedAdaptHeight) { var tW = tbFirst ? extraHeight : extraWidth, tH = tbFirst ? 0 : extraHeight; if (BI.DOM.isLeftSpaceEnough(combo, popup, tW)) { - left = BI.DOM.getLeftPosition(combo, popup, tW).left; + left = BI.DOM.getLeftPosition(combo, popup, tW, container).left; if (topBottom[0] === "bottom") { - pos = BI.DOM.getTopAlignPosition(combo, popup, tH, needAdaptHeight); + pos = BI.DOM.getTopAlignPosition(combo, popup, tH, needAdaptHeight, container); } else { - pos = BI.DOM.getBottomAlignPosition(combo, popup, tH, needAdaptHeight); + pos = BI.DOM.getBottomAlignPosition(combo, popup, tH, needAdaptHeight, container); } pos.dir = "left," + pos.dir; if (tbFirst) { @@ -503,11 +525,11 @@ if (!isNeedAdaptHeight) { var tW = tbFirst ? extraHeight : extraWidth, tH = tbFirst ? extraWidth : extraHeight; if (BI.DOM.isRightSpaceEnough(combo, popup, tW)) { - left = BI.DOM.getRightPosition(combo, popup, tW).left; + left = BI.DOM.getRightPosition(combo, popup, tW, container).left; if (topBottom[0] === "bottom") { - pos = BI.DOM.getTopAlignPosition(combo, popup, tH, needAdaptHeight); + pos = BI.DOM.getTopAlignPosition(combo, popup, tH, needAdaptHeight, container); } else { - pos = BI.DOM.getBottomAlignPosition(combo, popup, tH, needAdaptHeight); + pos = BI.DOM.getBottomAlignPosition(combo, popup, tH, needAdaptHeight, container); } pos.dir = "right," + pos.dir; if (tbFirst) { @@ -522,11 +544,11 @@ case "top": var tW = lrFirst ? extraHeight : extraWidth, tH = lrFirst ? extraWidth : extraHeight; if (BI.DOM.isTopSpaceEnough(combo, popup, tH)) { - top = BI.DOM.getTopPosition(combo, popup, tH).top; + top = BI.DOM.getTopPosition(combo, popup, tH, container).top; if (leftRight[0] === "right") { - pos = BI.DOM.getLeftAlignPosition(combo, popup, tW, needAdaptHeight); + pos = BI.DOM.getLeftAlignPosition(combo, popup, tW, container); } else { - pos = BI.DOM.getRightAlignPosition(combo, popup, tW); + pos = BI.DOM.getRightAlignPosition(combo, popup, tW, container); } pos.dir = "top," + pos.dir; if (lrFirst) { @@ -543,11 +565,11 @@ case "bottom": var tW = lrFirst ? extraHeight : extraWidth, tH = lrFirst ? extraWidth : extraHeight; if (BI.DOM.isBottomSpaceEnough(combo, popup, tH)) { - top = BI.DOM.getBottomPosition(combo, popup, tH).top; + top = BI.DOM.getBottomPosition(combo, popup, tH, container).top; if (leftRight[0] === "right") { - pos = BI.DOM.getLeftAlignPosition(combo, popup, tW, needAdaptHeight); + pos = BI.DOM.getLeftAlignPosition(combo, popup, tW, container); } else { - pos = BI.DOM.getRightAlignPosition(combo, popup, tW); + pos = BI.DOM.getRightAlignPosition(combo, popup, tW, container); } pos.dir = "bottom," + pos.dir; if (lrFirst) { @@ -648,13 +670,13 @@ }, - getComboPosition: function (combo, popup, extraWidth, extraHeight, needAdaptHeight, directions, offsetStyle) { + getComboPosition: function (combo, popup, extraWidth, extraHeight, needAdaptHeight, directions, offsetStyle, container) { extraWidth || (extraWidth = 0); extraHeight || (extraHeight = 0); var bodyHeight = BI.Widget._renderEngine.createElement("body").bounds().height - extraHeight; var maxHeight = Math.min(popup.attr("maxHeight") || bodyHeight, bodyHeight); popup.resetHeight && popup.resetHeight(maxHeight); - var position = BI.DOM.getComboPositionByDirections(combo, popup, extraWidth, extraHeight, needAdaptHeight, directions || ["bottom", "top", "right", "left"]); + var position = BI.DOM.getComboPositionByDirections(combo, popup, extraWidth, extraHeight, needAdaptHeight, directions || ["bottom", "top", "right", "left"], container); switch (offsetStyle) { case "center": if (position.change) { @@ -679,6 +701,32 @@ popup.resetHeight && popup.resetHeight(Math.min(bodyHeight - position.top, maxHeight)); } return position; - } + }, + + /** + * 获取position:fixed相对定位的元素 + */ + getPositionRelativeContainingBlock: function (element) { + if (['html', 'body', '#document'].indexOf((element.nodeName || '').toLowerCase()) >= 0) { + // $FlowFixMe[incompatible-return]: assume body is always available + return element.ownerDocument.body; + } + + function isExcept(node) { + var _computedStyle = getComputedStyle(node); + var transform = _computedStyle.transform; + var perspective = _computedStyle.perspective; + var filter = _computedStyle.filter; + var willChange = _computedStyle["will-change"]; + + return [transform, perspective, filter].some(value => value !== 'none') || (willChange === "transform"); + } + + if (isExcept(element)) { + return element; + } + + return BI.DOM.getPositionRelativeContainingBlock(element.parentNode); + }, }); })();