找回密码
 立即注册
首页 业界区 业界 改造jsp项目的alert框和confirm框

改造jsp项目的alert框和confirm框

坟菊 3 天前
背景

之前项目的模态框改造完成,业务也想把页面中的提示框和确认框也改造一下;这里记录一下改造中的细节。
之前项目中的提示框和确认框用的是浏览器自带的 alert 和 confirm。改造之前无法支持业务一些复杂一点的需求,遂将之改造;
实现

弹框层级设计参考了 element 和 antd,默认样式也是复用了他们的样式。层级从父到子如下所示
1.png

messageBoxWrap 是弹出框包裹层和遮罩层。messageBox 是弹出框本身,里面包含了标题,内容,按钮。
而且因为默认 confirm 框会有返回值,所以这里改造后的也就返回了一个 Promise,并且只会 resolve(true) 或者 resolve(false)。
  1. // type 区分是 alert 还是 confirm
  2. // paramSting 表示提示框的内容,项目中没有自定义标题的需求,所以这里提示框都用统一的标题
  3. function showMessagebox(type, paramString) {
  4.   //获取项目顶层的document,弹框显示需要覆盖顶层页面
  5.   var topDoc = window.top.document;
  6.   var mainFrameSet = topDoc.querySelector("#setMain");
  7.   var mainFrameSetParent = mainFrameSet.parentNode;
  8.   var topDocBody = window.top.document.body;
  9.   //创建弹框盒子,添加遮罩层
  10.   return new Promise((resolve, reject) => {
  11.       // 具体实现
  12.   });
  13. }
复制代码
注意事项

有几个注意的点是

  • 创建弹框时需要禁用键盘事件,弹框消失后启用键盘事件,防止弹框还未消失,使用 tab+enter去了其他页面的情况
  • 需要避免有一个弹框存在的情况下,重复点击创建弹框
然后是具体实现。
添加默认样式
  1. /*弹框的默认样式;*/
  2. var messageBoxWrap_class = "modernMessagebox";
  3. var messageBoxWrap_style =
  4.   "width:100%;height:100%;position:fixed;top:0;left:0;text-align:center;";
  5. var messageBox_style =
  6.   "user-select:none;display: inline-block;width: 420px;padding: 10px 0px 20px;vertical-align: middle;background-color: #fff;border-radius: 4px;border: 1px solid #ebeef5;font-size:18px;box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);text-align: left;";
  7. var header_style =
  8.   "padding: 10px 16px 10px;font-size:14px;display:flex;justify-content: space-between;";
  9. var content_style = "padding: 10px 15px;color: #606266;font-size: 14px;";
  10. var footer_style = "padding: 5px 15px 0;text-align: right;";
  11. var button_style =
  12.   "display: inline-block;line-height: 1;wite-space: nowrap;cursor: pointer;background: #fff;border: 1px solid #dcdfe6;color: #606266;-webkit-appearance: none;text-align:center;box-sizing:border-box;outline:0;margin:0;transition:.1s;font-weight:500;padding:10px 16px;font-size:12px;border-radius:3px;";
  13. var button_primary =
  14.   "color: #fff;background: rgb(11, 87, 208);border: 1px solid rgb(11, 87, 208);border-radius: 20px 20px;";
复制代码
创建 messageBoxWrap,添加遮罩层
  1. var messageBoxWrap = document.createElement("div");
  2. messageBoxWrap.setAttribute("tabindex", "-1"); // 设置使其不能通过tab键聚焦
  3. messageBoxWrap.className = messageBoxWrap_class + Date.now(); // 每次弹框的类名都是唯一的
  4. // 使 messageBoxWrap 覆盖在顶层 window 上
  5. messageBoxWrap.style = messageBoxWrap_style + ";width:" + topDocBody.clientWidth + "px;";
复制代码
创建 messageBox,添加 header,content,footer

1、创建messageBox
  1. var messageBox = document.createElement("div");
  2. messageBox.className = "messageBox";
  3. messageBox.style = messageBox_style;
