下拉错误,如果点击太快,下拉列表中的选项仍然可见

时间:2017-04-25 08:28:21

标签: javascript html css drop-down-menu

我无法弄清楚为什么在点击下拉箭头过快时,即使关闭后,下拉菜单中的选项也会保留。

HTML

<div class="dropdown-container">
  <div class="dropdown-header">
    <h5 class="js-title-hook dropdown-title">
      Option 1
    </h5>
    <div class="toggle-button">
      <p>
        &darr;    
      </p>
    </div>
  </div>
  <div class="dropdown-options">
    <ul class="dropdown-options-list">
      <li class="js-hook-dropdown-list" data-title="Option 1">Option 1</li>
      <li class="js-hook-dropdown-list" data-title="Option 2">Option 2</li>
      <li class="js-hook-dropdown-list" data-title="Option 3">Option 3</li>
      <li class="js-hook-dropdown-list" data-title="Option 4">Option 4</li>
      <li class="js-hook-dropdown-list" data-title="Option 5">Option 5</li>
    </ul>
  </div>
</div>

CSS

.dropdown-container{
  width: 400px;
  font-family: 'helvetica';
  color: 2b2b2b;
  border-bottom: 1px solid #2b2b2b;
}

.dropdown-title{
  float: left;
  margin-right: 20px;
}

.toggle-button{
  display: inline-block;
  cursor: pointer;
  transform: rotate(0deg);
}

.dropdown-options{
  /* padding-top: 30px; */
}

.dropdown-options{
  visibility: hidden;
    opacity: 0;
    transition: height 1s, visibility 0.5s, opacity 0.5s ease-out;
}

.dropdown-options-list{
  list-style: none;
}

.dropdown-options-list li{
  margin-bottom: 5px;
  cursor: pointer;
}

.dropdown-options-list li:hover{
  color: #D62727;
}

的JavaScript

(function(){

  //Incase anything ever changes in the DOM
    var DOMstrings = {
      dropPointer: '.toggle-button',
      pageTitle: '.js-title-hook',
      dropOptions: '.dropdown-options',
      dropTitle: '.project-dropdown-title',
      listItems: '.js-hook-dropdown-list',
    }

    var dropPointer = document.querySelector(DOMstrings.dropPointer);
    var dropOptions = document.querySelector(DOMstrings.dropOptions);
    var dropTitle = document.querySelector(DOMstrings.dropTitle);
    var height = dropOptions.clientHeight;
    var width = dropOptions.clientWidth;

    //initisualise the height of drop options
    dropOptions.style.height = '0';

    // console.log(height + ' x ' + width);

    dropDown();

    function dropDown(){
      dropPointer.addEventListener('click', function(){

        //toggle for the pointer rotating
        if(dropPointer.style.transform !== "rotate(180deg)"){
          dropPointer.style.transform = "rotate(180deg)";

          setTimeout(function(){
            dropOptions.style.height = height + 'px';
            dropOptions.style.marginBottom = '10px';
          }, 150)

          setTimeout(function(){
              dropOptions.style.visibility = 'visible';
              dropOptions.style.opacity = '1';
          }, 700)

          // console.log(height + ' x ' + width);

        } else {
          closeDropdown();
        }
      });
    }

    function closeDropdown() {
      dropPointer.style.transform = "rotate(0deg)";
      dropOptions.style.visibility = 'hidden';
      dropOptions.style.opacity = '0';

      setTimeout(function(){
        dropOptions.style.height = '0';
        dropOptions.style.marginBottom = '0px';
      }, 200);

      setTimeout(function(){
        dropTitle.style.marginBottom = "0px";
      }, 500)

    }

    var elements = document.querySelectorAll(DOMstrings.listItems);
    var title = document.querySelector(DOMstrings.pageTitle);

    // console.log(listProjects);

    for(var i = 0; i < elements.length; i++){
      changeProject(elements[i]);
    }

    function changeProject(el) {
      el.addEventListener('click', function(e){

        var target = e.currentTarget;
        // console.log(target);

        title.innerHTML = target.dataset.title;

        closeDropdown();
      })
    }

})();

代码有点长,所以这里是说明行为的JSfiddle:https://jsfiddle.net/andylyell/jkjxmLxx/

谢谢!

2 个答案:

答案 0 :(得分:1)

问题取决于您的setTimeout功能dropDown()

如果在打开它的700ms内再次单击下拉按钮,将首先执行dropOptions.style.visibility = 'hidden';行,然后700ms超时将到期,因此将执行dropOptions.style.visibility = 'visible'; - 从而留下下拉列表在屏幕上可见。

