javascript - 调用函数在上次调用中销毁回调

标签 javascript

我有功能,可以创建类似于警报、确认或提示的弹出窗口。调用新弹出窗口(任何类型)时出现问题,然后在第一次调用(提示值)时销毁回调

PoppyPopup.prompt('Type your name', 'User control', {}, function(value) {
    PoppyPopup.alert('Welcome ' + value); //<-- value is id of second popup
});

PoppyPopup.alert('Hi, this is a PopUp!', 'With title!');

演示:https://jsfiddle.net/yojz8sb3/

编辑:什么时候调用一次就OK了,真不知道哪里出了问题。

最佳答案

嗯,简短的回答是因为 PoppyPopup 的设计不是为了处理同时打开多个弹出窗口。

popupType 在所有弹出窗口之间共享,因此当您打开 alert 弹出窗口时,它会将 popupType 设置为 ALERT 并且因此,当提示弹出窗口的 accept 回调被调用时,它的处理就好像它是一个 ALERT 类型的弹出窗口一样。


一个(相当老套的)解决方案是删除 var popupType = null; 并将 popupType 作为第四个参数传递给 Popup 构造函数.然后你可以改变

PoppyPopup.accept(basePopup.id, options);

PoppyPopup.accept(basePopup.id, options, popupType);

Popup 函数中。

并改变