复制代码
2、创建 header
  1. //创建 header
  2. var header = document.createElement("div");
  3. header.className = "messageBox_header";
  4. header.style = header_style;
  5. var headerText = document.createElement("div");
  6. headerText.textContent = "提示";
  7. var headerBtn = document.createElement("div");
  8. headerBtn.style = "cursor:pointer;text-align:right;";
  9. headerBtn.textContent = "x";
  10. headerBtn.onclick = function () {
  11.   mainFrameSetParent.removeChild(messageBoxWrap);
  12.   enableKeyboard();
  13. };
复制代码
当点击头部的关闭按钮时,在顶层文档对象(mainFrameSetParent)中移除弹框。这里 enableKeyboard
表示移除弹框后恢复键盘事件。因为有时候业务操作飞快,有时候因为电脑卡,弹框还没完全关闭,使用键盘操作去到了其他页面,导致弹框显示在了其他页面。
3、创建 content 包裹层
  1. //创建 content 包裹层
  2. var contentBox = document.createElement("div");
  3. contentBox.className = "messageBox_content";
  4. contentBox.style = content_style;
  5. contentBox.textContent = paramString;
复制代码
4、创建 footer
这里如果使 confirm 框,则多一个取消按钮
  1. //创建 footer
  2. var footer = document.createElement("div");
  3. footer.className = "messageBox_footer";
  4. footer.style = footer_style;
  5. var yesBtn = document.createElement("button");
  6. yesBtn.style = button_style + button_primary;
  7. yesBtn.textContent = type === "confirm" ? "确认" : "确定";
  8. yesBtn.onclick = function () {
  9.   if (type === "alert") {
  10.     if (currentAlertBoxCount > 0) {
  11.       currentAlertBoxCount--;
  12.     }
  13.   }
  14.   resolve(true);
  15.   mainFrameSetParent.removeChild(messageBoxWrap);
  16.   enableKeyboard(); // 关闭弹框后恢复键盘事件
  17. };
  18. if (type === "confirm") {
  19.   var noBtn = document.createElement("button");
  20.   noBtn.style =
  21.     button_style + "margin-left: 10px;border-radius: 20px 20px;";
  22.   noBtn.textContent = "取消";
  23.   noBtn.onclick = function () {
  24.     resolve(false);
  25.     mainFrameSetParent.removeChild(messageBoxWrap);
  26.     enableKeyboard(); // 关闭弹框后恢复键盘事件
  27.   };
  28. }
  29. footer.appendChild(yesBtn);
  30. if (type === "confirm") {
  31.   footer.appendChild(noBtn);
  32. }
复制代码
5、将创建的弹框插入顶层文档
创建弹框时,使焦点聚焦到弹框,并且禁用键盘事件。
  1. messageBox.appendChild(header);
  2. messageBox.appendChild(contentBox);
  3. messageBox.appendChild(footer);
  4. messageBoxWrap.appendChild(messageBox);
  5. //将创建好的弹框插入顶层 document
  6. mainFrameSetParent.appendChild(messageBoxWrap);
  7. messageBoxWrap.focus();
  8. disableKeyboard();
复制代码
6、页面调用弹出框
设置 currentAlertBoxCount 代表 alert 框的数量,避免同时出现多个弹框
  1. var currentAlertBoxCount = 0;
  2. async function modernConfirm(str) {
  3.   return await showMessagebox("confirm", str);
  4. }
  5. async function modernAlert(str) {
  6.   if(currentAlertBoxCount>0){
  7.     return
  8.   }
  9.   currentAlertBoxCount++;
  10.   return await showMessagebox("alert", str);
  11. }
