@whitesev/pops
Version:
弹窗库,包含了alert、confirm、prompt、drawer、folder、loading、iframe、panel、tooltip、searchSuggestion、rightClickMenu组件
357 lines (337 loc) • 11.9 kB
text/typescript
import { GlobalConfig } from "../../config/GlobalConfig";
import { EventEmiter } from "../../event/EventEmiter";
import { PopsElementHandler } from "../../handler/PopsElementHandler";
import { PopsHandler } from "../../handler/PopsHandler";
import { PopsInstHandler } from "../../handler/PopsInstHandler";
import { PopsCSS } from "../../PopsCSS";
import { PopsInstData } from "../../PopsInst";
import type { PopsType } from "../../types/main";
import { popsDOMUtils } from "../../utils/PopsDOMUtils";
import { popsUtils } from "../../utils/PopsUtils";
import { PopsIframeDefaultConfig } from "./defaultConfig";
import type { PopsIframeClickEventConfig, PopsIframeConfig } from "./types";
export const PopsIframe = {
init(__config__: PopsIframeConfig) {
const guid = popsUtils.getRandomGUID();
// 设置当前类型
const popsType: PopsType = "iframe";
let config = PopsIframeDefaultConfig();
config = popsUtils.assign(config, GlobalConfig.getGlobalConfig());
config = popsUtils.assign(config, __config__);
if (config.url == null) {
throw new TypeError("config.url must not be null.");
}
config = PopsHandler.handleOnly(popsType, config);
const emitter =
config.emitter ??
new EventEmiter<{
"pops:iframe-min": (eventConfig: PopsIframeClickEventConfig, event: MouseEvent | PointerEvent) => void;
"pops:iframe-mise": (eventConfig: PopsIframeClickEventConfig, event: MouseEvent | PointerEvent) => void;
"pops:iframe-max": (eventConfig: PopsIframeClickEventConfig, event: MouseEvent | PointerEvent) => void;
}>(popsType);
const { $shadowContainer, $shadowRoot } = PopsHandler.handlerShadow(config);
PopsHandler.handleInit($shadowRoot, [
{
name: "index",
css: PopsCSS.index,
},
{
name: "ninePalaceGridPosition",
css: PopsCSS.ninePalaceGridPosition,
},
{
name: "scrollbar",
css: PopsCSS.scrollbar,
},
{
name: "anim",
css: PopsCSS.anim,
},
{
name: "common",
css: PopsCSS.common,
},
{
name: "skeleton",
css: PopsCSS.skeletonCSS,
},
{
name: "iframeCSS",
css: PopsCSS.iframeCSS,
},
]);
const maskExtraStyle =
config.animation != null && <string>config.animation != "" && config.animation ? "position:absolute;" : "";
// 先把z-index提取出来
const zIndex = PopsHandler.getTargerOrFunctionValue(config.zIndex);
const maskHTML = PopsElementHandler.createMask(guid, zIndex, maskExtraStyle);
const headerBtnHTML = PopsElementHandler.createHeader(popsType, config);
const iframeLoadingHTML = /*html*/ '<div class="pops-loading"></div>';
const titleText = config.title!.text!.trim() !== "" ? config.title.text : config.url;
const { headerStyle, headerPStyle } = PopsElementHandler.createHeaderStyle(popsType, config);
const animHTML = PopsElementHandler.createAnim(
guid,
popsType,
config,
/*html*/ `
<div class="pops-title pops-${popsType}-title" style="text-align: ${
config.title.position
};${headerStyle}">${
config.title.html
? titleText
: `<p pops class="pops-${popsType}-title-text" style="${headerPStyle}">${titleText}</p>`
}${headerBtnHTML}</div>
<div class="pops-content pops-${popsType}-content">
<div class="pops-${popsType}-content-global-loading"></div>
<iframe src="${config.url}" pops ${
config.sandbox ? "sandbox='allow-forms allow-same-origin allow-scripts'" : ""
}>
</iframe>
</div>${config.loading.enable ? iframeLoadingHTML : ""}`,
"",
zIndex
);
/**
* 弹窗的主元素,包括动画层
*/
const $anim = PopsElementHandler.parseElement<HTMLDivElement>(animHTML);
const {
$pops,
$headerBtnClose,
$headerControls,
$title,
$iframe,
$loading,
$contentLoading,
$headerBtnMin,
$headerBtnMax,
$headerBtnMise,
} = PopsHandler.handleQueryElement($anim, popsType);
let $iframeContainer = popsDOMUtils.selector<HTMLDivElement>(".pops-iframe-container");
if (!$iframeContainer) {
$iframeContainer = popsDOMUtils.createElement("div", {
className: "pops-iframe-container",
});
$iframeContainer.style.cssText =
"display: flex;position: fixed;bottom: 0px;flex-flow: wrap-reverse;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;";
popsDOMUtils.appendBody($iframeContainer);
}
/**
* 遮罩层元素
*/
let $mask: HTMLDivElement | undefined = void 0;
/**
* 已创建的元素列表
*/
const $elList: HTMLElement[] = [$anim];
if (config.mask.enable) {
const handleMask = PopsHandler.handleMask({
type: popsType,
guid: guid,
config: config,
animElement: $anim,
maskHTML: maskHTML,
});
$mask = handleMask.maskElement;
$elList.push($mask);
}
const evtConfig = PopsHandler.handleEventConfig(
config,
guid,
$shadowContainer,
$shadowRoot,
popsType,
$anim,
$pops,
emitter,
$mask
) as PopsIframeClickEventConfig<typeof emitter>;
// 赋值额外的$iframe参数
evtConfig.$iframe = $iframe;
const result = PopsHandler.handleResultConfig(evtConfig);
popsDOMUtils.on($anim, popsDOMUtils.getAnimationEndNameList(), function () {
// 动画加载完毕
$anim.style.width = "0%";
$anim.style.height = "0%";
});
popsDOMUtils.on($iframe, "load", () => {
// iframe加载中...
popsDOMUtils.remove($loading);
$contentLoading!.style.animation = "iframeLoadingChange_85 0.3s forwards";
popsDOMUtils.on($contentLoading, popsDOMUtils.getAnimationEndNameList(), () => {
// 动画加载完毕就移除
popsDOMUtils.remove($contentLoading);
});
if (config.title!.text!.trim() === "" && $iframe!.contentDocument) {
// 同域名下的才可以获取网页标题
$title!.querySelector<HTMLElement>("p")!.innerText = $iframe!.contentDocument.title;
}
config.loadEndCallBack(evtConfig);
});
// 创建到页面中
popsDOMUtils.append($shadowRoot, $elList);
emitter.emit("pops:before-append-to-page", $shadowRoot, $shadowContainer);
$iframeContainer.appendChild($shadowContainer);
if ($mask != null) {
$anim.after($mask);
}
// 拖拽
if (config.drag) {
PopsInstHandler.drag($pops!, {
dragElement: $title!,
limit: config.dragLimit,
extraDistance: config.dragExtraDistance,
moveCallBack: config.dragMoveCallBack,
endCallBack: config.dragEndCallBack,
});
}
const TYPE_MODULE = "type-module";
// 最小化按钮点击事件
let origin_left = "";
let origin_top = "";
let origin_is_max = false;
popsDOMUtils.on<PointerEvent | MouseEvent>(
$headerBtnMin,
"click",
(event) => {
event.preventDefault();
event.stopPropagation();
origin_left = $pops.style.left;
origin_top = $pops.style.top;
popsDOMUtils.addClassName(
$pops,
"pops-iframe-unset-top",
"pops-iframe-unset-left",
"pops-iframe-unset-transform"
);
$pops.style.transitionDuration = "";
$pops.setAttribute(TYPE_MODULE, "min");
$headerControls.setAttribute("type", "min");
// 隐藏放大图标
$headerBtnMax.style.setProperty("display", "none");
// 显示复位图标
$headerBtnMise.style.setProperty("display", "");
if (typeof config?.btn?.min?.callback === "function") {
config.btn.min.callback(evtConfig, event);
}
emitter.emit("pops:iframe-min", evtConfig, event);
},
{
capture: true,
}
);
// 最大化按钮点击事件
popsDOMUtils.on<MouseEvent | PointerEvent>(
$headerBtnMax,
"click",
(event) => {
event.preventDefault();
event.stopPropagation();
if ($pops.getAttribute(TYPE_MODULE) !== "min") {
origin_left = $pops.style.left;
origin_top = $pops.style.top;
}
origin_is_max = true;
$pops.style.transitionDuration = "";
$pops.style.transform = "";
$pops.removeAttribute(TYPE_MODULE);
popsDOMUtils.addClassName(
$pops,
"pops-iframe-unset-transition",
"pops-iframe-unset-left",
"pops-iframe-unset-top",
"pops-iframe-unset-transform"
);
popsDOMUtils.removeClassName($pops, "pops-iframe-unset-transition");
$pops.setAttribute(TYPE_MODULE, "max");
$headerControls.setAttribute("type", "max");
// 隐藏放大图标
$headerBtnMax.style.setProperty("display", "none");
// 显示复位图标
$headerBtnMise.style.setProperty("display", "");
if (typeof config?.btn?.max?.callback === "function") {
config.btn.max.callback(evtConfig, event);
}
emitter.emit("pops:iframe-max", evtConfig, event);
},
{
capture: true,
}
);
// 先隐藏窗口化按钮
$headerBtnMise?.style?.setProperty("display", "none");
// 复位按钮点击事件
popsDOMUtils.on<MouseEvent | PointerEvent>(
$headerBtnMise,
"click",
(event) => {
event.preventDefault();
event.stopPropagation();
if (origin_is_max && $pops.getAttribute(TYPE_MODULE) === "min") {
popsDOMUtils.addClassName(
$pops,
"pops-iframe-unset-transition",
"pops-iframe-unset-left",
"pops-iframe-unset-top",
"pops-iframe-unset-transform"
);
popsDOMUtils.removeClassName($pops, "pops-iframe-unset-transition");
$pops.setAttribute(TYPE_MODULE, "max");
$headerControls.setAttribute("type", "max");
} else {
origin_is_max = false;
$pops.style.left = origin_left;
$pops.style.top = origin_top;
$pops.style.transitionDuration = "";
$pops.style.transform = "";
$headerControls.removeAttribute("type");
$pops.removeAttribute(TYPE_MODULE);
popsDOMUtils.removeClassName(
$pops,
"pops-iframe-unset-top",
"pops-iframe-unset-left",
"pops-iframe-unset-transform"
);
// 显示放大图标
$headerBtnMax.style.setProperty("display", "");
// 隐藏复位图标
$headerBtnMise.style.setProperty("display", "none");
}
if (typeof config?.btn?.mise?.callback === "function") {
config.btn.mise.callback(evtConfig, event);
}
emitter.emit("pops:iframe-mise", evtConfig, event);
},
{
capture: true,
}
);
// 关闭按钮点击事件
popsDOMUtils.on<MouseEvent | PointerEvent>(
$headerBtnClose,
"click",
async (event) => {
event.preventDefault();
event.stopPropagation();
await PopsInstHandler.removeInstance([PopsInstData.iframe], guid, false);
if (typeof config?.btn?.close?.callback === "function") {
config.btn.close.callback(evtConfig, event);
}
},
{
capture: true,
}
);
PopsHandler.handlePush(popsType, {
guid: guid,
$anim: $anim,
$pops: $pops!,
$mask: $mask!,
$shadowContainer: $shadowContainer,
$shadowRoot: $shadowRoot,
config: config,
emitter,
});
return result;
},
};