要修复它,在每个setTimeout处理程序中,检查下拉列表是否仍然隐藏/显示,然后再修改dragOptions的属性。

这就是我的意思:

function dropDown(){
  dropPointer.addEventListener('click', function(){

    //toggle for the pointer rotating
    if(dropPointer.style.transform !== "rotate(180deg)"){
      dropPointer.style.transform = "rotate(180deg)";

      setTimeout(function(){
        if(dropPointer.style.transform !== "rotate(180deg)")return;
        dropOptions.style.height = height + 'px';
        dropOptions.style.marginBottom = '10px';
      }, 150)

      setTimeout(function(){
          if(dropPointer.style.transform !== "rotate(180deg)")return;
          dropOptions.style.visibility = 'visible';
          dropOptions.style.opacity = '1';
      }, 700)

      // console.log(height + ' x ' + width);

    } else {
      closeDropdown();
    }
  });
}

function closeDropdown() {
  dropPointer.style.transform = "rotate(0deg)";
  dropOptions.style.visibility = 'hidden';
  dropOptions.style.opacity = '0';

  setTimeout(function(){
    if(dropPointer.style.transform === "rotate(180deg)")return;
    dropOptions.style.height = '0';
    dropOptions.style.marginBottom = '0px';
  }, 200);

  setTimeout(function(){
    if(dropPointer.style.transform === "rotate(180deg)")return;
    dropTitle.style.marginBottom = "0px";
  }, 500);
}

Working JSFiddle

答案 1 :(得分:1)

为setTimeout函数创建一个全局变量,使内容可见:

thistimeout = setTimeout(function(){
          dropOptions.style.visibility = 'visible';
          dropOptions.style.opacity = '1';
      }, 700)

clearTimeout()函数中使用closeDropdown()来停止setTimeout函数

function closeDropdown() {
  clearTimeout(thistimeout);
  dropPointer.style.transform = "rotate(0deg)";
  dropOptions.style.visibility = 'hidden';

工作时尚:https://jsfiddle.net/VLK_STUDIO/jkjxmLxx/2/

(function(){

  //Incase anything ever changes in the DOM
    var DOMstrings = {
      dropPointer: '.toggle-button',
      pageTitle: '.js-title-hook',
      dropOptions: '.dropdown-options',
      dropTitle: '.project-dropdown-title',
      listItems: '.js-hook-dropdown-list',
    }

    var dropPointer = document.querySelector(DOMstrings.dropPointer);
    var dropOptions = document.querySelector(DOMstrings.dropOptions);
    var dropTitle = document.querySelector(DOMstrings.dropTitle);
    var height = dropOptions.clientHeight;
    var width = dropOptions.clientWidth;

    //initisualise the height of drop options
    dropOptions.style.height = '0';

    // console.log(height + ' x ' + width);

    dropDown();

    function dropDown(){
      dropPointer.addEventListener('click', function(){

        //toggle for the pointer rotating
        if(dropPointer.style.transform !== "rotate(180deg)"){
          dropPointer.style.transform = "rotate(180deg)";

          setTimeout(function(){
            dropOptions.style.height = height + 'px';
            dropOptions.style.marginBottom = '10px';
          }, 150)

          thistimeout = setTimeout(function(){
              dropOptions.style.visibility = 'visible';
              dropOptions.style.opacity = '1';
          }, 700)

          // console.log(height + ' x ' + width);

        } else {
          closeDropdown();
        }
      });
    }

    function closeDropdown() {
      clearTimeout(thistimeout);
      dropPointer.style.transform = "rotate(0deg)";
      dropOptions.style.visibility = 'hidden';
      dropOptions.style.opacity = '0';

      setTimeout(function(){
        dropOptions.style.height = '0';
        dropOptions.style.marginBottom = '0px';
      }, 200);

      setTimeout(function(){
        dropTitle.style.marginBottom = "0px";
      }, 500)

    }

    var elements = document.querySelectorAll(DOMstrings.listItems);
    var title = document.querySelector(DOMstrings.pageTitle);

    // console.log(listProjects);

    for(var i = 0; i < elements.length; i++){
      changeProject(elements[i]);
    }

    function changeProject(el) {
      el.addEventListener('click', function(e){

        var target = e.currentTarget;
        // console.log(target);

        title.innerHTML = target.dataset.title;

        closeDropdown();
      })
    }

})();