复制代码
完整代码
  1. /*弹框的默认样式;*/
  2. var messageBoxWrap_class = "modernMessagebox";
  3. var messageBoxWrap_style =
  4.   "width:100%;height:100%;position:fixed;top:0;left:0;text-align:center;";
  5. var messageBox_style =
  6.   "user-select:none;display: inline-block;width: 420px;padding: 10px 0px 20px;vertical-align: middle;background-color: #fff;border-radius: 4px;border: 1px solid #ebeef5;font-size:18px;box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);text-align: left;";
  7. var header_style =
  8.   "padding: 10px 16px 10px;font-size:14px;display:flex;justify-content: space-between;";
  9. var content_style = "padding: 10px 15px;color: #606266;font-size: 14px;";
  10. var footer_style = "padding: 5px 15px 0;text-align: right;";
  11. var button_style =
  12.   "display: inline-block;line-height: 1;wite-space: nowrap;cursor: pointer;background: #fff;border: 1px solid #dcdfe6;color: #606266;-webkit-appearance: none;text-align:center;box-sizing:border-box;outline:0;margin:0;transition:.1s;font-weight:500;padding:10px 16px;font-size:12px;border-radius:3px;";
  13. var button_primary =
  14.   "color: #fff;background: rgb(11, 87, 208);border: 1px solid rgb(11, 87, 208);border-radius: 20px 20px;";var currentAlertBoxCount = 0;//弹框时禁用键盘事件,弹框消失后启用键盘事件,防止弹框还未消失,使用 tab+enter去了其他页面的情况let keyboardDisabled = false;function disableKeyboard() {  keyboardDisabled = true;  document.addEventListener("keydown", handleKeyDown);}function enableKeyboard() {  keyboardDisabled = false;  document.removeEventListener("keydown", handleKeyDown);}function handleKeyDown(event) {  if (keyboardDisabled) {    event.preventDefau1t();  }}// type 区分是 alert 还是 confirm// paramSting 表示提示框的内容,项目中没有自定义标题的需求,所以这里提示框都用统一的标题function showMessagebox(type, paramString) {  //获取项目顶层的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 messageBoxWrap = document.createElement("div");    messageBoxWrap.setAttribute("tabindex", "-1");    messageBoxWrap.className = messageBoxWrap_class + Date.now();    messageBoxWrap.style = messageBoxWrap_style + ";width:" + topDocBody.clientWidth + "px;";    var messageBox = document.createElement("div");    messageBox.className = "messageBox";    messageBox.style = messageBox_style;    //创建 header    var header = document.createElement("div");    header.className = "messageBox_header";    header.style = header_style;    var headerText = document.createElement("div");    headerText.textContent = "提示";    var headerBtn = document.createElement("div");    headerBtn.style = "cursor:pointer;text-align:right;";    headerBtn.textContent = "x";    headerBtn.onclick = function () {      mainFrameSetParent.removeChild(messageBoxWrap);      enableKeyboard();    };    header.appendChild(headerText);    header.appendChild(headerBtn);    //创建 content 包裹层    var contentBox = document.createElement("div");    contentBox.className = "messageBox_content";    contentBox.style = content_style;    contentBox.textContent = paramString;    //创建 footer    var footer = document.createElement("div");    footer.className = "messageBox_footer";    footer.style = footer_style;    var yesBtn = document.createElement("button");    yesBtn.style = button_style + button_primary;    yesBtn.textContent = type === "confirm" ? "确认" : "确定";    yesBtn.onclick = function () {      if (type === "alert") {        if (currentAlertBoxCount > 0) {          currentAlertBoxCount--;        }      }      resolve(true);      mainFrameSetParent.removeChild(messageBoxWrap);      enableKeyboard();    };    if (type === "confirm") {      var noBtn = document.createElement("button");      noBtn.style =        button_style + "margin-left: 10px;border-radius: 20px 20px;";      noBtn.textContent = "取消";      noBtn.onclick = function () {        resolve(false);        mainFrameSetParent.removeChild(messageBoxWrap);        enableKeyboard();      };    }    footer.appendChild(yesBtn);    if (type === "confirm") {      footer.appendChild(noBtn);    }    messageBox.appendChild(header);    messageBox.appendChild(contentBox);    messageBox.appendChild(footer);    messageBoxWrap.appendChild(messageBox);    //将创建好的弹框插入顶层 document    mainFrameSetParent.appendChild(messageBoxWrap);    messageBoxWrap.focus();    disableKeyboard();  });}async function modernConfirm(str) {  return await showMessagebox("confirm", str);}async function modernAlert(str) {  if(currentAlertBoxCount>0){    return  }  currentAlertBoxCount++;  return await showMessagebox("alert", str);}
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册