accept: function(popupId, options) {

accept: function(popupId, options, popupType) {

这样弹出窗口类型与弹出窗口实例相关联,而不是在所有弹出窗口之间共享。

这是一个工作示例:https://jsfiddle.net/0xpz7f9L/


但是我上面的回答并没有解决点击接受按钮似乎关闭随机弹出窗口的问题(显然不理想)。我建议重写整个内容以简化它并使其更易于阅读/理解。同样,这种事情传统上使用 promise 而不是回调。

下面是我将如何重写它:

const PoppyPopup = (function() {
  let nextPopupId = 0;

  return {
    alert: function(message, title, options) {
      const realOptions = buildOptionsFrom(options);
      const popupElem = buildPopupElem(title, message, realOptions, false, false);

      const promise = new Promise(resolve => {
        popupElem.querySelector('.accept').onclick = resolve;
      });
      promise.finally(() => close(popupElem, realOptions.removeWhenClosed));
      document.querySelector('body').appendChild(popupElem);

      return promise;
    },

    confirm: function(message, title, options) {
      const realOptions = buildOptionsFrom(options);
      const popupElem = buildPopupElem(title, message, realOptions, false, true);

      const promise = new Promise((resolve, reject) => {
        popupElem.querySelector('.accept').onclick = resolve;
        popupElem.querySelector('.cancel').onclick = reject;
      });
      promise.finally(() => close(popupElem, realOptions.removeWhenClosed));
      document.querySelector('body').appendChild(popupElem);

      return promise;
    },

    prompt: function(message, title, options) {
      const realOptions = buildOptionsFrom(options);
      const popupElem = buildPopupElem(title, message, realOptions, true, true);

      const promise = new Promise((resolve, reject) => {
        popupElem.querySelector('.accept').onclick = () => resolve(popupElem.querySelector('input').value);
        popupElem.querySelector('.cancel').onclick = reject;
      });
      promise.finally(() => close(popupElem, realOptions.removeWhenClosed));
      document.querySelector('body').appendChild(popupElem);

      return promise;
    }
  };
  
  function close(popupElem, removeWhenClosed) {
    popupElem.classList.remove('show');

    popupElem.addEventListener('transitionend', function(e) {
      if (e.propertyName === 'opacity' && removeWhenClosed) {
        popupElem.parentNode.removeChild(popupElem);
      }
    });
  }
  
  function buildOptionsFrom(options) {
    return Object.assign({
      showBackground: true,
      removeWhenClosed: true,
      width: '400px'
    }, options || {});
  }

  function buildPopupElem(title, message, options, provideInput, provideCancel) {
    const basePopupDiv = document.createElement("DIV");
    basePopupDiv.className = "poppy-popup show";
    basePopupDiv.id = nextPopupId++;
    
    if (options.showBackground) { 
      const backgroundDiv = document.createElement("DIV");
      backgroundDiv.className = "poppy-popup-background";
      basePopupDiv.appendChild(backgroundDiv);
    }
    
    const containerDiv = document.createElement("DIV");
    containerDiv.className = "poppy-popup-container";
    containerDiv.style.width = options.width;
    containerDiv.style.height = options.height;
    
    if (title) {
      const headerTitleDiv = document.createElement("DIV");
      headerTitleDiv.className = "poppy-popup-title-text";
      headerTitleDiv.innerHTML = title;
    
      const headerDiv = document.createElement("DIV");
      headerDiv.className = "poppy-popup-header";
      headerDiv.appendChild(headerTitleDiv);

      containerDiv.appendChild(headerDiv);
    }
    
    const contentDiv = document.createElement("DIV");
    contentDiv.className = "poppy-popup-content";
    contentDiv.innerHTML = message;
    
    if (provideInput) {
      const input = document.createElement("INPUT");
      input.type = "text";
      contentDiv.appendChild(input);
    }
    
    const acceptLink = document.createElement("A");
    acceptLink.className = 'accept';
    acceptLink.href = "#";
    acceptLink.innerHTML = "<i class='material-icons'>done</i> OK";
    
    const acceptSpan = document.createElement("SPAN");
    acceptSpan.className = "poppy-popup-accept";
    acceptSpan.appendChild(acceptLink);
    
    const buttonsDiv = document.createElement("DIV");
    buttonsDiv.className = "poppy-popup-buttons";
    buttonsDiv.appendChild(acceptSpan);
    
    if (provideCancel) {
      const cancelLink = document.createElement("A");
      cancelLink.className = "cancel";
      cancelLink.href = "#";
      cancelLink.innerHTML = "<i class='material-icons'>close</i> Cancel";
    
      const cancelSpan = document.createElement("SPAN");
      cancelSpan.className = "poppy-popup-cancel";
      cancelSpan.appendChild(cancelLink);
      
      buttonsDiv.appendChild(cancelSpan);
    }
    
    containerDiv.appendChild(contentDiv);
    containerDiv.appendChild(buttonsDiv);

    basePopupDiv.appendChild(containerDiv);

    return basePopupDiv;
  } //end of buildPopupElem()
})();

PoppyPopup.prompt('Type your name', 'User control').then(value => {
  PoppyPopup.alert('Welcome ' + value).then(() => {
    PoppyPopup.confirm('And just for completeness, confirm?')
      .then(() => alert('accepted'), () => alert('rejected'));
  });
});

PoppyPopup.alert('Hi, this is a PopUp!', 'With title!');
*, *:before, *:after {
  box-sizing: border-box; }

html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  font-family: 'Roboto', sans-serif;
  font-size: 16px;
  background-color: #eeeeee; }

.poppy-popup {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1000;
  width: 100vw;
  height: 100vh;
  display: -ms-flexbox;
  display: flex;
  -ms-flex-pack: center;
      justify-content: center;
  -ms-flex-align: center;
      align-items: center;
  font-size: 16px;
  opacity: 0;
  transition: opacity .3s; }
  .poppy-popup.show {
    opacity: 1; }
  .poppy-popup > .poppy-popup-background {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 1010;
    background-color: rgba(0, 0, 0, 0.5);
    width: 100%;
    height: 100%; }
  .poppy-popup > .poppy-popup-container {
    max-width: 90%;
    max-height: 90%;
    width: 100%;
    position: relative;
    z-index: 1020;
    border-radius: 3px;
    box-shadow: 0 0 10px 1px rgba(0, 0, 0, 0.3); }
    .poppy-popup > .poppy-popup-container > .poppy-popup-header {
      background-color: #FFFFFF;
      color: #222222;
      height: 50px;
      width: 100%;
      position: relative;
      border-top-left-radius: 3px;
      border-top-right-radius: 3px; }
      .poppy-popup > .poppy-popup-container > .poppy-popup-header > .poppy-popup-title-text {
        width: 100%;
        max-height: 50px;
        font-size: 1.5em;
        text-align: center;
        line-height: 50px;
        text-overflow: ellipsis;
        font-weight: bold;
        overflow: hidden;
        white-space: nowrap; }
    .poppy-popup > .poppy-popup-container > .poppy-popup-content {
      background-color: #FFFFFF;
      width: 100%;
      padding: 10px 20px;
      border-left: 1px solid #DDDDDD;
      border-right: 1px solid #DDDDDD;
      overflow: auto; }
      .poppy-popup > .poppy-popup-container > .poppy-popup-content > input[type="text"] {
        background-color: transparent;
        border-width: 0;
        border-bottom: 2px solid #CCCCCC;
        outline: none;
        font-size: 1.3em;
        width: 100%;
        margin-top: 20px;
        padding: 5px;
        box-shadow: none;
        transition: border-bottom .2s; }
        .poppy-popup > .poppy-popup-container > .poppy-popup-content > input[type="text"]:focus {
          border-bottom: 2px solid #2088AD; }
    .poppy-popup > .poppy-popup-container > .poppy-popup-buttons {
      width: 100%;
      height: 50px;
      padding: 0 10px;
      background-color: #FFFFFF;
      border-bottom-left-radius: 3px;
      border-bottom-right-radius: 3px;
      overflow: hidden; }
      .poppy-popup > .poppy-popup-container > .poppy-popup-buttons > .poppy-popup-accept, .poppy-popup > .poppy-popup-container > .poppy-popup-buttons > .poppy-popup-cancel {
        width: 120px;
        display: block;
        float: right;
        color: #2088AD; }
        .poppy-popup > .poppy-popup-container > .poppy-popup-buttons > .poppy-popup-accept > a, .poppy-popup > .poppy-popup-container > .poppy-popup-buttons > .poppy-popup-cancel > a {
          display: block;
          color: inherit;
          text-decoration: none;
          text-align: center;
          padding: 10px 0;
          border-radius: 3px;
          transition: background-color .2s, box-shadow .1s; }
          .poppy-popup > .poppy-popup-container > .poppy-popup-buttons > .poppy-popup-accept > a:active, .poppy-popup > .poppy-popup-container > .poppy-popup-buttons > .poppy-popup-cancel > a:active {
            box-shadow: inset 0 0 5px 1px rgba(0, 0, 0, 0.3); }
          .poppy-popup > .poppy-popup-container > .poppy-popup-buttons > .poppy-popup-accept > a > i, .poppy-popup > .poppy-popup-container > .poppy-popup-buttons > .poppy-popup-cancel > a > i {
            vertical-align: middle;
            margin-top: -3px; }
      .poppy-popup > .poppy-popup-container > .poppy-popup-buttons > .poppy-popup-accept {
        right: 0;
        color: #2088AD; }
        .poppy-popup > .poppy-popup-container > .poppy-popup-buttons > .poppy-popup-accept > a:hover {
          background-color: rgba(0, 0, 0, 0.1); }
      .poppy-popup > .poppy-popup-container > .poppy-popup-buttons > .poppy-popup-cancel {
        left: 0;
        color: #2088AD; }
        .poppy-popup > .poppy-popup-container > .poppy-popup-buttons > .poppy-popup-cancel > a:hover {
          background-color: rgba(0, 0, 0, 0.1); }

注意:css不变

关于javascript - 调用函数在上次调用中销毁回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57129474/

相关文章:

javascript - 带有\x 转义序列的 JS 正则表达式在 Firefox 中不起作用

javascript - JavaScript 中的变量作用域问题

javascript - 检测正在加载到 DOM 中的新图像,jQuery 加载事件处理程序不会触发

javascript - 我如何在网络浏览器中检查 gzip 解码时间?

javascript - 如何在 Chrome 中访问 iframe 父页面的功能?

javascript - Angular 2 : insert component into a certain position

javascript - 第二次调用后未提交表格

javascript - 当记录超过一个时,无法禁用文本字段

javascript - 如何将 bacon.js 中一个流的当前值与另一个流的每个值组合起来?

javascript - 无法在 Javascript 中进行递归调用