diff --git a/package.json b/package.json index 6f67e4229..1e9064583 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@babel/polyfill": "7.6.0", "@fui/babel-preset-fineui": "^2.0.0", "@fui/eslint-plugin": "^1.0.19", + "@juggle/resize-observer": "^3.4.0", "@types/node": "15.6.1", "@typescript-eslint/eslint-plugin": "2.33.0", "@typescript-eslint/parser": "2.33.0", @@ -91,4 +92,4 @@ "@types/yargs": "17.0.13", "yargs": "17.6.2" } -} \ No newline at end of file +} diff --git a/src/core/platform/web/config.js b/src/core/platform/web/config.js index 66440ccf8..e4812bd7b 100644 --- a/src/core/platform/web/config.js +++ b/src/core/platform/web/config.js @@ -1,286 +1,315 @@ +import { Plugin } from "../../6.plugin"; + // 工程配置 -!(function () { - // 注册布局 - // adapt类布局优先级规则 - // 1、支持flex的浏览器下使用flex布局 - // 2、不支持flex的浏览器下使用inline布局 - // 3、当列宽既需要自动列宽又需要自适应列宽时,inline布局也处理不了了。当横向出滚动条时使用table布局,不出滚动条时使用float布局 - var _isSupportFlex, _isSupportGrid; - var isSupportFlex = function () { - if (_isSupportFlex == null) { - _isSupportFlex = !!(BI.isSupportCss3 && BI.isSupportCss3("flex")); - } - return _isSupportFlex; - }; - var isSupportGrid = function () { - if (_isSupportGrid == null) { - _isSupportGrid = !!(BI.isSupportCss3 && BI.isSupportCss3("grid")); - } - return _isSupportGrid; - }; - // 判断浏览器是否支持sticky 属性 - var isSupportSticky = (function () { - var vendorList = ["", "-webkit-", "-ms-", "-moz-", "-o-"], - vendorListLength = vendorList.length, - stickyElement = document.createElement("div"); - for (var i = 0; i < vendorListLength; i++) { - stickyElement.style.position = vendorList[i] + "sticky"; - if (stickyElement.style.position !== "") { - return true; - } - } - return false; - })(); - BI.Plugin.configWidget("bi.horizontal", function (ob) { - var supportFlex = isSupportFlex(); - // // 在横向自适应场景下我们需要使用table的自适应撑出滚动条的特性(flex处理不了这种情况) - // // 主要出现在center_adapt或者horizontal_adapt的场景,或者主动设置horizontalAlign的场景 - // if (ob.horizontalAlign === BI.HorizontalAlign.Center || ob.horizontalAlign === BI.HorizontalAlign.Stretch) { - // return BI.extend({}, ob, {type: "bi.table_adapt"}); - // } - if (supportFlex) { - return BI.extend({}, ob, { type: "bi.flex_horizontal" }); - } - return BI.extend({ - scrollx: true - }, ob, { type: "bi.inline" }); - }); - BI.Plugin.configWidget("bi.vertical", function (ob) { - if (ob.horizontalAlign === BI.HorizontalAlign.Left || ob.horizontalAlign === BI.HorizontalAlign.Right) { - if (isSupportFlex()) { - return BI.extend({}, ob, { type: "bi.flex_vertical" }); - } - return BI.extend({}, ob, { - horizontalAlign: BI.HorizontalAlign.Stretch, - type: "bi.vertical", - items: BI.map(ob.items, function (i, item) { - return { - type: "bi.inline", - horizontalAlign: ob.horizontalAlign, - items: [item] - }; - }) - }); - } - if (ob.verticalAlign === BI.VerticalAlign.Stretch) { - if (isSupportFlex()) { - return BI.extend({ - horizontalAlign: BI.HorizontalAlign.Stretch, - }, ob, { type: "bi.flex_vertical" }); - } - } - return ob; - }); - BI.Plugin.configWidget("bi.inline", function (ob) { - // 当列宽既需要自动列宽又需要自适应列宽时,inline布局也处理不了了,降级table处理吧 - var hasAutoAndFillColumnSize = false; - if (ob.columnSize && ob.columnSize.length > 0) { - if ((ob.columnSize.indexOf("") >= 0 || ob.columnSize.indexOf("auto") >= 0) && ob.columnSize.indexOf("fill") >= 0) { - hasAutoAndFillColumnSize = true; - } - } else { - var hasAuto = false, hasFill = false; - BI.each(ob.items, function (i, item) { - if (item.width === "fill") { - hasFill = true; - } else if (BI.isNull(item.width) || item.width === "" || item.width === "auto") { - hasAuto = true; - } - }); - hasAutoAndFillColumnSize = hasAuto && hasFill; - } +// 注册布局 +// adapt类布局优先级规则 +// 1、支持flex的浏览器下使用flex布局 +// 2、不支持flex的浏览器下使用inline布局 +// 3、当列宽既需要自动列宽又需要自适应列宽时,inline布局也处理不了了。当横向出滚动条时使用table布局,不出滚动条时使用float布局 +let _isSupportFlex, _isSupportGrid; - if (hasAutoAndFillColumnSize) { - // 宽度是不是受限 - if ((ob.scrollable !== true && ob.scrollx !== true) || ob.horizontalAlign === BI.HorizontalAlign.Stretch) { - return BI.extend({ - verticalAlign: BI.VerticalAlign.Top - }, ob, { type: "bi.horizontal_float_fill" }); - } - return BI.extend({ - horizontalAlign: BI.HorizontalAlign.Stretch - }, ob, { type: "bi.table_adapt" }); - } - if (BI.Providers.getProvider("bi.provider.system").getResponsiveMode()) { - return BI.extend({}, ob, { type: "bi.responsive_inline" }); - } - return ob; - }); - BI.Plugin.configWidget("bi.center_adapt", function (ob) { - var supportFlex = isSupportFlex(); - // var isAdapt = !ob.horizontalAlign || ob.horizontalAlign === BI.HorizontalAlign.Center || ob.horizontalAlign === BI.HorizontalAlign.Stretch; - // if (!isAdapt || justOneItem) { - if (supportFlex) { - return BI.extend({}, ob, { type: "bi.flex_center_adapt" }); - } - return BI.extend({}, ob, { type: "bi.inline_center_adapt" }); - // } - // return ob; - }); - BI.Plugin.configWidget("bi.vertical_adapt", function (ob) { - var supportFlex = isSupportFlex(); - // var isAdapt = ob.horizontalAlign === BI.HorizontalAlign.Center || ob.horizontalAlign === BI.HorizontalAlign.Stretch; - // if (!isAdapt || justOneItem) { - if (supportFlex) { - return BI.extend({}, ob, { type: "bi.flex_vertical_center_adapt" }); - } - return BI.extend({}, ob, { type: "bi.inline_vertical_adapt" }); - // } - // return ob; - }); - BI.Plugin.configWidget("bi.horizontal_adapt", function (ob) { - var justOneItem = (ob.items && ob.items.length <= 1); - var isAdapt = !ob.horizontalAlign || ob.horizontalAlign === BI.HorizontalAlign.Center || ob.horizontalAlign === BI.HorizontalAlign.Stretch; - var verticalAlignTop = !ob.verticalAlign || ob.verticalAlign === BI.VerticalAlign.TOP; - if (verticalAlignTop && justOneItem) { - return BI.extend({}, ob, { type: "bi.horizontal_auto" }); - } - var supportFlex = isSupportFlex(); - // 在横向自适应场景下我们需要使用table的自适应撑出滚动条的特性(flex处理不了这种情况) - // 主要出现在center_adapt或者horizontal_adapt的场景,或者主动设置horizontalAlign的场景 - if (isAdapt) { - return BI.extend({ - horizontalAlign: BI.HorizontalAlign.Center - }, ob, { type: "bi.table_adapt" }); - } - if (supportFlex) { - return BI.extend({ - horizontalAlign: BI.HorizontalAlign.Center, - scrollx: false - }, ob, { type: "bi.flex_horizontal" }); - } - return BI.extend({ - horizontalAlign: BI.HorizontalAlign.Center - }, ob, { type: "bi.table_adapt" }); - }); - BI.Plugin.configWidget("bi.horizontal_float", function (ob) { - if (isSupportFlex()) { - return BI.extend({}, ob, { type: "bi.flex_horizontal_adapt" }); - } - if (ob.items && ob.items.length <= 1) { - return BI.extend({}, ob, { type: "bi.inline_horizontal_adapt" }); - } - return ob; - }); +function isSupportFlex() { + if (!_isSupportFlex) { + _isSupportFlex = !!(BI.isSupportCss3 && BI.isSupportCss3("flex")); + } + + return _isSupportFlex; +} + +function isSupportGrid() { + if (!_isSupportGrid) { + _isSupportGrid = !!(BI.isSupportCss3 && BI.isSupportCss3("grid")); + } + + return _isSupportGrid; +} - BI.Plugin.configWidget("bi.horizontal_fill", function (ob) { +// 判断浏览器是否支持sticky 属性 +const isSupportSticky = (function () { + const vendorList = ["", "-webkit-", "-ms-", "-moz-", "-o-"], + vendorListLength = vendorList.length, + stickyElement = document.createElement("div"); + for (let i = 0; i < vendorListLength; i++) { + stickyElement.style.position = `${vendorList[i]}sticky`; + if (stickyElement.style.position !== "") { + return true; + } + } + + return false; +}()); + + +const configWidget = Plugin.configWidget; + +configWidget("bi.horizontal", ob => { + const supportFlex = isSupportFlex(); + // // 在横向自适应场景下我们需要使用table的自适应撑出滚动条的特性(flex处理不了这种情况) + // // 主要出现在center_adapt或者horizontal_adapt的场景,或者主动设置horizontalAlign的场景 + // if (ob.horizontalAlign === BI.HorizontalAlign.Center || ob.horizontalAlign === BI.HorizontalAlign.Stretch) { + // return BI.extend({}, ob, {type: "bi.table_adapt"}); + // } + if (supportFlex) { + return BI.extend({}, ob, { type: "bi.flex_horizontal" }); + } + + return BI.extend({ + scrollx: true, + }, ob, { type: "bi.inline" }); +}); +configWidget("bi.vertical", ob => { + if (ob.horizontalAlign === BI.HorizontalAlign.Left || ob.horizontalAlign === BI.HorizontalAlign.Right) { if (isSupportFlex()) { - return BI.extend({ - horizontalAlign: BI.HorizontalAlign.Stretch, - verticalAlign: BI.VerticalAlign.Stretch, - scrollx: false - }, ob, { type: "bi.flex_horizontal" }); - } - if ((ob.horizontalAlign && ob.horizontalAlign !== BI.HorizontalAlign.Stretch) || (ob.scrollable === true || ob.scrollx === true)) { - // 宽度不受限,要用table布局 - return BI.extend({ - horizontalAlign: BI.HorizontalAlign.Stretch, - verticalAlign: BI.VerticalAlign.Stretch - }, ob, { type: "bi.table_adapt" }); + return BI.extend({}, ob, { type: "bi.flex_vertical" }); } - return BI.extend({}, ob, { type: "bi.horizontal_float_fill" }); - }); - BI.Plugin.configWidget("bi.vertical_fill", function (ob) { + + return BI.extend({}, ob, { + horizontalAlign: BI.HorizontalAlign.Stretch, + type: "bi.vertical", + items: BI.map(ob.items, (i, item) => { + return { + type: "bi.inline", + horizontalAlign: ob.horizontalAlign, + items: [item], + }; + }), + }); + } + if (ob.verticalAlign === BI.VerticalAlign.Stretch) { if (isSupportFlex()) { return BI.extend({ horizontalAlign: BI.HorizontalAlign.Stretch, - verticalAlign: BI.VerticalAlign.Stretch, - scrolly: false }, ob, { type: "bi.flex_vertical" }); } - if (ob.scrollable === true || ob.scrollx === true || ob.scrolly === true) { - // 有滚动条,降级到table布局处理 - return BI.extend({}, ob, { - type: "bi.td", - items: BI.map(ob.items, function (i, item) { - return [item]; - }) - }); - } - var hasAuto = false; - if (ob.rowSize && ob.rowSize.length > 0) { - if (ob.rowSize.indexOf("") >= 0 || ob.rowSize.indexOf("auto") >= 0) { + } + + return ob; +}); +configWidget("bi.inline", ob => { + // 当列宽既需要自动列宽又需要自适应列宽时,inline布局也处理不了了,降级table处理吧 + let hasAutoAndFillColumnSize = false; + if (ob.columnSize && ob.columnSize.length > 0) { + if ((ob.columnSize.indexOf("") >= 0 || ob.columnSize.indexOf("auto") >= 0) && ob.columnSize.indexOf("fill") >= 0) { + hasAutoAndFillColumnSize = true; + } + } else { + let hasAuto = false, hasFill = false; + BI.each(ob.items, (i, item) => { + if (item.width === "fill") { + hasFill = true; + } else if (BI.isNull(item.width) || item.width === "" || item.width === "auto") { hasAuto = true; } - } else { - BI.each(ob.items, function (i, item) { - if (BI.isNull(item.height) || item.height === "") { - hasAuto = true; - } - }); - } - if (hasAuto) { - // 有自动高的时候 - return BI.extend({}, ob, { type: "bi.vtape_auto" }); - } - return BI.extend({}, ob, { type: "bi.vtape" }); - }); - BI.Plugin.configWidget("bi.horizontal_sticky", function (ob) { - if (!isSupportSticky) { - return BI.extend({ scrollx: true }, ob, { type: "bi.horizontal_fill" }); - } - }); - BI.Plugin.configWidget("bi.vertical_sticky", function (ob) { - if (!isSupportSticky) { - return BI.extend({ scrolly: true }, ob, { type: "bi.vertical_fill" }); - } - }); + }); + hasAutoAndFillColumnSize = hasAuto && hasFill; + } - BI.Plugin.configWidget("bi.left_right_vertical_adapt", function (ob) { - if (isSupportFlex()) { - // IE下其实也是可以使用flex布局的,只要排除掉出现滚动条的情况 - // if (!BI.isIE() || (ob.scrollable !== true && ob.scrolly !== true)) { - return BI.extend({}, ob, { type: "bi.flex_left_right_vertical_adapt" }); - // } + if (hasAutoAndFillColumnSize) { + // 宽度是不是受限 + if ((ob.scrollable !== true && ob.scrollx !== true) || ob.horizontalAlign === BI.HorizontalAlign.Stretch) { + return BI.extend({ + verticalAlign: BI.VerticalAlign.Top, + }, ob, { type: "bi.horizontal_float_fill" }); } - return ob; - }); - BI.Plugin.configWidget("bi.flex_horizontal", function (ob) { - if (ob.scrollable === true || ob.scrollx === true || ob.scrolly === true) { - if (ob.hgap > 0 || ob.lgap > 0 || ob.rgap > 0) { - if (BI.Providers.getProvider("bi.provider.system").getResponsiveMode()) { - return BI.extend({}, ob, { type: "bi.responsive_flex_scrollable_horizontal" }); - } - return BI.extend({}, ob, { type: "bi.flex_scrollable_horizontal" }); + + return BI.extend({ + horizontalAlign: BI.HorizontalAlign.Stretch, + }, ob, { type: "bi.table_adapt" }); + } + if (BI.Providers.getProvider("bi.provider.system").getResponsiveMode()) { + return BI.extend({}, ob, { type: "bi.responsive_inline" }); + } + + return ob; +}); +configWidget("bi.center_adapt", ob => { + const supportFlex = isSupportFlex(); + // var isAdapt = !ob.horizontalAlign || ob.horizontalAlign === BI.HorizontalAlign.Center || ob.horizontalAlign === BI.HorizontalAlign.Stretch; + // if (!isAdapt || justOneItem) { + if (supportFlex) { + return BI.extend({}, ob, { type: "bi.flex_center_adapt" }); + } + + return BI.extend({}, ob, { type: "bi.inline_center_adapt" }); + // } + // return ob; +}); +configWidget("bi.vertical_adapt", ob => { + const supportFlex = isSupportFlex(); + // var isAdapt = ob.horizontalAlign === BI.HorizontalAlign.Center || ob.horizontalAlign === BI.HorizontalAlign.Stretch; + // if (!isAdapt || justOneItem) { + if (supportFlex) { + return BI.extend({}, ob, { type: "bi.flex_vertical_center_adapt" }); + } + + return BI.extend({}, ob, { type: "bi.inline_vertical_adapt" }); + // } + // return ob; +}); + +configWidget("bi.horizontal_adapt", ob => { + const justOneItem = (ob.items && ob.items.length <= 1); + const isAdapt = !ob.horizontalAlign || ob.horizontalAlign === BI.HorizontalAlign.Center || ob.horizontalAlign === BI.HorizontalAlign.Stretch; + const verticalAlignTop = !ob.verticalAlign || ob.verticalAlign === BI.VerticalAlign.TOP; + if (verticalAlignTop && justOneItem) { + return BI.extend({}, ob, { type: "bi.horizontal_auto" }); + } + const supportFlex = isSupportFlex(); + // 在横向自适应场景下我们需要使用table的自适应撑出滚动条的特性(flex处理不了这种情况) + // 主要出现在center_adapt或者horizontal_adapt的场景,或者主动设置horizontalAlign的场景 + if (isAdapt) { + return BI.extend({ + horizontalAlign: BI.HorizontalAlign.Center, + }, ob, { type: "bi.table_adapt" }); + } + if (supportFlex) { + return BI.extend({ + horizontalAlign: BI.HorizontalAlign.Center, + scrollx: false, + }, ob, { type: "bi.flex_horizontal" }); + } + + return BI.extend({ + horizontalAlign: BI.HorizontalAlign.Center, + }, ob, { type: "bi.table_adapt" }); +}); + +configWidget("bi.horizontal_float", ob => { + if (isSupportFlex()) { + return BI.extend({}, ob, { type: "bi.flex_horizontal_adapt" }); + } + if (ob.items && ob.items.length <= 1) { + return BI.extend({}, ob, { type: "bi.inline_horizontal_adapt" }); + } + + return ob; +}); + +configWidget("bi.horizontal_fill", ob => { + if (isSupportFlex()) { + return BI.extend({ + horizontalAlign: BI.HorizontalAlign.Stretch, + verticalAlign: BI.VerticalAlign.Stretch, + scrollx: false, + }, ob, { type: "bi.flex_horizontal" }); + } + if ((ob.horizontalAlign && ob.horizontalAlign !== BI.HorizontalAlign.Stretch) || (ob.scrollable === true || ob.scrollx === true)) { + // 宽度不受限,要用table布局 + return BI.extend({ + horizontalAlign: BI.HorizontalAlign.Stretch, + verticalAlign: BI.VerticalAlign.Stretch, + }, ob, { type: "bi.table_adapt" }); + } + + return BI.extend({}, ob, { type: "bi.horizontal_float_fill" }); +}); +configWidget("bi.vertical_fill", ob => { + if (isSupportFlex()) { + return BI.extend({ + horizontalAlign: BI.HorizontalAlign.Stretch, + verticalAlign: BI.VerticalAlign.Stretch, + scrolly: false, + }, ob, { type: "bi.flex_vertical" }); + } + if (ob.scrollable === true || ob.scrollx === true || ob.scrolly === true) { + // 有滚动条,降级到table布局处理 + return BI.extend({}, ob, { + type: "bi.td", + items: BI.map(ob.items, (i, item) => [item]), + }); + } + let hasAuto = false; + if (ob.rowSize && ob.rowSize.length > 0) { + if (ob.rowSize.indexOf("") >= 0 || ob.rowSize.indexOf("auto") >= 0) { + hasAuto = true; + } + } else { + BI.each(ob.items, (i, item) => { + if (BI.isNull(item.height) || item.height === "") { + hasAuto = true; } - } - if (BI.Providers.getProvider("bi.provider.system").getResponsiveMode()) { - return BI.extend({}, ob, { type: "bi.responsive_flex_horizontal" }); - } - }); - BI.Plugin.configWidget("bi.flex_vertical", function (ob) { - if (ob.scrollable === true || ob.scrollx === true || ob.scrolly === true) { - if (ob.hgap > 0 || ob.lgap > 0 || ob.rgap > 0) { - return BI.extend({}, ob, { type: "bi.flex_scrollable_vertical" }); + }); + } + if (hasAuto) { + // 有自动高的时候 + return BI.extend({}, ob, { type: "bi.vtape_auto" }); + } + + return BI.extend({}, ob, { type: "bi.vtape" }); +}); +configWidget("bi.horizontal_sticky", ob => { + if (!isSupportSticky) { + return BI.extend({ scrollx: true }, ob, { type: "bi.horizontal_fill" }); + } +}); +configWidget("bi.vertical_sticky", ob => { + if (!isSupportSticky) { + return BI.extend({ scrolly: true }, ob, { type: "bi.vertical_fill" }); + } +}); + +configWidget("bi.left_right_vertical_adapt", ob => { + if (isSupportFlex()) { + // IE下其实也是可以使用flex布局的,只要排除掉出现滚动条的情况 + // if (!BI.isIE() || (ob.scrollable !== true && ob.scrolly !== true)) { + return BI.extend({}, ob, { type: "bi.flex_left_right_vertical_adapt" }); + // } + } + + return ob; +}); +configWidget("bi.flex_horizontal", ob => { + if (ob.scrollable === true || ob.scrollx === true || ob.scrolly === true) { + if (ob.hgap > 0 || ob.lgap > 0 || ob.rgap > 0) { + if (BI.Providers.getProvider("bi.provider.system").getResponsiveMode()) { + return BI.extend({}, ob, { type: "bi.responsive_flex_scrollable_horizontal" }); } - } - }); - BI.Plugin.configWidget("bi.table", function (ob) { - if (!isSupportGrid()) { - return BI.extend({}, ob, { type: "bi.td" }); - } - return ob; - }); + return BI.extend({}, ob, { type: "bi.flex_scrollable_horizontal" }); + } + } + if (BI.Providers.getProvider("bi.provider.system").getResponsiveMode()) { + return BI.extend({}, ob, { type: "bi.responsive_flex_horizontal" }); + } +}); +configWidget("bi.flex_vertical", ob => { + if (ob.scrollable === true || ob.scrollx === true || ob.scrolly === true) { + if (ob.hgap > 0 || ob.lgap > 0 || ob.rgap > 0) { + return BI.extend({}, ob, { type: "bi.flex_scrollable_vertical" }); + } + } +}); - BI.Plugin.configWidget("bi.radio", function (ob) { - if (BI.isIE() && BI.getIEVersion() <= 9) { - return BI.extend({}, ob, { type: "bi.image_radio" }); - } - return ob; - }); +configWidget("bi.table", ob => { + if (!isSupportGrid()) { + return BI.extend({}, ob, { type: "bi.td" }); + } - BI.Plugin.configWidget("bi.checkbox", function (ob) { - if (BI.isIE() && BI.getIEVersion() <= 9) { - return BI.extend({}, ob, { type: "bi.image_checkbox" }); - } + return ob; +}); + +configWidget("bi.radio", ob => { + if (BI.isIE() && BI.getIEVersion() <= 9) { + return BI.extend({}, ob, { type: "bi.image_radio" }); + } + + return ob; +}); + +configWidget("bi.checkbox", ob => { + if (BI.isIE() && BI.getIEVersion() <= 9) { + return BI.extend({}, ob, { type: "bi.image_checkbox" }); + } + + return ob; +}); + +configWidget("bi.half_icon_button", ob => { + if (BI.isIE() && BI.getIEVersion() < 9) { return ob; - }); + } + + return BI.extend({}, ob, { type: "bi.half_button" }); +}); + - BI.Plugin.configWidget("bi.half_icon_button", function (ob) { - if (BI.isIE() && BI.getIEVersion() < 9) { - return ob; - } - return BI.extend({}, ob, { type: "bi.half_button" }); - }); -}()); diff --git a/src/core/platform/web/detectElementResize.js b/src/core/platform/web/detectElementResize.js index 502ebb0ee..7be166fd9 100644 --- a/src/core/platform/web/detectElementResize.js +++ b/src/core/platform/web/detectElementResize.js @@ -1,571 +1,15 @@ -/** - * Detect Element Resize. - * A minimal library which polyfills the ResizeObserver API and is entirely based on the latest Draft Specification. - * https://github.com/juggle/resize-observer - * version: 3.4.0 - **/ -var ResizeObserverPolyfill = (function (exports) { - 'use strict'; +import { ResizeObserver as ResizeObserverPolyfill } from "@juggle/resize-observer"; - var resizeObservers = []; +const ResizeObserver = window.ResizeObserver || ResizeObserverPolyfill; - var hasActiveObservations = function () { - return resizeObservers.some(function (ro) { - return ro.activeTargets.length > 0; - }); - }; - - var hasSkippedObservations = function () { - return resizeObservers.some(function (ro) { - return ro.skippedTargets.length > 0; - }); - }; - - var msg = 'ResizeObserver loop completed with undelivered notifications.'; - var deliverResizeLoopError = function () { - var event; - if (typeof ErrorEvent === 'function') { - event = new ErrorEvent('error', { - message: msg - }); - } else { - event = document.createEvent('Event'); - event.initEvent('error', false, false); - event.message = msg; - } - window.dispatchEvent(event); - }; - - var ResizeObserverBoxOptions; - (function (ResizeObserverBoxOptions) { - ResizeObserverBoxOptions["BORDER_BOX"] = "border-box"; - ResizeObserverBoxOptions["CONTENT_BOX"] = "content-box"; - ResizeObserverBoxOptions["DEVICE_PIXEL_CONTENT_BOX"] = "device-pixel-content-box"; - })(ResizeObserverBoxOptions || (ResizeObserverBoxOptions = {})); - - var freeze = function (obj) { - return Object.freeze(obj); - }; - - var ResizeObserverSize = (function () { - function ResizeObserverSize(inlineSize, blockSize) { - this.inlineSize = inlineSize; - this.blockSize = blockSize; - freeze(this); - } - - return ResizeObserverSize; - }()); - - var DOMRectReadOnly = (function () { - function DOMRectReadOnly(x, y, width, height) { - this.x = x; - this.y = y; - this.width = width; - this.height = height; - this.top = this.y; - this.left = this.x; - this.bottom = this.top + this.height; - this.right = this.left + this.width; - return freeze(this); - } - - DOMRectReadOnly.prototype.toJSON = function () { - var _a = this, x = _a.x, y = _a.y, top = _a.top, right = _a.right, bottom = _a.bottom, left = _a.left, - width = _a.width, height = _a.height; - return { x: x, y: y, top: top, right: right, bottom: bottom, left: left, width: width, height: height }; - }; - DOMRectReadOnly.fromRect = function (rectangle) { - return new DOMRectReadOnly(rectangle.x, rectangle.y, rectangle.width, rectangle.height); - }; - return DOMRectReadOnly; - }()); - - var isSVG = function (target) { - return target instanceof SVGElement && 'getBBox' in target; - }; - var isHidden = function (target) { - if (isSVG(target)) { - var _a = target.getBBox(), width = _a.width, height = _a.height; - return !width && !height; - } - var _b = target, offsetWidth = _b.offsetWidth, offsetHeight = _b.offsetHeight; - return !(offsetWidth || offsetHeight || target.getClientRects().length); - }; - var isElement = function (obj) { - var _a; - if (obj instanceof Element) { - return true; - } - var scope = (_a = obj === null || obj === void 0 ? void 0 : obj.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView; - return !!(scope && obj instanceof scope.Element); - }; - var isReplacedElement = function (target) { - switch (target.tagName) { - case 'INPUT': - if (target.type !== 'image') { - break; - } - case 'VIDEO': - case 'AUDIO': - case 'EMBED': - case 'OBJECT': - case 'CANVAS': - case 'IFRAME': - case 'IMG': - return true; - } - return false; - }; - - var global = typeof window !== 'undefined' ? window : {}; - - var cache = new WeakMap(); - var scrollRegexp = /auto|scroll/; - var verticalRegexp = /^tb|vertical/; - var IE = (/msie|trident/i).test(global.navigator && global.navigator.userAgent); - var parseDimension = function (pixel) { - return parseFloat(pixel || '0'); - }; - var size = function (inlineSize, blockSize, switchSizes) { - if (inlineSize === void 0) { - inlineSize = 0; - } - if (blockSize === void 0) { - blockSize = 0; - } - if (switchSizes === void 0) { - switchSizes = false; - } - return new ResizeObserverSize((switchSizes ? blockSize : inlineSize) || 0, (switchSizes ? inlineSize : blockSize) || 0); - }; - var zeroBoxes = freeze({ - devicePixelContentBoxSize: size(), - borderBoxSize: size(), - contentBoxSize: size(), - contentRect: new DOMRectReadOnly(0, 0, 0, 0) - }); - var calculateBoxSizes = function (target, forceRecalculation) { - if (forceRecalculation === void 0) { - forceRecalculation = false; - } - if (cache.has(target) && !forceRecalculation) { - return cache.get(target); - } - if (isHidden(target)) { - cache.set(target, zeroBoxes); - return zeroBoxes; - } - var cs = getComputedStyle(target); - var svg = isSVG(target) && target.ownerSVGElement && target.getBBox(); - var removePadding = !IE && cs.boxSizing === 'border-box'; - var switchSizes = verticalRegexp.test(cs.writingMode || ''); - var canScrollVertically = !svg && scrollRegexp.test(cs.overflowY || ''); - var canScrollHorizontally = !svg && scrollRegexp.test(cs.overflowX || ''); - var paddingTop = svg ? 0 : parseDimension(cs.paddingTop); - var paddingRight = svg ? 0 : parseDimension(cs.paddingRight); - var paddingBottom = svg ? 0 : parseDimension(cs.paddingBottom); - var paddingLeft = svg ? 0 : parseDimension(cs.paddingLeft); - var borderTop = svg ? 0 : parseDimension(cs.borderTopWidth); - var borderRight = svg ? 0 : parseDimension(cs.borderRightWidth); - var borderBottom = svg ? 0 : parseDimension(cs.borderBottomWidth); - var borderLeft = svg ? 0 : parseDimension(cs.borderLeftWidth); - var horizontalPadding = paddingLeft + paddingRight; - var verticalPadding = paddingTop + paddingBottom; - var horizontalBorderArea = borderLeft + borderRight; - var verticalBorderArea = borderTop + borderBottom; - var horizontalScrollbarThickness = !canScrollHorizontally ? 0 : target.offsetHeight - verticalBorderArea - target.clientHeight; - var verticalScrollbarThickness = !canScrollVertically ? 0 : target.offsetWidth - horizontalBorderArea - target.clientWidth; - var widthReduction = removePadding ? horizontalPadding + horizontalBorderArea : 0; - var heightReduction = removePadding ? verticalPadding + verticalBorderArea : 0; - var contentWidth = svg ? svg.width : parseDimension(cs.width) - widthReduction - verticalScrollbarThickness; - var contentHeight = svg ? svg.height : parseDimension(cs.height) - heightReduction - horizontalScrollbarThickness; - var borderBoxWidth = contentWidth + horizontalPadding + verticalScrollbarThickness + horizontalBorderArea; - var borderBoxHeight = contentHeight + verticalPadding + horizontalScrollbarThickness + verticalBorderArea; - var boxes = freeze({ - devicePixelContentBoxSize: size(Math.round(contentWidth * devicePixelRatio), Math.round(contentHeight * devicePixelRatio), switchSizes), - borderBoxSize: size(borderBoxWidth, borderBoxHeight, switchSizes), - contentBoxSize: size(contentWidth, contentHeight, switchSizes), - contentRect: new DOMRectReadOnly(paddingLeft, paddingTop, contentWidth, contentHeight) - }); - cache.set(target, boxes); - return boxes; - }; - var calculateBoxSize = function (target, observedBox, forceRecalculation) { - var _a = calculateBoxSizes(target, forceRecalculation), borderBoxSize = _a.borderBoxSize, - contentBoxSize = _a.contentBoxSize, devicePixelContentBoxSize = _a.devicePixelContentBoxSize; - switch (observedBox) { - case ResizeObserverBoxOptions.DEVICE_PIXEL_CONTENT_BOX: - return devicePixelContentBoxSize; - case ResizeObserverBoxOptions.BORDER_BOX: - return borderBoxSize; - default: - return contentBoxSize; - } - }; - - var ResizeObserverEntry = (function () { - function ResizeObserverEntry(target) { - var boxes = calculateBoxSizes(target); - this.target = target; - this.contentRect = boxes.contentRect; - this.borderBoxSize = freeze([boxes.borderBoxSize]); - this.contentBoxSize = freeze([boxes.contentBoxSize]); - this.devicePixelContentBoxSize = freeze([boxes.devicePixelContentBoxSize]); - } - - return ResizeObserverEntry; - }()); - - var calculateDepthForNode = function (node) { - if (isHidden(node)) { - return Infinity; - } - var depth = 0; - var parent = node.parentNode; - while (parent) { - depth += 1; - parent = parent.parentNode; - } - return depth; - }; - - var broadcastActiveObservations = function () { - var shallowestDepth = Infinity; - var callbacks = []; - resizeObservers.forEach(function processObserver(ro) { - if (ro.activeTargets.length === 0) { - return; - } - var entries = []; - ro.activeTargets.forEach(function processTarget(ot) { - var entry = new ResizeObserverEntry(ot.target); - var targetDepth = calculateDepthForNode(ot.target); - entries.push(entry); - ot.lastReportedSize = calculateBoxSize(ot.target, ot.observedBox); - if (targetDepth < shallowestDepth) { - shallowestDepth = targetDepth; - } - }); - callbacks.push(function resizeObserverCallback() { - ro.callback.call(ro.observer, entries, ro.observer); - }); - ro.activeTargets.splice(0, ro.activeTargets.length); - }); - for (var _i = 0, callbacks_1 = callbacks; _i < callbacks_1.length; _i++) { - var callback = callbacks_1[_i]; - callback(); - } - return shallowestDepth; - }; - - var gatherActiveObservationsAtDepth = function (depth) { - resizeObservers.forEach(function processObserver(ro) { - ro.activeTargets.splice(0, ro.activeTargets.length); - ro.skippedTargets.splice(0, ro.skippedTargets.length); - ro.observationTargets.forEach(function processTarget(ot) { - if (ot.isActive()) { - if (calculateDepthForNode(ot.target) > depth) { - ro.activeTargets.push(ot); - } else { - ro.skippedTargets.push(ot); - } - } - }); - }); - }; - - var process = function () { - var depth = 0; - gatherActiveObservationsAtDepth(depth); - while (hasActiveObservations()) { - depth = broadcastActiveObservations(); - gatherActiveObservationsAtDepth(depth); - } - if (hasSkippedObservations()) { - deliverResizeLoopError(); - } - return depth > 0; - }; - - var trigger; - var callbacks = []; - var notify = function () { - return callbacks.splice(0).forEach(function (cb) { - return cb(); - }); - }; - var queueMicroTask = function (callback) { - if (!trigger) { - var toggle_1 = 0; - var el_1 = document.createTextNode(''); - var config = { characterData: true }; - new MutationObserver(function () { - return notify(); - }).observe(el_1, config); - trigger = function () { - el_1.textContent = "".concat(toggle_1 ? toggle_1-- : toggle_1++); - }; - } - callbacks.push(callback); - trigger(); - }; - - var queueResizeObserver = function (cb) { - queueMicroTask(function ResizeObserver() { - requestAnimationFrame(cb); - }); - }; - - var watching = 0; - var isWatching = function () { - return !!watching; - }; - var CATCH_PERIOD = 250; - var observerConfig = { attributes: true, characterData: true, childList: true, subtree: true }; - var events = [ - 'resize', - 'load', - 'transitionend', - 'animationend', - 'animationstart', - 'animationiteration', - 'keyup', - 'keydown', - 'mouseup', - 'mousedown', - 'mouseover', - 'mouseout', - 'blur', - 'focus' - ]; - var time = function (timeout) { - if (timeout === void 0) { - timeout = 0; - } - return Date.now() + timeout; - }; - var scheduled = false; - var Scheduler = (function () { - function Scheduler() { - var _this = this; - this.stopped = true; - this.listener = function () { - return _this.schedule(); - }; - } - - Scheduler.prototype.run = function (timeout) { - var _this = this; - if (timeout === void 0) { - timeout = CATCH_PERIOD; - } - if (scheduled) { - return; - } - scheduled = true; - var until = time(timeout); - queueResizeObserver(function () { - var elementsHaveResized = false; - try { - elementsHaveResized = process(); - } finally { - scheduled = false; - timeout = until - time(); - if (!isWatching()) { - return; - } - if (elementsHaveResized) { - _this.run(1000); - } else if (timeout > 0) { - _this.run(timeout); - } else { - _this.start(); - } - } - }); - }; - Scheduler.prototype.schedule = function () { - this.stop(); - this.run(); - }; - Scheduler.prototype.observe = function () { - var _this = this; - var cb = function () { - return _this.observer && _this.observer.observe(document.body, observerConfig); - }; - document.body ? cb() : global.addEventListener('DOMContentLoaded', cb); - }; - Scheduler.prototype.start = function () { - var _this = this; - if (this.stopped) { - this.stopped = false; - this.observer = new MutationObserver(this.listener); - this.observe(); - events.forEach(function (name) { - return global.addEventListener(name, _this.listener, true); - }); - } - }; - Scheduler.prototype.stop = function () { - var _this = this; - if (!this.stopped) { - this.observer && this.observer.disconnect(); - events.forEach(function (name) { - return global.removeEventListener(name, _this.listener, true); - }); - this.stopped = true; - } - }; - return Scheduler; - }()); - var scheduler = new Scheduler(); - var updateCount = function (n) { - !watching && n > 0 && scheduler.start(); - watching += n; - !watching && scheduler.stop(); - }; - - var skipNotifyOnElement = function (target) { - return !isSVG(target) - && !isReplacedElement(target) - && getComputedStyle(target).display === 'inline'; - }; - var ResizeObservation = (function () { - function ResizeObservation(target, observedBox) { - this.target = target; - this.observedBox = observedBox || ResizeObserverBoxOptions.CONTENT_BOX; - this.lastReportedSize = { - inlineSize: -1, - blockSize: -1 - }; - } - - ResizeObservation.prototype.isActive = function () { - var size = calculateBoxSize(this.target, this.observedBox, true); - if (skipNotifyOnElement(this.target)) { - this.lastReportedSize = size; - } - if (this.lastReportedSize.inlineSize !== size.inlineSize - || this.lastReportedSize.blockSize !== size.blockSize) { - return true; - } - return false; - }; - return ResizeObservation; - }()); - - var ResizeObserverDetail = (function () { - function ResizeObserverDetail(resizeObserver, callback) { - this.activeTargets = []; - this.skippedTargets = []; - this.observationTargets = []; - this.observer = resizeObserver; - this.callback = callback; - } - - return ResizeObserverDetail; - }()); - - var observerMap = new WeakMap(); - var getObservationIndex = function (observationTargets, target) { - for (var i = 0; i < observationTargets.length; i += 1) { - if (observationTargets[i].target === target) { - return i; - } - } - return -1; - }; - var ResizeObserverController = (function () { - function ResizeObserverController() { - } - - ResizeObserverController.connect = function (resizeObserver, callback) { - var detail = new ResizeObserverDetail(resizeObserver, callback); - observerMap.set(resizeObserver, detail); - }; - ResizeObserverController.observe = function (resizeObserver, target, options) { - var detail = observerMap.get(resizeObserver); - var firstObservation = detail.observationTargets.length === 0; - if (getObservationIndex(detail.observationTargets, target) < 0) { - firstObservation && resizeObservers.push(detail); - detail.observationTargets.push(new ResizeObservation(target, options && options.box)); - updateCount(1); - scheduler.schedule(); - } - }; - ResizeObserverController.unobserve = function (resizeObserver, target) { - var detail = observerMap.get(resizeObserver); - var index = getObservationIndex(detail.observationTargets, target); - var lastObservation = detail.observationTargets.length === 1; - if (index >= 0) { - lastObservation && resizeObservers.splice(resizeObservers.indexOf(detail), 1); - detail.observationTargets.splice(index, 1); - updateCount(-1); - } - }; - ResizeObserverController.disconnect = function (resizeObserver) { - var _this = this; - var detail = observerMap.get(resizeObserver); - detail.observationTargets.slice().forEach(function (ot) { - return _this.unobserve(resizeObserver, ot.target); - }); - detail.activeTargets.splice(0, detail.activeTargets.length); - }; - return ResizeObserverController; - }()); - - var ResizeObserver = (function () { - function ResizeObserver(callback) { - if (arguments.length === 0) { - throw new TypeError("Failed to construct 'ResizeObserver': 1 argument required, but only 0 present."); - } - if (typeof callback !== 'function') { - throw new TypeError("Failed to construct 'ResizeObserver': The callback provided as parameter 1 is not a function."); - } - ResizeObserverController.connect(this, callback); - } - - ResizeObserver.prototype.observe = function (target, options) { - if (arguments.length === 0) { - throw new TypeError("Failed to execute 'observe' on 'ResizeObserver': 1 argument required, but only 0 present."); - } - if (!isElement(target)) { - throw new TypeError("Failed to execute 'observe' on 'ResizeObserver': parameter 1 is not of type 'Element"); - } - ResizeObserverController.observe(this, target, options); - }; - ResizeObserver.prototype.unobserve = function (target) { - if (arguments.length === 0) { - throw new TypeError("Failed to execute 'unobserve' on 'ResizeObserver': 1 argument required, but only 0 present."); - } - if (!isElement(target)) { - throw new TypeError("Failed to execute 'unobserve' on 'ResizeObserver': parameter 1 is not of type 'Element"); - } - ResizeObserverController.unobserve(this, target); - }; - ResizeObserver.prototype.disconnect = function () { - ResizeObserverController.disconnect(this); - }; - ResizeObserver.toString = function () { - return 'function ResizeObserver () { [polyfill code] }'; - }; - return ResizeObserver; - }()); - - return ResizeObserver; -})(); - -var ResizeObserver = window.ResizeObserver || ResizeObserverPolyfill; - -var addResizeListener = function (element, fn) { +function addResizeListener(element, fn) { if (ResizeObserver) { if (!element.__resizeObserver__) { - var resizeObserver = new ResizeObserver(function () { - element.__resizeListeners__.forEach(function (listener) { + const resizeObserver = new ResizeObserver((() => { + element.__resizeListeners__.forEach(listener => { BI.$(element).is(":visible") && listener(); }); - }); + })); resizeObserver.observe(element); element.__resizeObserver__ = resizeObserver; } @@ -574,16 +18,18 @@ var addResizeListener = function (element, fn) { } element.__resizeListeners__.push(fn); } -}; -var removeResizeListener = function (element, fn) { +} + +function removeResizeListener(element, fn) { if (ResizeObserver) { if (BI.isNull(fn)) { element.__resizeListeners__ = []; element.__resizeObserver__ && element.__resizeObserver__.unobserve(element); element.__resizeObserver__ = null; + return; } - var index = element.__resizeListeners__.indexOf(fn); + const index = element.__resizeListeners__.indexOf(fn); if (index >= 0) { element.__resizeListeners__.splice(index, 1); if (!element.__resizeListeners__.length) { @@ -592,19 +38,17 @@ var removeResizeListener = function (element, fn) { } } } -}; +} export const ResizeDetector = { - addResizeListener: function (widget, fn) { + addResizeListener(widget, fn) { addResizeListener(widget.element[0], fn); + return function () { removeResizeListener(widget.element[0], fn); }; - }, removeResizeListener: function (widget, fn) { + }, + removeResizeListener(widget, fn) { removeResizeListener(widget.element[0], fn); - } + }, }; - -Object.assign(BI, { - ResizeDetector -}); diff --git a/src/core/platform/web/dom.js b/src/core/platform/web/dom.js index cc9ed0f8d..5835df64f 100644 --- a/src/core/platform/web/dom.js +++ b/src/core/platform/web/dom.js @@ -1,758 +1,784 @@ /** * 对DOM操作的通用函数 - * @type {{}} */ -!(function () { - BI.DOM = BI.DOM || {}; - - BI.extend(BI.DOM, { - ready: function (fn) { - BI.Widget._renderEngine.createElement(document).ready(fn); - } +import { each, isEmpty, isNull } from "../../2.base"; + +export function ready(fn) { + BI.Widget._renderEngine.createElement(document).ready(fn); +} + +export function patchProps(fromElement, toElement) { + const elemData = BI.jQuery._data(fromElement[0]); + const events = elemData.events; + each(events, (eventKey, event) => { + each(event, (i, handler) => { + toElement.on(eventKey + (handler.namespace ? (`.${handler.namespace}`) : ""), handler); + }); }); + const fromChildren = fromElement.children(), toChildren = toElement.children(); + if (fromChildren.length !== toChildren.length) { + throw new Error("不匹配"); + } + each(fromChildren, (i, child) => { + patchProps(BI.jQuery(child), BI.jQuery(toChildren[i])); + }); + each(fromElement.data("__widgets"), (i, widget) => { + widget.element = toElement; + }); +} - BI.extend(BI.DOM, { - - patchProps: function (fromElement, toElement) { - var elemData = BI.jQuery._data(fromElement[0]); - var events = elemData.events; - BI.each(events, function (eventKey, event) { - BI.each(event, function (i, handler) { - toElement.on(eventKey + (handler.namespace ? ("." + handler.namespace) : ""), handler); - }); - }); - var fromChildren = fromElement.children(), toChildren = toElement.children(); - if (fromChildren.length !== toChildren.length) { - throw new Error("不匹配"); - } - BI.each(fromChildren, function (i, child) { - BI.DOM.patchProps(BI.jQuery(child), BI.jQuery(toChildren[i])); - }); - BI.each(fromElement.data("__widgets"), function (i, widget) { - widget.element = toElement; - }); - }, - /** - * 把dom数组或元素悬挂起来,使其不对html产生影响 - * @param dom - */ - hang: function (doms) { - if (BI.isEmpty(doms)) { - return; - } - var frag = BI.Widget._renderEngine.createFragment(); - BI.each(doms, function (i, dom) { - dom instanceof BI.Widget && (dom = dom.element); - dom instanceof BI.$ && dom[0] && frag.appendChild(dom[0]); - }); - return frag; - }, - - isExist: function (obj) { - return BI.Widget._renderEngine.createElement("body").find(obj.element).length > 0; - }, - - // 预加载图片 - preloadImages: function (srcArray, onload) { - var count = 0, images = []; - - function complete() { - count++; - if (count >= srcArray.length) { - onload(); - } - } - - BI.each(srcArray, function (i, src) { - images[i] = new Image(); - images[i].src = src; - images[i].onload = function () { - complete(); - }; - images[i].onerror = function () { - complete(); - }; - }); - }, - - getTextSizeWidth: function (text, fontSize) { - var span = BI.Widget._renderEngine.createElement("").addClass("text-width-span").appendTo("body"); - - if (fontSize == null) { - fontSize = 12; - } - fontSize = fontSize + "px"; - - span.css("font-size", fontSize).text(text); +/** + * 把dom数组或元素悬挂起来,使其不对html产生影响 + * @param dom + */ +export function hang(doms) { + if (isEmpty(doms)) { + return; + } + const frag = BI.Widget._renderEngine.createFragment(); + each(doms, (i, dom) => { + dom instanceof BI.Widget && (dom = dom.element); + dom instanceof BI.$ && dom[0] && frag.appendChild(dom[0]); + }); - var width = span.width(); - span.remove(); + return frag; +} - return width; - }, +export function isExist(obj) { + return BI.Widget._renderEngine.createElement("body").find(obj.element).length > 0; +} - getTextSizeHeight: function (text, fontSize) { - var span = BI.Widget._renderEngine.createElement("").addClass("text-width-span").appendTo("body"); +// 预加载图片 +export function preloadImages(srcArray, onload) { + let count = 0; + const images = []; - if (fontSize == null) { - fontSize = 12; - } - fontSize = fontSize + "px"; - - span.css("font-size", fontSize).text(text); - - var height = span.height(); - span.remove(); - - return height; - }, - - // 获取滚动条的宽度,页面display: none时候获取到的为0 - getScrollWidth: function () { - if (BI.isNull(this._scrollWidth) || this._scrollWidth === 0) { - var ul = BI.Widget._renderEngine.createElement("
").width(50).height(50).css({ - position: "absolute", - top: "-9999px", - overflow: "scroll" - }).appendTo("body"); - this._scrollWidth = ul[0].offsetWidth - ul[0].clientWidth; - ul.destroy(); - } - return this._scrollWidth; - }, - - getImage: function (param, fillStyle, backgroundColor) { - var canvas = document.createElement("canvas"); - var ratio = 2; - BI.Widget._renderEngine.createElement("body").append(canvas); - - var ctx = canvas.getContext("2d"); - ctx.font = "12px Helvetica Neue,Arial,PingFang SC,Hiragino Sans GB,Microsoft YaHei,微软雅黑,Heiti,黑体,sans-serif"; - var w = ctx.measureText(param).width + 4; - canvas.width = w * ratio; - canvas.height = 16 * ratio; - ctx.font = 12 * ratio + "px Helvetica Neue,Arial,PingFang SC,Hiragino Sans GB,Microsoft YaHei,微软雅黑,Heiti,黑体,sans-serif"; - ctx.fillStyle = fillStyle || "#3685f2"; - ctx.textBaseline = "middle"; - // ctx.fillStyle = "#EAF2FD"; - ctx.fillText(param, 2 * ratio, 9 * ratio); - BI.Widget._renderEngine.createElement(canvas).destroy(); - var backColor = backgroundColor || "rgba(54, 133, 242, 0.1)"; - // IE可以放大缩小所以要固定最大最小宽高 - return { - width: w, - height: 16, - src: canvas.toDataURL("image/png"), - style: "background-color: " + backColor + ";vertical-align: middle; margin: 0 1px; width:" + w + "px;height: 16px; max-width:" + w + "px;max-height: 16px; min-width:" + w + "px;min-height: 16px", - param: param - }; + function complete() { + count++; + if (count >= srcArray.length) { + onload(); } + } + + each(srcArray, (i, src) => { + images[i] = new Image(); + images[i].src = src; + images[i].onload = function () { + complete(); + }; + images[i].onerror = function () { + complete(); + }; }); - - BI.extend(BI.DOM, { - - 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: elRect.left - containerRect.left - popupElRect.width - (extraWidth || 0) - }; - }, - - getInnerLeftPosition: function (combo, popup, extraWidth) { - return { - left: combo.element.offset().left + (extraWidth || 0) - }; - }, - - getRightPosition: function (combo, popup, extraWidth, container) { - var el = combo.element; - var elRect = el[0].getBoundingClientRect(); - var containerRect = container ? container.getBoundingClientRect() : { left: 0 }; - - return { - left: elRect.left + elRect.width - containerRect.left + (extraWidth || 0) - }; - }, - - getInnerRightPosition: function (combo, popup, extraWidth) { - var el = combo.element, viewBounds = popup.element.bounds(); - return { - left: el.offset().left + el.outerWidth() - viewBounds.width - (extraWidth || 0) - }; - }, - - 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: elRect.top - containerRect.top - popupElRect.height - (extraHeight || 0) - }; - }, - - getBottomPosition: function (combo, popup, extraHeight, container) { - var el = combo.element; - var elRect = el[0].getBoundingClientRect(); - var containerRect = container ? container.getBoundingClientRect() : { top: 0 }; - - return { - top: elRect.top - containerRect.top + elRect.height + (extraHeight || 0) - }; - }, - - isLeftSpaceEnough: function (combo, popup, extraWidth) { - return BI.DOM.getLeftPosition(combo, popup, extraWidth).left >= 0; - }, - - isInnerLeftSpaceEnough: function (combo, popup, extraWidth) { - var viewBounds = popup.element.bounds(), - windowBounds = BI.Widget._renderEngine.createElement("body").bounds(); - return BI.DOM.getInnerLeftPosition(combo, popup, extraWidth).left + viewBounds.width <= windowBounds.width; - }, - - isRightSpaceEnough: function (combo, popup, extraWidth) { - var viewBounds = popup.element[0].getBoundingClientRect(), - viewportBounds = document.documentElement.getBoundingClientRect(); - return BI.DOM.getRightPosition(combo, popup, extraWidth).left + viewBounds.width <= viewportBounds.width; - }, - - isInnerRightSpaceEnough: function (combo, popup, extraWidth) { - return BI.DOM.getInnerRightPosition(combo, popup, extraWidth).left >= 0; - }, - - isTopSpaceEnough: function (combo, popup, extraHeight) { - return BI.DOM.getTopPosition(combo, popup, extraHeight).top >= 0; - }, - - isBottomSpaceEnough: function (combo, popup, extraHeight) { - var viewBounds = popup.element[0].getBoundingClientRect(), - viewportBounds = document.documentElement.getBoundingClientRect(); - return BI.DOM.getBottomPosition(combo, popup, extraHeight).top + viewBounds.height <= viewportBounds.height; - }, - - isRightSpaceLarger: function (combo) { - var comboBounds = combo.element[0].getBoundingClientRect(), - viewportBounds = document.documentElement.getBoundingClientRect(); - return viewportBounds.width - comboBounds.right >= comboBounds.left; - }, - - isBottomSpaceLarger: function (combo) { - var comboBounds = combo.element[0].getBoundingClientRect(), - viewportBounds = document.documentElement.getBoundingClientRect(); - return viewportBounds.height - comboBounds.bottom >= comboBounds.top; - }, - - _getLeftAlignPosition: function (combo, popup, extraWidth, container) { - var comboRect = combo.element[0].getBoundingClientRect(), - popupRect = popup.element[0].getBoundingClientRect(), - viewportRect = document.documentElement.getBoundingClientRect(), - containerRect = container ? container.getBoundingClientRect() : { left: 0 }; - var left = comboRect.left - containerRect.left + extraWidth; - - if (comboRect.left + popupRect.width > viewportRect.width) { - left = viewportRect.width - popupRect.width - containerRect.left; - } - return left; - }, - - getLeftAlignPosition: function (combo, popup, extraWidth, container) { - var left = this._getLeftAlignPosition(combo, popup, extraWidth, container); - var dir = ""; - // 如果放不下,优先使用RightAlign, 如果RightAlign也放不下, 再使用left=0 - var containerRect = container ? container.getBoundingClientRect() : { left: 0 }; - if (left + containerRect.left < 0) { - left = this._getRightAlignPosition(combo, popup, extraWidth); - dir = "left"; - } - if (left + containerRect.left < 0) { - left = 0 - containerRect.left; - } - return { - left: left, - dir: dir || "right" - }; - }, - - getLeftAdaptPosition: function (combo, popup, extraWidth, container) { - if (BI.DOM.isLeftSpaceEnough(combo, popup, extraWidth, container)) { - return BI.DOM.getLeftPosition(combo, popup, extraWidth, container); - } - return { - left: 0 - }; - }, - - _getRightAlignPosition: function (combo, popup, extraWidth, container) { - var comboBounds = combo.element[0].getBoundingClientRect(), - viewBounds = popup.element[0].getBoundingClientRect(), - containerRect = container ? container.getBoundingClientRect() : { left: 0 }; - return comboBounds.left + comboBounds.width - viewBounds.width - extraWidth - containerRect.left; - }, - - getRightAlignPosition: function (combo, popup, extraWidth, container) { - var left = this._getRightAlignPosition(combo, popup, extraWidth, container); - var dir = ""; - // 如果放不下,优先使用LeftAlign, 如果LeftAlign也放不下, 再使用left=0 - if (left < 0) { - left = this._getLeftAlignPosition(combo, popup, extraWidth, container); - dir = "right"; - } - if (left < 0) { - left = 0; - } - return { - left: left, - dir: dir || "left" - }; - }, - - getRightAdaptPosition: function (combo, popup, extraWidth, container) { - if (BI.DOM.isRightSpaceEnough(combo, popup, extraWidth, container)) { - return BI.DOM.getRightPosition(combo, popup, extraWidth, container); - } - return { - left: document.documentElement.getBoundingClientRect().width - popup.element[0].getBoundingClientRect().width - container.getBoundingClientRect().left - }; - }, - - getTopAlignPosition: function (combo, popup, extraHeight, needAdaptHeight, container) { - var comboBounds = combo.element[0].getBoundingClientRect(), - popupBounds = popup.element[0].getBoundingClientRect(), - viewportBounds = document.documentElement.getBoundingClientRect(), - containerBounds = container ? container.getBoundingClientRect() : { top: 0 }; - var top, adaptHeight, dir; - if (BI.DOM.isBottomSpaceEnough(combo, popup, -1 * comboBounds.height + extraHeight)) { - top = comboBounds.top - containerBounds.top + extraHeight; - } else if (needAdaptHeight) { - top = comboBounds.top - containerBounds.top + extraHeight; - adaptHeight = viewportBounds.height - comboBounds.top; - } else if (BI.DOM.isTopSpaceEnough(combo, popup, -1 * comboBounds.height + extraHeight)) { - // 下方空间不足且不允许调整高度的情况下,优先使用上对齐 - top = comboBounds.top + comboBounds.height - popupBounds.height - containerBounds.top - extraHeight; - dir = "top"; - } else { - top = viewportBounds.height - popupBounds.height; - if (top < extraHeight) { - adaptHeight = viewportBounds.height - extraHeight; - } - } - if (top < extraHeight) { - top = extraHeight; - } - return adaptHeight ? { - top: top, - adaptHeight: adaptHeight, - dir: dir || "bottom" - } : { - top: top, - dir: dir || "bottom" - }; - }, - - getTopAdaptPosition: function (combo, popup, extraHeight, needAdaptHeight, positionRelativeElement) { - var comboBounds = combo.element[0].getBoundingClientRect(), - popupBounds = popup.element[0].getBoundingClientRect(), - positionRelativeElementRect = positionRelativeElement.getBoundingClientRect(), - viewportBounds = document.documentElement.getBoundingClientRect(); - if (BI.DOM.isTopSpaceEnough(combo, popup, extraHeight)) { - return BI.DOM.getTopPosition(combo, popup, extraHeight); - } - if (needAdaptHeight) { - return { - top: 0 - positionRelativeElementRect.top, - adaptHeight: comboBounds.top - extraHeight - }; - } - if (popupBounds.height + extraHeight > viewportBounds.height) { - return { - top: 0 - positionRelativeElementRect.top, - adaptHeight: viewportBounds.height - extraHeight - }; - } - return { - top: 0 - positionRelativeElementRect.top - }; - }, - - getBottomAlignPosition: function (combo, popup, extraHeight, needAdaptHeight, container) { - 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 = comboBounds.top + comboBounds.height - containerBounds.top - popupBounds.height; - } else if (needAdaptHeight) { - top = 0 - containerBounds.top; - adaptHeight = comboBounds.top + comboBounds.height - extraHeight; - } else if (BI.DOM.isBottomSpaceEnough(combo, popup, -1 * comboBounds.height + extraHeight)) { - // 上方空间不足且不允许调整高度的情况下,优先使用下对齐 - top = comboBounds.top - containerBounds.top + extraHeight; - dir = "bottom"; - } else { - top = 0; - if (popupBounds.height + extraHeight > windowBounds.height) { - adaptHeight = windowBounds.height - extraHeight; - } - } - if (top + containerBounds.top < 0) { - top = 0; - } - return adaptHeight ? { - top: top, - adaptHeight: adaptHeight, - dir: dir || "top" - } : { - top: top, - dir: dir || "top" - }; - }, - - getBottomAdaptPosition: function (combo, popup, extraHeight, needAdaptHeight, positionRelativeElement) { - var comboBounds = combo.element[0].getBoundingClientRect(), - popupBounds = popup.element[0].getBoundingClientRect(), - viewportBounds = document.documentElement.getBoundingClientRect(), - positionRelativeElementRect = positionRelativeElement.getBoundingClientRect(); - if (BI.DOM.isBottomSpaceEnough(combo, popup, extraHeight)) { - return BI.DOM.getBottomPosition(combo, popup, extraHeight, positionRelativeElement); - } - if (needAdaptHeight) { - return { - top: comboBounds.top + comboBounds.height + extraHeight - positionRelativeElementRect.top, - adaptHeight: viewportBounds.height - comboBounds.top - comboBounds.height - extraHeight - }; - } - if (popupBounds.height + extraHeight > viewportBounds.height) { - return { - top: extraHeight - positionRelativeElementRect.top, - adaptHeight: viewportBounds.height - extraHeight - }; - } - return { - top: viewportBounds.height - popupBounds.height - extraHeight - positionRelativeElementRect.top - }; - }, - - getCenterAdaptPosition: function (combo, popup, positionRelativeElement) { - var comboRect = combo.element[0].getBoundingClientRect(), - popupRect = popup.element[0].getBoundingClientRect(), - positionRelativeElementRect = positionRelativeElement.getBoundingClientRect(), - viewportBounds = document.documentElement.getBoundingClientRect(); - var left; - if (comboRect.left + comboRect.width / 2 + popupRect.width / 2 > viewportBounds.width) { - left = viewportBounds.width - popupRect.width - positionRelativeElementRect.left; - } else { - left = comboRect.left + (comboRect.width - popupRect.width) / 2 - positionRelativeElementRect.left; - } - if (left + positionRelativeElementRect.left < 0) { - left = 0; - } - return { - left: left - }; - }, - - getMiddleAdaptPosition: function (combo, popup, positionRelativeElement) { - var comboRect = combo.element[0].getBoundingClientRect(), - popupRect = popup.element[0].getBoundingClientRect(), - positionRelativeElementRect = positionRelativeElement.getBoundingClientRect(), - viewportBounds = document.documentElement.getBoundingClientRect(); - - var top; - if (comboRect.top + comboRect.height / 2 + popupRect.height / 2 > viewportBounds.height) { - top = viewportBounds.height - popupRect.height - positionRelativeElementRect.top; - } else { - top = comboRect.top + (comboRect.height - popupRect.height) / 2 - positionRelativeElementRect.top; - } - if (top + positionRelativeElementRect.top < 0) { - top = 0; - } - return { - top: top - }; - }, - - getComboPositionByDirections: function (combo, popup, extraWidth, extraHeight, needAdaptHeight, directions, container) { - extraWidth || (extraWidth = 0); - extraHeight || (extraHeight = 0); - var i, direct; - var leftRight = [], topBottom = [], innerLeftRight = []; - var isNeedAdaptHeight = false, tbFirst = false, lrFirst = false; - var left, top, pos, firstDir = directions[0]; - for (i = 0; i < directions.length; i++) { - direct = directions[i]; - switch (direct) { - case "left": - leftRight.push(direct); - break; - case "right": - leftRight.push(direct); - break; - case "top": - topBottom.push(direct); - break; - case "bottom": - topBottom.push(direct); - break; - case "innerLeft": - innerLeftRight.push(direct); - break; - case "innerRight": - innerLeftRight.push(direct); - break; - } - } - for (i = 0; i < directions.length; i++) { - direct = directions[i]; - switch (direct) { - case "left": - if (!isNeedAdaptHeight) { - var tW = tbFirst ? extraHeight : extraWidth, tH = tbFirst ? 0 : extraHeight; - if (BI.DOM.isLeftSpaceEnough(combo, popup, tW)) { - left = BI.DOM.getLeftPosition(combo, popup, tW, container).left; - if (topBottom[0] === "bottom") { - pos = BI.DOM.getTopAlignPosition(combo, popup, tH, needAdaptHeight, container); - } else { - pos = BI.DOM.getBottomAlignPosition(combo, popup, tH, needAdaptHeight, container); - } - pos.dir = "left," + pos.dir; - if (tbFirst) { - pos.change = "left"; - } - pos.left = left; - return pos; - } - } - lrFirst = true; - break; - case "right": - if (!isNeedAdaptHeight) { - var tW = tbFirst ? extraHeight : extraWidth, tH = tbFirst ? extraWidth : extraHeight; - if (BI.DOM.isRightSpaceEnough(combo, popup, tW)) { - left = BI.DOM.getRightPosition(combo, popup, tW, container).left; - if (topBottom[0] === "bottom") { - pos = BI.DOM.getTopAlignPosition(combo, popup, tH, needAdaptHeight, container); - } else { - pos = BI.DOM.getBottomAlignPosition(combo, popup, tH, needAdaptHeight, container); - } - pos.dir = "right," + pos.dir; - if (tbFirst) { - pos.change = "right"; - } - pos.left = left; - return pos; - } - } - lrFirst = true; - break; - case "top": - var tW = lrFirst ? extraHeight : extraWidth, tH = lrFirst ? extraWidth : extraHeight; - if (BI.DOM.isTopSpaceEnough(combo, popup, tH)) { - top = BI.DOM.getTopPosition(combo, popup, tH, container).top; - if (leftRight[0] === "right") { - pos = BI.DOM.getLeftAlignPosition(combo, popup, tW, container); - } else { - pos = BI.DOM.getRightAlignPosition(combo, popup, tW, container); - } - pos.dir = "top," + pos.dir; - if (lrFirst) { - pos.change = "top"; - } - pos.top = top; - return pos; - } - if (needAdaptHeight) { - isNeedAdaptHeight = true; - } - tbFirst = true; - break; - case "bottom": - var tW = lrFirst ? extraHeight : extraWidth, tH = lrFirst ? extraWidth : extraHeight; - if (BI.DOM.isBottomSpaceEnough(combo, popup, tH)) { - top = BI.DOM.getBottomPosition(combo, popup, tH, container).top; - if (leftRight[0] === "right") { - pos = BI.DOM.getLeftAlignPosition(combo, popup, tW, container); - } else { - pos = BI.DOM.getRightAlignPosition(combo, popup, tW, container); - } - pos.dir = "bottom," + pos.dir; - if (lrFirst) { - pos.change = "bottom"; - } - pos.top = top; - return pos; +} + +export function getTextSizeWidth(text, fontSize = 12) { + const span = BI.Widget._renderEngine.createElement("").addClass("text-width-span").appendTo("body"); + + fontSize = `${fontSize}px`; + + span.css("font-size", fontSize).text(text); + + const width = span.width(); + span.remove(); + + return width; +} + +export function getTextSizeHeight(text, fontSize = 12) { + const span = BI.Widget._renderEngine.createElement("").addClass("text-width-span").appendTo("body"); + + fontSize = `${fontSize}px`; + + span.css("font-size", fontSize).text(text); + + const height = span.height(); + span.remove(); + + return height; +} + +// 获取滚动条的宽度,页面display: none时候获取到的为0 +let _scrollWidth = null; + +export function getScrollWidth() { + if (isNull(_scrollWidth) || _scrollWidth === 0) { + const ul = BI.Widget._renderEngine.createElement("
").width(50).height(50) + .css({ + position: "absolute", + top: "-9999px", + overflow: "scroll", + }) + .appendTo("body"); + _scrollWidth = ul[0].offsetWidth - ul[0].clientWidth; + ul.destroy(); + } + + return _scrollWidth; +} + +export function getImage(param, fillStyle, backgroundColor) { + const canvas = document.createElement("canvas"); + const ratio = 2; + BI.Widget._renderEngine.createElement("body").append(canvas); + + const ctx = canvas.getContext("2d"); + ctx.font = "12px Helvetica Neue,Arial,PingFang SC,Hiragino Sans GB,Microsoft YaHei,微软雅黑,Heiti,黑体,sans-serif"; + const w = ctx.measureText(param).width + 4; + canvas.width = w * ratio; + canvas.height = 16 * ratio; + ctx.font = `${12 * ratio}px Helvetica Neue,Arial,PingFang SC,Hiragino Sans GB,Microsoft YaHei,微软雅黑,Heiti,黑体,sans-serif`; + ctx.fillStyle = fillStyle || "#3685f2"; + ctx.textBaseline = "middle"; + // ctx.fillStyle = "#EAF2FD"; + ctx.fillText(param, 2 * ratio, 9 * ratio); + BI.Widget._renderEngine.createElement(canvas).destroy(); + const backColor = backgroundColor || "rgba(54, 133, 242, 0.1)"; + + // IE可以放大缩小所以要固定最大最小宽高 + return { + width: w, + height: 16, + src: canvas.toDataURL("image/png"), + style: `background-color: ${backColor};vertical-align: middle; margin: 0 1px; width:${w}px;height: 16px; max-width:${w}px;max-height: 16px; min-width:${w}px;min-height: 16px`, + param, + }; +} + +export function getLeftPosition(combo, popup, extraWidth, container) { + const el = combo.element; + const popupEl = popup.element; + const elRect = el[0].getBoundingClientRect(); + const popupElRect = popupEl[0].getBoundingClientRect(); + const containerRect = container ? container.getBoundingClientRect() : { left: 0 }; + + return { + left: elRect.left - containerRect.left - popupElRect.width - (extraWidth || 0), + }; +} + +export function getInnerLeftPosition(combo, popup, extraWidth) { + return { + left: combo.element.offset().left + (extraWidth || 0), + }; +} + +export function getRightPosition(combo, popup, extraWidth, container) { + const el = combo.element; + const elRect = el[0].getBoundingClientRect(); + const containerRect = container ? container.getBoundingClientRect() : { left: 0 }; + + return { + left: elRect.left + elRect.width - containerRect.left + (extraWidth || 0), + }; +} + +export function getInnerRightPosition(combo, popup, extraWidth) { + const el = combo.element, viewBounds = popup.element.bounds(); + + return { + left: el.offset().left + el.outerWidth() - viewBounds.width - (extraWidth || 0), + }; +} + +export function getTopPosition(combo, popup, extraHeight, container) { + const el = combo.element; + const popupEl = popup.element; + const elRect = el[0].getBoundingClientRect(); + const popupElRect = popupEl[0].getBoundingClientRect(); + const containerRect = container ? container.getBoundingClientRect() : { top: 0 }; + + return { + top: elRect.top - containerRect.top - popupElRect.height - (extraHeight || 0), + }; +} + +export function getBottomPosition(combo, popup, extraHeight, container) { + const el = combo.element; + const elRect = el[0].getBoundingClientRect(); + const containerRect = container ? container.getBoundingClientRect() : { top: 0 }; + + return { + top: elRect.top - containerRect.top + elRect.height + (extraHeight || 0), + }; +} + +export function isLeftSpaceEnough(combo, popup, extraWidth) { + return getLeftPosition(combo, popup, extraWidth).left >= 0; +} + +export function isInnerLeftSpaceEnough(combo, popup, extraWidth) { + const viewBounds = popup.element.bounds(), + windowBounds = BI.Widget._renderEngine.createElement("body").bounds(); + + return getInnerLeftPosition(combo, popup, extraWidth).left + viewBounds.width <= windowBounds.width; +} + +export function isRightSpaceEnough(combo, popup, extraWidth) { + const viewBounds = popup.element[0].getBoundingClientRect(), + viewportBounds = document.documentElement.getBoundingClientRect(); + + return getRightPosition(combo, popup, extraWidth).left + viewBounds.width <= viewportBounds.width; +} + +export function isInnerRightSpaceEnough(combo, popup, extraWidth) { + return getInnerRightPosition(combo, popup, extraWidth).left >= 0; +} + +export function isTopSpaceEnough(combo, popup, extraHeight) { + return getTopPosition(combo, popup, extraHeight).top >= 0; +} + +export function isBottomSpaceEnough(combo, popup, extraHeight) { + const viewBounds = popup.element[0].getBoundingClientRect(), + viewportBounds = document.documentElement.getBoundingClientRect(); + + return getBottomPosition(combo, popup, extraHeight).top + viewBounds.height <= viewportBounds.height; +} + +export function isRightSpaceLarger(combo) { + const comboBounds = combo.element[0].getBoundingClientRect(), + viewportBounds = document.documentElement.getBoundingClientRect(); + + return viewportBounds.width - comboBounds.right >= comboBounds.left; +} + +export function isBottomSpaceLarger(combo) { + const comboBounds = combo.element[0].getBoundingClientRect(), + viewportBounds = document.documentElement.getBoundingClientRect(); + + return viewportBounds.height - comboBounds.bottom >= comboBounds.top; +} + +export function _getLeftAlignPosition(combo, popup, extraWidth, container) { + const comboRect = combo.element[0].getBoundingClientRect(), + popupRect = popup.element[0].getBoundingClientRect(), + viewportRect = document.documentElement.getBoundingClientRect(), + containerRect = container ? container.getBoundingClientRect() : { left: 0 }; + let left = comboRect.left - containerRect.left + extraWidth; + + if (comboRect.left + popupRect.width > viewportRect.width) { + left = viewportRect.width - popupRect.width - containerRect.left; + } + + return left; +} + +export function getLeftAlignPosition(combo, popup, extraWidth, container) { + let left = this._getLeftAlignPosition(combo, popup, extraWidth, container); + let dir = ""; + // 如果放不下,优先使用RightAlign, 如果RightAlign也放不下, 再使用left=0 + const containerRect = container ? container.getBoundingClientRect() : { left: 0 }; + if (left + containerRect.left < 0) { + left = this._getRightAlignPosition(combo, popup, extraWidth); + dir = "left"; + } + if (left + containerRect.left < 0) { + left = 0 - containerRect.left; + } + + return { + left, + dir: dir || "right", + }; +} + +export function getLeftAdaptPosition(combo, popup, extraWidth, container) { + if (isLeftSpaceEnough(combo, popup, extraWidth, container)) { + return getLeftPosition(combo, popup, extraWidth, container); + } + + return { + left: 0, + }; +} + +export function _getRightAlignPosition(combo, popup, extraWidth, container) { + const comboBounds = combo.element[0].getBoundingClientRect(), + viewBounds = popup.element[0].getBoundingClientRect(), + containerRect = container ? container.getBoundingClientRect() : { left: 0 }; + + return comboBounds.left + comboBounds.width - viewBounds.width - extraWidth - containerRect.left; +} + +export function getRightAlignPosition(combo, popup, extraWidth, container) { + let left = this._getRightAlignPosition(combo, popup, extraWidth, container); + let dir = ""; + // 如果放不下,优先使用LeftAlign, 如果LeftAlign也放不下, 再使用left=0 + if (left < 0) { + left = this._getLeftAlignPosition(combo, popup, extraWidth, container); + dir = "right"; + } + if (left < 0) { + left = 0; + } + + return { + left, + dir: dir || "left", + }; +} + +export function getRightAdaptPosition(combo, popup, extraWidth, container) { + if (isRightSpaceEnough(combo, popup, extraWidth, container)) { + return getRightPosition(combo, popup, extraWidth, container); + } + + return { + left: document.documentElement.getBoundingClientRect().width - popup.element[0].getBoundingClientRect().width - container.getBoundingClientRect().left, + }; +} + +export function getTopAlignPosition(combo, popup, extraHeight, needAdaptHeight, container) { + const comboBounds = combo.element[0].getBoundingClientRect(), + popupBounds = popup.element[0].getBoundingClientRect(), + viewportBounds = document.documentElement.getBoundingClientRect(), + containerBounds = container ? container.getBoundingClientRect() : { top: 0 }; + let top, adaptHeight, dir; + if (isBottomSpaceEnough(combo, popup, -1 * comboBounds.height + extraHeight)) { + top = comboBounds.top - containerBounds.top + extraHeight; + } else if (needAdaptHeight) { + top = comboBounds.top - containerBounds.top + extraHeight; + adaptHeight = viewportBounds.height - comboBounds.top; + } else if (isTopSpaceEnough(combo, popup, -1 * comboBounds.height + extraHeight)) { + // 下方空间不足且不允许调整高度的情况下,优先使用上对齐 + top = comboBounds.top + comboBounds.height - popupBounds.height - containerBounds.top - extraHeight; + dir = "top"; + } else { + top = viewportBounds.height - popupBounds.height; + if (top < extraHeight) { + adaptHeight = viewportBounds.height - extraHeight; + } + } + if (top < extraHeight) { + top = extraHeight; + } + + return adaptHeight ? { + top, + adaptHeight, + dir: dir || "bottom", + } : { + top, + dir: dir || "bottom", + }; +} + +export function getTopAdaptPosition(combo, popup, extraHeight, needAdaptHeight, positionRelativeElement) { + const comboBounds = combo.element[0].getBoundingClientRect(), + popupBounds = popup.element[0].getBoundingClientRect(), + positionRelativeElementRect = positionRelativeElement.getBoundingClientRect(), + viewportBounds = document.documentElement.getBoundingClientRect(); + if (isTopSpaceEnough(combo, popup, extraHeight)) { + return getTopPosition(combo, popup, extraHeight); + } + if (needAdaptHeight) { + return { + top: 0 - positionRelativeElementRect.top, + adaptHeight: comboBounds.top - extraHeight, + }; + } + if (popupBounds.height + extraHeight > viewportBounds.height) { + return { + top: 0 - positionRelativeElementRect.top, + adaptHeight: viewportBounds.height - extraHeight, + }; + } + + return { + top: 0 - positionRelativeElementRect.top, + }; +} + +export function getBottomAlignPosition(combo, popup, extraHeight, needAdaptHeight, container) { + const comboBounds = combo.element[0].getBoundingClientRect(), + popupBounds = popup.element[0].getBoundingClientRect(), + windowBounds = BI.Widget._renderEngine.createElement("body").bounds(), + containerBounds = container ? container.getBoundingClientRect() : { top: 0 }; + let top, adaptHeight, dir; + if (isTopSpaceEnough(combo, popup, -1 * comboBounds.height + extraHeight)) { + top = comboBounds.top + comboBounds.height - containerBounds.top - popupBounds.height; + } else if (needAdaptHeight) { + top = 0 - containerBounds.top; + adaptHeight = comboBounds.top + comboBounds.height - extraHeight; + } else if (isBottomSpaceEnough(combo, popup, -1 * comboBounds.height + extraHeight)) { + // 上方空间不足且不允许调整高度的情况下,优先使用下对齐 + top = comboBounds.top - containerBounds.top + extraHeight; + dir = "bottom"; + } else { + top = 0; + if (popupBounds.height + extraHeight > windowBounds.height) { + adaptHeight = windowBounds.height - extraHeight; + } + } + if (top + containerBounds.top < 0) { + top = 0; + } + + return adaptHeight ? { + top, + adaptHeight, + dir: dir || "top", + } : { + top, + dir: dir || "top", + }; +} + +export function getBottomAdaptPosition(combo, popup, extraHeight, needAdaptHeight, positionRelativeElement) { + const comboBounds = combo.element[0].getBoundingClientRect(), + popupBounds = popup.element[0].getBoundingClientRect(), + viewportBounds = document.documentElement.getBoundingClientRect(), + positionRelativeElementRect = positionRelativeElement.getBoundingClientRect(); + if (isBottomSpaceEnough(combo, popup, extraHeight)) { + return getBottomPosition(combo, popup, extraHeight, positionRelativeElement); + } + if (needAdaptHeight) { + return { + top: comboBounds.top + comboBounds.height + extraHeight - positionRelativeElementRect.top, + adaptHeight: viewportBounds.height - comboBounds.top - comboBounds.height - extraHeight, + }; + } + if (popupBounds.height + extraHeight > viewportBounds.height) { + return { + top: extraHeight - positionRelativeElementRect.top, + adaptHeight: viewportBounds.height - extraHeight, + }; + } + + return { + top: viewportBounds.height - popupBounds.height - extraHeight - positionRelativeElementRect.top, + }; +} + +export function getCenterAdaptPosition(combo, popup, positionRelativeElement) { + const comboRect = combo.element[0].getBoundingClientRect(), + popupRect = popup.element[0].getBoundingClientRect(), + positionRelativeElementRect = positionRelativeElement.getBoundingClientRect(), + viewportBounds = document.documentElement.getBoundingClientRect(); + let left; + if (comboRect.left + comboRect.width / 2 + popupRect.width / 2 > viewportBounds.width) { + left = viewportBounds.width - popupRect.width - positionRelativeElementRect.left; + } else { + left = comboRect.left + (comboRect.width - popupRect.width) / 2 - positionRelativeElementRect.left; + } + if (left + positionRelativeElementRect.left < 0) { + left = 0; + } + + return { + left, + }; +} + +export function getMiddleAdaptPosition(combo, popup, positionRelativeElement) { + const comboRect = combo.element[0].getBoundingClientRect(), + popupRect = popup.element[0].getBoundingClientRect(), + positionRelativeElementRect = positionRelativeElement.getBoundingClientRect(), + viewportBounds = document.documentElement.getBoundingClientRect(); + + let top; + if (comboRect.top + comboRect.height / 2 + popupRect.height / 2 > viewportBounds.height) { + top = viewportBounds.height - popupRect.height - positionRelativeElementRect.top; + } else { + top = comboRect.top + (comboRect.height - popupRect.height) / 2 - positionRelativeElementRect.top; + } + if (top + positionRelativeElementRect.top < 0) { + top = 0; + } + + return { + top, + }; +} + +export function getComboPositionByDirections(combo, popup, extraWidth, extraHeight, needAdaptHeight, directions, container) { + extraWidth || (extraWidth = 0); + extraHeight || (extraHeight = 0); + let i, direct; + const leftRight = [], topBottom = [], innerLeftRight = []; + let isNeedAdaptHeight = false, tbFirst = false, lrFirst = false; + let left, top, pos, firstDir = directions[0]; + for (i = 0; i < directions.length; i++) { + direct = directions[i]; + switch (direct) { + case "left": + leftRight.push(direct); + break; + case "right": + leftRight.push(direct); + break; + case "top": + topBottom.push(direct); + break; + case "bottom": + topBottom.push(direct); + break; + case "innerLeft": + innerLeftRight.push(direct); + break; + case "innerRight": + innerLeftRight.push(direct); + break; + default: + break; + } + } + for (i = 0; i < directions.length; i++) { + direct = directions[i]; + switch (direct) { + case "left": + if (!isNeedAdaptHeight) { + var tW = tbFirst ? extraHeight : extraWidth, tH = tbFirst ? 0 : extraHeight; + if (isLeftSpaceEnough(combo, popup, tW)) { + left = getLeftPosition(combo, popup, tW, container).left; + if (topBottom[0] === "bottom") { + pos = getTopAlignPosition(combo, popup, tH, needAdaptHeight, container); + } else { + pos = getBottomAlignPosition(combo, popup, tH, needAdaptHeight, container); } - if (needAdaptHeight) { - isNeedAdaptHeight = true; + pos.dir = `left,${pos.dir}`; + if (tbFirst) { + pos.change = "left"; } - tbFirst = true; - break; - case "innerLeft": - if (!isNeedAdaptHeight) { - var tW = tbFirst ? extraHeight : extraWidth, tH = tbFirst ? 0 : extraHeight; - if (BI.DOM.isInnerLeftSpaceEnough(combo, popup, tW)) { - left = BI.DOM.getInnerLeftPosition(combo, popup, tW).left; - if (topBottom[0] === "bottom") { - pos = BI.DOM.getTopAlignPosition(combo, popup, tH, needAdaptHeight); - } else { - pos = BI.DOM.getBottomAlignPosition(combo, popup, tH, needAdaptHeight); - } - pos.dir = "innerLeft," + pos.dir; - if (tbFirst) { - pos.change = "innerLeft"; - } - pos.left = left; - return pos; - } + pos.left = left; + + return pos; + } + } + lrFirst = true; + break; + case "right": + if (!isNeedAdaptHeight) { + var tW = tbFirst ? extraHeight : extraWidth, tH = tbFirst ? extraWidth : extraHeight; + if (isRightSpaceEnough(combo, popup, tW)) { + left = getRightPosition(combo, popup, tW, container).left; + if (topBottom[0] === "bottom") { + pos = getTopAlignPosition(combo, popup, tH, needAdaptHeight, container); + } else { + pos = getBottomAlignPosition(combo, popup, tH, needAdaptHeight, container); } - lrFirst = true; - break; - case "innerRight": - if (!isNeedAdaptHeight) { - var tW = tbFirst ? extraHeight : extraWidth, tH = tbFirst ? extraWidth : extraHeight; - if (BI.DOM.isInnerRightSpaceEnough(combo, popup, tW)) { - left = BI.DOM.getInnerRightPosition(combo, popup, tW).left; - if (topBottom[0] === "bottom") { - pos = BI.DOM.getTopAlignPosition(combo, popup, tH, needAdaptHeight); - } else { - pos = BI.DOM.getBottomAlignPosition(combo, popup, tH, needAdaptHeight); - } - pos.dir = "innerLeft," + pos.dir; - if (tbFirst) { - pos.change = "innerRight"; - } - pos.left = left; - return pos; - } + pos.dir = `right,${pos.dir}`; + if (tbFirst) { + pos.change = "right"; } - break; + pos.left = left; + return pos; + } } - } - - // 此处为四个方向放不下时挑空间最大的方向去放置, 也就是说我设置了弹出方向为"bottom,left", - // 最后发现实际弹出方向可能是"top,left",那么此时外界获取popup的方向应该是"top,left" - switch (directions[0]) { - case "left": - case "right": - if (BI.DOM.isRightSpaceLarger(combo)) { - left = BI.DOM.getRightAdaptPosition(combo, popup, extraWidth, container).left; - firstDir = "right"; + lrFirst = true; + break; + case "top": + var tW = lrFirst ? extraHeight : extraWidth, tH = lrFirst ? extraWidth : extraHeight; + if (isTopSpaceEnough(combo, popup, tH)) { + top = getTopPosition(combo, popup, tH, container).top; + if (leftRight[0] === "right") { + pos = getLeftAlignPosition(combo, popup, tW, container); } else { - left = BI.DOM.getLeftAdaptPosition(combo, popup, extraWidth, container).left; - firstDir = "left"; + pos = getRightAlignPosition(combo, popup, tW, container); } - if (topBottom[0] === "bottom") { - pos = BI.DOM.getTopAlignPosition(combo, popup, extraHeight, needAdaptHeight); - pos.left = left; - pos.dir = firstDir + "," + pos.dir; - return pos; + pos.dir = `top,${pos.dir}`; + if (lrFirst) { + pos.change = "top"; } - pos = BI.DOM.getBottomAlignPosition(combo, popup, extraHeight, needAdaptHeight); - pos.left = left; - pos.dir = firstDir + "," + pos.dir; + pos.top = top; + return pos; - default : - if (BI.DOM.isBottomSpaceLarger(combo)) { - top = BI.DOM.getBottomAdaptPosition(combo, popup, extraHeight, needAdaptHeight, container).top; - firstDir = "bottom"; + } + if (needAdaptHeight) { + isNeedAdaptHeight = true; + } + tbFirst = true; + break; + case "bottom": + var tW = lrFirst ? extraHeight : extraWidth, tH = lrFirst ? extraWidth : extraHeight; + if (isBottomSpaceEnough(combo, popup, tH)) { + top = getBottomPosition(combo, popup, tH, container).top; + if (leftRight[0] === "right") { + pos = getLeftAlignPosition(combo, popup, tW, container); } else { - top = BI.DOM.getTopAdaptPosition(combo, popup, extraHeight, needAdaptHeight, container).top; - firstDir = "top"; + pos = getRightAlignPosition(combo, popup, tW, container); } - if (leftRight[0] === "right") { - pos = BI.DOM.getLeftAlignPosition(combo, popup, extraWidth, container); - pos.top = top; - pos.dir = firstDir + "," + pos.dir; - return pos; + pos.dir = `bottom,${pos.dir}`; + if (lrFirst) { + pos.change = "bottom"; } - pos = BI.DOM.getRightAlignPosition(combo, popup, extraWidth, container); pos.top = top; - pos.dir = firstDir + "," + pos.dir; + return pos; - } - }, - - - getComboPosition: function (combo, popup, extraWidth, extraHeight, needAdaptHeight, directions, offsetStyle, positionRelativeElement) { - extraWidth || (extraWidth = 0); - extraHeight || (extraHeight = 0); - var viewportBounds = document.documentElement.getBoundingClientRect(); - var maxHeight = Math.min(popup.attr("maxHeight") || viewportBounds.height, viewportBounds.height); - popup.resetHeight && popup.resetHeight(maxHeight); - var position = BI.DOM.getComboPositionByDirections(combo, popup, extraWidth, extraHeight, needAdaptHeight, directions || ["bottom", "top", "right", "left"], positionRelativeElement); - switch (offsetStyle) { - case "center": - if (position.change) { - var p = BI.DOM.getMiddleAdaptPosition(combo, popup, positionRelativeElement); - position.top = p.top; - } else { - var p = BI.DOM.getCenterAdaptPosition(combo, popup, positionRelativeElement); - position.left = p.left; + } + if (needAdaptHeight) { + isNeedAdaptHeight = true; + } + tbFirst = true; + break; + case "innerLeft": + if (!isNeedAdaptHeight) { + var tW = tbFirst ? extraHeight : extraWidth, tH = tbFirst ? 0 : extraHeight; + if (isInnerLeftSpaceEnough(combo, popup, tW)) { + left = getInnerLeftPosition(combo, popup, tW).left; + if (topBottom[0] === "bottom") { + pos = getTopAlignPosition(combo, popup, tH, needAdaptHeight); + } else { + pos = getBottomAlignPosition(combo, popup, tH, needAdaptHeight); + } + pos.dir = `innerLeft,${pos.dir}`; + if (tbFirst) { + pos.change = "innerLeft"; + } + pos.left = left; + + return pos; } - break; - case "middle": - if (position.change) { - var p = BI.DOM.getCenterAdaptPosition(combo, popup, positionRelativeElement); - position.left = p.left; - } else { - var p = BI.DOM.getMiddleAdaptPosition(combo, popup, positionRelativeElement); - position.top = p.top; + } + lrFirst = true; + break; + case "innerRight": + if (!isNeedAdaptHeight) { + var tW = tbFirst ? extraHeight : extraWidth, tH = tbFirst ? extraWidth : extraHeight; + if (isInnerRightSpaceEnough(combo, popup, tW)) { + left = getInnerRightPosition(combo, popup, tW).left; + if (topBottom[0] === "bottom") { + pos = getTopAlignPosition(combo, popup, tH, needAdaptHeight); + } else { + pos = getBottomAlignPosition(combo, popup, tH, needAdaptHeight); + } + pos.dir = `innerLeft,${pos.dir}`; + if (tbFirst) { + pos.change = "innerRight"; + } + pos.left = left; + + return pos; } - break; + } + break; + default: + break; + } + } + + // 此处为四个方向放不下时挑空间最大的方向去放置, 也就是说我设置了弹出方向为"bottom,left", + // 最后发现实际弹出方向可能是"top,left",那么此时外界获取popup的方向应该是"top,left" + switch (directions[0]) { + case "left": + case "right": + if (isRightSpaceLarger(combo)) { + left = getRightAdaptPosition(combo, popup, extraWidth, container).left; + firstDir = "right"; + } else { + left = getLeftAdaptPosition(combo, popup, extraWidth, container).left; + firstDir = "left"; } - if (needAdaptHeight === true) { - popup.resetHeight && popup.resetHeight(Math.min(viewportBounds.height - position.top - (positionRelativeElement ? positionRelativeElement.getBoundingClientRect().top : 0), maxHeight)); + if (topBottom[0] === "bottom") { + pos = getTopAlignPosition(combo, popup, extraHeight, needAdaptHeight); + pos.left = left; + pos.dir = `${firstDir},${pos.dir}`; + + return pos; } - 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; + pos = getBottomAlignPosition(combo, popup, extraHeight, needAdaptHeight); + pos.left = left; + pos.dir = `${firstDir},${pos.dir}`; + + return pos; + default : + if (isBottomSpaceLarger(combo)) { + top = getBottomAdaptPosition(combo, popup, extraHeight, needAdaptHeight, container).top; + firstDir = "bottom"; + } else { + top = getTopAdaptPosition(combo, popup, extraHeight, needAdaptHeight, container).top; + firstDir = "top"; + } + if (leftRight[0] === "right") { + pos = getLeftAlignPosition(combo, popup, extraWidth, container); + pos.top = top; + pos.dir = `${firstDir},${pos.dir}`; + + return pos; + } + pos = getRightAlignPosition(combo, popup, extraWidth, container); + pos.top = top; + pos.dir = `${firstDir},${pos.dir}`; + + return pos; + } +} + + +export function getComboPosition(combo, popup, extraWidth, extraHeight, needAdaptHeight, directions, offsetStyle, positionRelativeElement) { + extraWidth || (extraWidth = 0); + extraHeight || (extraHeight = 0); + const viewportBounds = document.documentElement.getBoundingClientRect(); + const maxHeight = Math.min(popup.attr("maxHeight") || viewportBounds.height, viewportBounds.height); + popup.resetHeight && popup.resetHeight(maxHeight); + const position = getComboPositionByDirections(combo, popup, extraWidth, extraHeight, needAdaptHeight, directions || ["bottom", "top", "right", "left"], positionRelativeElement); + switch (offsetStyle) { + case "center": + if (position.change) { + var p = getMiddleAdaptPosition(combo, popup, positionRelativeElement); + position.top = p.top; + } else { + var p = getCenterAdaptPosition(combo, popup, positionRelativeElement); + position.left = p.left; + } + break; + case "middle": + if (position.change) { + var p = getCenterAdaptPosition(combo, popup, positionRelativeElement); + position.left = p.left; + } else { + var p = getMiddleAdaptPosition(combo, popup, positionRelativeElement); + position.top = p.top; } + break; + default: + break; + } + if (needAdaptHeight === true) { + popup.resetHeight && popup.resetHeight(Math.min(viewportBounds.height - position.top - (positionRelativeElement ? positionRelativeElement.getBoundingClientRect().top : 0), maxHeight)); + } - 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 position; +} - return [transform, perspective, filter].some(value => value !== 'none') || (willChange === "transform"); - } +/** + * 获取position:fixed相对定位的元素 + */ +export function getPositionRelativeContainingBlock(element) { + if (["html", "body", "#document"].indexOf((element.nodeName || "").toLowerCase()) >= 0) { + // $FlowFixMe[incompatible-return]: assume body is always available + return element.ownerDocument.body; + } - if (isExcept(element)) { - return element; - } + function isExcept(node) { + const _computedStyle = getComputedStyle(node); + const transform = _computedStyle.transform; + const perspective = _computedStyle.perspective; + const filter = _computedStyle.filter; + const willChange = _computedStyle["will-change"]; - return BI.DOM.getPositionRelativeContainingBlock(element.parentNode); - }, - - /** - * 获取position:fixed相对定位的元素的clientRect - */ - getPositionRelativeContainingBlockRect: function (element) { - var positionRelativeElement = BI.DOM.getPositionRelativeContainingBlock(element); - var rect = positionRelativeElement.getBoundingClientRect(); - - return { - ...rect.toJSON(), - scaleX: rect.width / positionRelativeElement.offsetWidth, - scaleY: rect.height / positionRelativeElement.offsetHeight - }; - }, - }); -})(); + return [transform, perspective, filter].some(value => value !== "none") || (willChange === "transform"); + } + + if (isExcept(element)) { + return element; + } + + return getPositionRelativeContainingBlock(element.parentNode); +} + +/** + * 获取position:fixed相对定位的元素的clientRect + */ +export function getPositionRelativeContainingBlockRect(element) { + const positionRelativeElement = getPositionRelativeContainingBlock(element); + const rect = positionRelativeElement.getBoundingClientRect(); + + return { + ...rect.toJSON(), + scaleX: rect.width / positionRelativeElement.offsetWidth, + scaleY: rect.height / positionRelativeElement.offsetHeight, + }; +} diff --git a/src/core/platform/web/function.js b/src/core/platform/web/function.js index f05ef923d..2044e4160 100644 --- a/src/core/platform/web/function.js +++ b/src/core/platform/web/function.js @@ -1,151 +1,170 @@ // 浏览器相关方法 -BI._.extend(BI, { - isIE: function () { - if(!_global.navigator) { - return false; - } - if (this.__isIE == null) { - this.__isIE = /(msie|trident)/i.test(navigator.userAgent.toLowerCase()); - } - return this.__isIE; - }, +import { isString } from "../../2.base"; - getIEVersion: function () { - if(!_global.navigator) { - return 0; - } - if (this.__IEVersion != null) { - return this.__IEVersion; - } - var version = 0; - var agent = navigator.userAgent.toLowerCase(); - var v1 = agent.match(/(?:msie\s([\w.]+))/); - var v2 = agent.match(/(?:trident.*rv:([\w.]+))/); - if (v1 && v2 && v1[1] && v2[1]) { - version = Math.max(v1[1] * 1, v2[1] * 1); - } else if (v1 && v1[1]) { - version = v1[1] * 1; - } else if (v2 && v2[1]) { - version = v2[1] * 1; - } else { - version = 0; - } - return this.__IEVersion = version; - }, +let __isIE; - isIE9Below: function () { - if (!BI.isIE()) { - return false; - } - return this.getIEVersion() < 9; - }, +export function isIE() { + if (!_global.navigator) { + return false; + } + if (!__isIE) { + __isIE = /(msie|trident)/i.test(navigator.userAgent.toLowerCase()); + } - isEdge: function () { - if(!_global.navigator) { - return false; - } - return /edg/i.test(navigator.userAgent.toLowerCase()); - }, + return __isIE; +} - isChrome: function () { - if(!_global.navigator) { - return false; - } - return /chrome/i.test(navigator.userAgent.toLowerCase()); - }, +let __IEVersion; - isFireFox: function () { - if(!_global.navigator) { - return false; - } - return /firefox/i.test(navigator.userAgent.toLowerCase()); - }, +export function getIEVersion() { + if (!_global.navigator) { + return 0; + } + if (__IEVersion) { + return __IEVersion; + } + let version = 0; + const agent = navigator.userAgent.toLowerCase(); + const v1 = agent.match(/(?:msie\s([\w.]+))/); + const v2 = agent.match(/(?:trident.*rv:([\w.]+))/); + if (v1 && v2 && v1[1] && v2[1]) { + version = Math.max(v1[1] * 1, v2[1] * 1); + } else if (v1 && v1[1]) { + version = v1[1] * 1; + } else if (v2 && v2[1]) { + version = v2[1] * 1; + } else { + version = 0; + } + __IEVersion = version; - isOpera: function () { - if(!_global.navigator) { - return false; - } - return /opera/i.test(navigator.userAgent.toLowerCase()); - }, + return __IEVersion; +} - isSafari: function () { - if(!_global.navigator) { - return false; - } - return /safari/i.test(navigator.userAgent.toLowerCase()) && !/chrome/i.test(navigator.userAgent.toLowerCase()); - }, +export function isIE9Below() { + if (!isIE()) { + return false; + } - isKhtml: function () { - if(!_global.navigator) { - return false; - } - return /Konqueror|Safari|KHTML/i.test(navigator.userAgent); - }, + return getIEVersion() < 9; +} - isMac: function () { - if(!_global.navigator) { - return false; - } - return /macintosh|mac os x/i.test(navigator.userAgent); - }, +export function isEdge() { + if (!_global.navigator) { + return false; + } - isWindows: function () { - if(!_global.navigator) { - return false; - } - return /windows|win32/i.test(navigator.userAgent); - }, + return /edg/i.test(navigator.userAgent.toLowerCase()); +} - isSupportCss3: function (style) { - if(!_global.document) { - return false; - } - var prefix = ["webkit", "Moz", "ms", "o"], - i, len, - humpString = [], - htmlStyle = document.documentElement.style, - _toHumb = function (string) { - if (!BI.isString(string)) { - return ""; - } - - return string.replace(/-(\w)/g, function ($0, $1) { - return $1.toUpperCase(); - }); - }; - - for ( i = 0; i < prefix.length; i++) { - humpString.push(_toHumb(prefix[i] + "-" + style)); - } - humpString.push(_toHumb(style)); +export function isChrome() { + if (!_global.navigator) { + return false; + } - for (i = 0, len = humpString.length; i < len; i++) { - if (humpString[i] in htmlStyle) { - return true; - } - } + return /chrome/i.test(navigator.userAgent.toLowerCase()); +} + +export function isFireFox() { + if (!_global.navigator) { + return false; + } + + return /firefox/i.test(navigator.userAgent.toLowerCase()); +} + +export function isOpera() { + if (!_global.navigator) { + return false; + } + + return /opera/i.test(navigator.userAgent.toLowerCase()); +} + +export function isSafari() { + if (!_global.navigator) { + return false; + } + + return /safari/i.test(navigator.userAgent.toLowerCase()) && !/chrome/i.test(navigator.userAgent.toLowerCase()); +} + +export function isKhtml() { + if (!_global.navigator) { + return false; + } + + return /Konqueror|Safari|KHTML/i.test(navigator.userAgent); +} + +export function isMac() { + if (!_global.navigator) { + return false; + } + + return /macintosh|mac os x/i.test(navigator.userAgent); +} + +export function isWindows() { + if (!_global.navigator) { return false; - }, + } + + return /windows|win32/i.test(navigator.userAgent); +} + +export function isSupportCss3(style) { + if (!_global.document) { + return false; + } + const prefix = ["webkit", "Moz", "ms", "o"]; + const humpString = []; + const htmlStyle = document.documentElement.style; + let i; + let len; - getSafariVersion: function () { - if (!_global.navigator) { - return 0; + function _toHumb(string) { + if (!isString(string)) { + return ""; } - var agent = navigator.userAgent.toLowerCase(); - var version = agent.match(/version\/([\d.]+)/); - if (version && version[1]) { - return version[1] * 1; + + return string.replace(/-(\w)/g, ($0, $1) => $1.toUpperCase()); + }; + + for (i = 0; i < prefix.length; i++) { + humpString.push(_toHumb(`${prefix[i]}-${style}`)); + } + humpString.push(_toHumb(style)); + + for (i = 0, len = humpString.length; i < len; i++) { + if (humpString[i] in htmlStyle) { + return true; } + } + + return false; +} + +export function getSafariVersion() { + if (!_global.navigator) { return 0; - }, - - getMinimumFontSize: function () { - // not work for firefox - const el = document.createElement('div'); - el.style.fontSize = "1px"; - document.body.appendChild(el); - const size = getComputedStyle(el).fontSize; - el.remove(); - return parseInt(size); - } -}); + } + const agent = navigator.userAgent.toLowerCase(); + const version = agent.match(/version\/([\d.]+)/); + if (version && version[1]) { + return version[1] * 1; + } + + return 0; +} + +export function getMinimumFontSize() { + // not work for firefox + const el = document.createElement("div"); + el.style.fontSize = "1px"; + document.body.appendChild(el); + const size = getComputedStyle(el).fontSize; + el.remove(); + + return parseInt(size, 10); +} diff --git a/src/core/platform/web/index.js b/src/core/platform/web/index.js new file mode 100644 index 000000000..6dcaf06ba --- /dev/null +++ b/src/core/platform/web/index.js @@ -0,0 +1,4 @@ +export * as DOM from "./dom"; +export * from "./detectElementResize"; +export * from "./function"; +export * from "./load"; diff --git a/src/core/platform/web/load.js b/src/core/platform/web/load.js index f367b8cf6..7ab3a490a 100644 --- a/src/core/platform/web/load.js +++ b/src/core/platform/web/load.js @@ -1,55 +1,56 @@ -BI._.extend(BI, { - $import: function () { - var _LOADED = {}; // alex:保存加载过的 - function loadReady (src, must) { - var $scripts = BI.$("head script, body script"); - BI.$.each($scripts, function (i, item) { - if (item.src.indexOf(src) != -1) { - _LOADED[src] = true; - } - }); - var $links = BI.$("head link"); - BI.$.each($links, function (i, item) { - if (item.href.indexOf(src) != -1 && must) { - _LOADED[src] = false; - BI.$(item).remove(); - } - }); +const _LOADED = {}; // alex:保存加载过的 +function loadReady(src, must) { + const $scripts = BI.$("head script, body script"); + BI.$.each($scripts, (i, item) => { + if (item.src.indexOf(src) !== -1) { + _LOADED[src] = true; } + }); + const $links = BI.$("head link"); + BI.$.each($links, (i, item) => { + if (item.href.indexOf(src) !== -1 && must) { + _LOADED[src] = false; + BI.$(item).remove(); + } + }); +} - // must=true 强行加载 - return function (src, ext, must) { - loadReady(src, must); - // alex:如果已经加载过了的,直接return - if (_LOADED[src] === true) { - return; - } - if (ext === "css") { - var link = document.createElement("link"); - link.rel = "stylesheet"; - link.type = "text/css"; - link.href = src; - var head = document.getElementsByTagName("head")[0]; - head.appendChild(link); - _LOADED[src] = true; - } else { - // alex:这里用同步调用的方式,必须等待ajax完成 - BI.$.ajax({ - url: src, - dataType: "script", // alex:指定dataType为script,jquery会帮忙做globalEval的事情 - async: false, - cache: true, - complete: function (res, status) { - /* - * alex:发现jquery会很智能地判断一下返回的数据类型是不是script,然后做一个globalEval - * 所以当status为success时就不需要再把其中的内容加到script里面去了 - */ - if (status == "success") { - _LOADED[src] = true; - } - } - }); - } - }; - }() -}); \ No newline at end of file +/** + * + * @param src + * @param ext + * @param must 强行加载 + */ +export function $import(src, ext, must) { + loadReady(src, must); + // alex:如果已经加载过了的,直接return + if (_LOADED[src] === true) { + return; + } + if (ext === "css") { + const link = document.createElement("link"); + link.rel = "stylesheet"; + link.type = "text/css"; + link.href = src; + const head = document.getElementsByTagName("head")[0]; + head.appendChild(link); + _LOADED[src] = true; + } else { + // alex:这里用同步调用的方式,必须等待ajax完成 + BI.$.ajax({ + url: src, + dataType: "script", // alex:指定dataType为script,jquery会帮忙做globalEval的事情 + async: false, + cache: true, + complete(res, status) { + /* + * alex:发现jquery会很智能地判断一下返回的数据类型是不是script,然后做一个globalEval + * 所以当status为success时就不需要再把其中的内容加到script里面去了 + */ + if (status === "success") { + _LOADED[src] = true; + } + }, + }); + } +}