UNPKG

@whitesev/pops

Version:

弹窗库

345 lines (320 loc) 10.8 kB
import { PopsCore } from "../../Core"; import { GlobalConfig } from "../../GlobalConfig"; import { PopsElementHandler } from "../../handler/PopsElementHandler"; import { PopsHandler } from "../../handler/PopsHandler"; import { pops } from "../../Pops"; import type { PopsEventDetails } from "../../types/event"; import { popsDOMUtils } from "../../utils/PopsDOMUtils"; import { PopsInstanceUtils } from "../../utils/PopsInstanceUtils"; import { popsUtils } from "../../utils/PopsUtils"; import { PopsIframeConfig } from "./config"; import type { PopsIframeDetails } from "./indexType"; export class PopsIframe { constructor(details: PopsIframeDetails) { const guid = popsUtils.getRandomGUID(); // 设置当前类型 const PopsType = "iframe"; let config = PopsIframeConfig(); config = popsUtils.assign(config, GlobalConfig.getGlobalConfig()); config = popsUtils.assign(config, details); if (config.url == null) { throw "config.url不能为空"; } config = PopsHandler.handleOnly(PopsType, config); const { $shadowContainer, $shadowRoot } = PopsHandler.handlerShadow(config); PopsHandler.handleInit($shadowRoot, [ pops.config.cssText.index, pops.config.cssText.ninePalaceGridPosition, pops.config.cssText.scrollbar, pops.config.cssText.anim, pops.config.cssText.common, pops.config.cssText.iframeCSS, ]); let maskExtraStyle = // @ts-ignore config.animation != null && config.animation != "" ? "position:absolute;" : ""; // 先把z-index提取出来 let zIndex = PopsHandler.handleZIndex(config.zIndex); let maskHTML = PopsElementHandler.getMaskHTML(guid, zIndex, maskExtraStyle); let headerBtnHTML = PopsElementHandler.getHeaderBtnHTML(PopsType, config); let iframeLoadingHTML = '<div class="pops-loading"></div>'; let titleText = config.title!.text!.trim() !== "" ? config.title.text : config.url; let { headerStyle, headerPStyle } = PopsElementHandler.getHeaderStyle( PopsType, config ); let animHTML = PopsElementHandler.getAnimHTML( guid, PopsType, config, /*html*/ ` <div class="pops-iframe-title" style="text-align: ${config.title.position};${headerStyle}" > ${ config.title.html ? titleText : `<p pops style="${headerPStyle}">${titleText}</p>` } ${headerBtnHTML} </div> <div class="pops-iframe-content"> <div class="pops-iframe-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 ); /** * 弹窗的主元素,包括动画层 */ let $anim = PopsElementHandler.parseElement<HTMLDivElement>(animHTML); let { popsElement: $pops, headerCloseBtnElement, headerControlsElement, titleElement: $title, iframeElement: $iframe, loadingElement, contentLoadingElement: $contentLoading, headerMinBtnElement, headerMaxBtnElement, headerMiseBtnElement, } = PopsHandler.handleQueryElement($anim, PopsType); let $iframeContainer = PopsCore.document.querySelector<HTMLDivElement>( ".pops-iframe-container" ); if (!$iframeContainer) { $iframeContainer = PopsCore.document.createElement("div"); $iframeContainer.className = "pops-iframe-container"; $iframeContainer.style.cssText = "display: flex;position: fixed;bottom: 0px;flex-flow: wrap-reverse;user-select: none;-webkit-user-select: none;-ms-user-select: none;-moz-user-select: none;"; popsDOMUtils.appendBody($iframeContainer); } /** * 遮罩层元素 */ let $mask: HTMLDivElement | null = null; /** * 已创建的元素列表 */ let elementList: HTMLElement[] = [$anim]; if (config.mask.enable) { let _handleMask_ = PopsHandler.handleMask({ type: PopsType, guid: guid, config: config, animElement: $anim, maskHTML: maskHTML, }); $mask = _handleMask_.maskElement; elementList.push($mask); } let eventDetails = PopsHandler.handleEventDetails( guid, $shadowContainer, $shadowRoot, PopsType, $anim, $pops!, $mask!, config ) as any as PopsEventDetails & { iframeElement: HTMLIFrameElement; }; eventDetails["iframeElement"] = $iframe!; popsDOMUtils.on($anim, popsDOMUtils.getAnimationEndNameList(), function () { /* 动画加载完毕 */ $anim.style.width = "0%"; $anim.style.height = "0%"; }); popsDOMUtils.on($iframe, "load", () => { /* iframe加载中... */ loadingElement?.remove(); $contentLoading!.style.animation = "iframeLoadingChange_85 0.3s forwards"; popsDOMUtils.on( $contentLoading, popsDOMUtils.getAnimationEndNameList(), () => { /* 动画加载完毕就移除 */ $contentLoading!.remove(); } ); if (config.title!.text!.trim() === "" && $iframe!.contentDocument) { /* 同域名下的才可以获取网页标题 */ $title!.querySelector<HTMLElement>("p")!.innerText = $iframe!.contentDocument.title; } config.loadEndCallBack(eventDetails); }); /* 创建到页面中 */ popsDOMUtils.append($shadowRoot, elementList); if (typeof config.beforeAppendToPageCallBack === "function") { config.beforeAppendToPageCallBack($shadowRoot, $shadowContainer); } $iframeContainer.appendChild($shadowContainer); if ($mask != null) { $anim.after($mask); } /* 拖拽 */ if (config.drag) { PopsInstanceUtils.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>( headerMinBtnElement, "click", (event) => { event.preventDefault(); event.stopPropagation(); origin_left = $pops.style.left; origin_top = $pops.style.top; $pops.classList.add("pops-iframe-unset-top"); $pops.classList.add("pops-iframe-unset-left"); $pops.classList.add("pops-iframe-unset-transform"); $pops.style.transitionDuration = ""; $pops.setAttribute(TYPE_MODULE, "min"); headerControlsElement.setAttribute("type", "min"); // 隐藏放大图标 headerMaxBtnElement.style.setProperty("display", "none"); // 显示复位图标 headerMiseBtnElement.style.setProperty("display", ""); if (typeof config?.btn?.min?.callback === "function") { config.btn.min.callback(eventDetails, event); } }, { capture: true, } ); /* 最大化按钮点击事件 */ popsDOMUtils.on<MouseEvent | PointerEvent>( headerMaxBtnElement, "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); $pops.classList.add("pops-iframe-unset-transition"); $pops.classList.add("pops-iframe-unset-left"); $pops.classList.add("pops-iframe-unset-top"); $pops.classList.add("pops-iframe-unset-transform"); $pops.classList.remove("pops-iframe-unset-transition"); $pops.setAttribute(TYPE_MODULE, "max"); headerControlsElement.setAttribute("type", "max"); // 隐藏放大图标 headerMaxBtnElement.style.setProperty("display", "none"); // 显示复位图标 headerMiseBtnElement.style.setProperty("display", ""); if (typeof config?.btn?.max?.callback === "function") { config.btn.max.callback(eventDetails, event); } }, { capture: true, } ); /* 先隐藏窗口化按钮 */ headerMiseBtnElement?.style?.setProperty("display", "none"); /* 复位按钮点击事件 */ popsDOMUtils.on<MouseEvent | PointerEvent>( headerMiseBtnElement, "click", (event) => { event.preventDefault(); event.stopPropagation(); if (origin_is_max && $pops.getAttribute(TYPE_MODULE) === "min") { $pops.classList.add("pops-iframe-unset-transition"); $pops.classList.add("pops-iframe-unset-left"); $pops.classList.add("pops-iframe-unset-top"); $pops.classList.add("pops-iframe-unset-transform"); $pops.classList.remove("pops-iframe-unset-transition"); $pops.setAttribute(TYPE_MODULE, "max"); headerControlsElement.setAttribute("type", "max"); } else { origin_is_max = false; $pops.style.left = origin_left; $pops.style.top = origin_top; $pops.style.transitionDuration = ""; $pops.style.transform = ""; headerControlsElement.removeAttribute("type"); $pops.removeAttribute(TYPE_MODULE); $pops.classList.remove("pops-iframe-unset-top"); $pops.classList.remove("pops-iframe-unset-left"); $pops.classList.remove("pops-iframe-unset-transform"); // 显示放大图标 headerMaxBtnElement.style.setProperty("display", ""); // 隐藏复位图标 headerMiseBtnElement.style.setProperty("display", "none"); } if (typeof config?.btn?.mise?.callback === "function") { config.btn.mise.callback(eventDetails, event); } }, { capture: true, } ); /* 关闭按钮点击事件 */ popsDOMUtils.on<MouseEvent | PointerEvent>( headerCloseBtnElement, "click", (event) => { event.preventDefault(); event.stopPropagation(); PopsInstanceUtils.removeInstance( [pops.config.layer.iframe], guid, false ); if (typeof config?.btn?.close?.callback === "function") { config.btn.close.callback(eventDetails, event); } }, { capture: true, } ); PopsHandler.handlePush(PopsType, { guid: guid, animElement: $anim, popsElement: $pops!, maskElement: $mask!, $shadowContainer: $shadowContainer, $shadowRoot: $shadowRoot, }); let result = PopsHandler.handleResultDetails(eventDetails); return result; } }