背景
之前有个项目是 jsp 的,之前都是在 IE 浏览器上运行,现在要将这个项目做兼容性改造(信创),需要兼容谷歌。所以需要将项目中的公共弹框给改掉,而项目中模态框基本上都是用的 showModalDialog。
介绍 showModalDialog
showModalDialog 是微软在早期版本的(IE)中引入的一个方法,用于创建模态对话框。不过在现代浏览器中已经不再支持这个方法了。
用法(参考MDN):- returnVal = window.showModalDialog(uri[, arguments][, options]);
复制代码
- returnVal 模态框的返回值。
- uri 要在模态对话框中打开的页面 URI。
- arguments 可选变量。可以通过该参数将需要的值传入对话框。
- options 可选字符串参数。用于设置对话框打开的样式,使用一个或多个逗号分隔。
缺点:
- 现代浏览器不支持
- 模态框没有遮罩层,无法做到处理完模态框再处理父级页面
重写
步骤
- 使用 iframe 代替模态框中的内容包裹层(传递给模态框的uri是后台一个接口,接口返回一个jsp页面,模态框展示的就是这个页面,而 iframe 可以用来嵌入内容)
- 仍然支持 showModalDialog 的三个参数以及返回值给父页面
- 添加遮罩层,关闭模态框之前不能点击并处理父级页面
- 重写关闭模态框的方法(之前模态框关闭方法是 window.close)
编写函数
1、定义默认样式- //定义默认样式
- var DIALOG_CLASS = "modernShowDialog"; //弹框类名
- var SUB_STYLE =
- "position:absolute;top:50%;left:50%;margin-1eft:-50%;margin-top:150px;background:#fff;border-radius: 4px;";
- var IFAME_STYLE = "width:100%;border: none;height: 70%;";
- var dialog_header_style =
- "width:100%;height:32px;font-size:14px;line-height:34px;";
复制代码 2、获取项目顶层的 document,弹框要覆盖所有页面,必须添加到顶层 window 中- function showModalDialog(pageUrl, comeInParams, iframeStyle) {
- //获取传进来的宽高
- iframeStyle = iframeStyle.replace(/dialogwidth/g, "width");
- iframeStyle = iframeStyle.replace(/dialogHeight/g, "height");
- //获取项目顶层的 document
- var topDoc = window.top.document;
- var topDocBody = window.top.document.body;
- var mainFrameSet = topDoc.querySelector("#setMain");
-
- // 最终生成的模态框会插入到 mainFrameSetParent 中
- var mainFrameSetParent = mainFrameSet.parentNode;
-
- return new Promise((resolve, reject) => {
- //···
- })
- }
复制代码 这里返回一个 promise ,返回值也会通过 resolve 返回给父级页面,父页面通过 .then 或者 await 接收。
3、创建弹框盒子,弹框header,iframe区域,footer,添加遮罩层- return new Promise((resolve, reject) => {
- //创建弹框盒子,添加遮罩层
- var dialog = document.createElement("div");
- dialog.className = DIALOG_CLASS + Date.now();
- dialog.style = DIALOG_STYLE + ";width:" + topDocBody.clientwidth + "px;";
- //创建弹框里面用来包裹iframe的 div
- var dialogBody = document.createElement("div");
- dialogBody.className = "dialogBody";
- var marginLeft = parseFloat(
- iframeStyle.match(/width\:(\d)+px;/g)[0].replace("width:", "")
- );
- var marginTop = parseFloat(
- iframeStyle.match(/height\:(\d)+px;/g)[0].replace("height:", "")
- );
- dialogBody.style =
- SUB_STYLE +
- ";margin-left:-" +
- marginLeft / 2 +
- "px;margin-top:-" +
- marginTop / 2 +
- "px;";
- //创建 header
- var header = document.createElement("div");
- header.className = "dialog_header";
- header.style = dialog_header_style;
- var headerBtn = document.createElement("div");
- headerBtn.style =
- "cursor:pointer;text-align:right;padding-right:10px;font-size: 20px;user-select: none;";
- headerBtn.textContent = "x";
- headerBtn.onclick = function () {
- mainFrameSetParent.removeChild(dialog);
- };
- header.appendChild(headerBtn);
- //创建 iframe 包裹层
- var iframe = document.createElement("iframe");
- iframe.src = pageUrl;
- iframe.className = "modernDialogIframe";
- iframe.style = IFAME_STYLE + iframeStyle;
- iframe.destroy = function (returnValue) {
- resolve(returnValue);
- mainFrameSetParent.removeChild(dialog);
- removeStorageClass();
- };
- dialogBody.appendChild(header);
- dialogBody.appendChild(iframe);
- dialog.appendChild(dialogBody);
-
- var removeStorageClass = function () {
- var existClass = sessionStorage.getItem("dialogClass");
- if (existClass) {
- sessionStorage.setItem(
- "dialogClass",
- existClass.split(",").pop().join(",")
- );
- }
- };
-
- //将创建好的弹框插入顶层 document
- mainFrameSetParent.appendChild(dialog);
-
- // 通过sessionStorage 存储当前显示的弹框的类名,
- //给某些特定页面(通过windbw.close 关闭不了的页面,因为里面的window可能表单操作刷新了window)使用
- var session = sessionStorage.getItem('dialogClass')
- sessionStorage.setItem('dialogClass',session ? (session + ',' + dialog.className) : dialog.className)
复制代码 需要注意的是,上面定义了 iframe.destroy 和 removeStorageClass 方法用来给某些特殊页面用的,那些特殊页面因为表单操作刷新了当前 window,导致调用不到了我们的重写的 close 方法。所以只能那些页面中处理完业务后手动调用 destroy 方法关闭模态框。
4、iframe加载完毕后,重写模态框的关闭方法- var modernDialogIframe = topDoc.querySelector(
- "." + dialog.className + " .modernDialogIframe"
- );
- var tempValue = null;
- //监听 iframe 包裹的目标页面的加载情况
- modernDialogIframe.contentwindow.addEventListener("load", function () {
- this.dialogArguments = comeInParams;
- this.oldClose = this.close;
- //重写当前页面的 window.close
- this.close = function () {
- // returnValue 是业务页面中定义的全局变量
- tempValue = this.returnValue;
- setTimeout(function () {
- resolve(tempValue);
- }, 10);
- mainFrameSetParent.removeChild(dialog);
- removeStorageClass();
- this.oldClose();
- };
- });
复制代码 完整代码
- //定义默认样式
- var DIALOG_CLASS = "modernShowDialog";
- var SUB_STYLE =
- "position:absolute;top:50%;left:50%;margin-1eft:-50%;margin-top:150px;background:#fff;border-radius: 4px;";
- var IFAME_STYLE = "width:100%;border: none;height: 70%;";
- var dialog_header_style =
- "width:100%;height:32px;font-size:14px;line-height:34px;";
- /**
- * 模拟 IE 的 showModalDialog 方法,同样接收三个参数;
- * pageUrl 表示要显示的页面地址
- * comeInParams 表示传进目标页面的参数
- * iframeStyle 表示自定义页面样式,比如宽高
- **/
- function showModalDialog(pageUrl, comeInParams, iframeStyle) {
- iframeStyle = iframeStyle.replace(/dialogwidth/g, "width");
- iframeStyle = iframeStyle.replace(/dialogHeight/g, "height");
- //获取项目顶层的 document,弹框显示需要覆盖顶层页面
- var topDoc = window.top.document;
- var mainFrameSet = topDoc.querySelector("#setMain");
- var mainFrameSetParent = mainFrameSet.parentNode;
- var topDocBody = window.top.document.body;
- return new Promise((resolve, reject) => {
- //创建弹框盒子,添加遮罩层
- var dialog = document.createElement("div");
- dialog.className = DIALOG_CLASS + Date.now();
- dialog.style = DIALOG_STYLE + ";width:" + topDocBody.clientwidth + "px;";
- //创建弹框里面用来包裹iframe的 div
- var dialogBody = document.createElement("div");
- dialogBody.className = "dialogBody";
- var marginLeft = parseFloat(
- iframeStyle.match(/width\:(\d)+px;/g)[0].replace("width:", "")
- );
- var marginTop = parseFloat(
- iframeStyle.match(/height\:(\d)+px;/g)[0].replace("height:", "")
- );
- dialogBody.style =
- SUB_STYLE +
- ";margin-left:-" +
- marginLeft / 2 +
- "px;margin-top:-" +
- marginTop / 2 +
- "px;";
- //创建 header
- var header = document.createElement("div");
- header.className = "dialog_header";
- header.style = dialog_header_style;
- var headerBtn = document.createElement("div");
- headerBtn.style =
- "cursor:pointer;text-align:right;padding-right:10px;font-size: 20px;user-select: none;";
- headerBtn.textContent = "x";
- headerBtn.onclick = function () {
- mainFrameSetParent.removeChild(dialog);
- };
- header.appendChild(headerBtn);
- //创建 iframe 包裹层
- var iframe = document.createElement("iframe");
- iframe.src = pageUrl;
- iframe.className = "modernDialogIframe";
- iframe.style = IFAME_STYLE + iframeStyle;
- iframe.destroy = function (returnValue) {
- resolve(returnValue);
- mainFrameSetParent.removeChild(dialog);
- removeStorageClass();
- };
- dialogBody.appendChild(header);
- dialogBody.appendChild(iframe);
- dialog.appendChild(dialogBody);
- var removeStorageClass = function () {
- var existClass = sessionStorage.getItem("dialogClass");
- if (existClass) {
- sessionStorage.setItem(
- "dialogClass",
- existClass.split(",").pop().join(",")
- );
- }
- };
- //将创建好的弹框插入顶层 document
- mainFrameSetParent.appendChild(dialog);
- // 通过sessionStorage 存储当前显示的弹框的类名,给某些特定页面(通过windbw.close 关闭不了的页面,因为里面的window可能表单操作刷新了window)使用
- var session = sessionStorage.getItem('dialogClass')
- sessionStorage.setItem('dialogClass',session ? (session + ',' + dialog.className) : dialog.className)
-
- var modernDialogIframe = topDoc.querySelector(
- "." + dialog.className + " .modernDialogIframe"
- );
- var tempValue = null;
- //监听 iframe 包裹的目标页面的加载情况
- modernDialogIframe.contentwindow.addEventListener("load", function () {
- this.dialogArguments = comeInParams;
- this.oldClose = this.close;
- //重写当前页面的 window.close
- this.close = function () {
- tempValue = this.returnValue;
- setTimeout(function () {
- resolve(tempValue);
- }, 10);
- mainFrameSetParent.removeChild(dialog);
- removeStorageClass();
- this.oldClose();
- };
- });
- });
- }
复制代码 来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |