【问题标题】:Show/Hide Combobox Dropdown with pure Javascript使用纯 Javascript 显示/隐藏组合框下拉菜单
【发布时间】:2016-05-25 12:31:21
【问题描述】:

我在 asp.net 中有一个用户控件,它输出类似于以下的标记:

<div id="combobox1">
  <div id="combobox1_text"><span>combobox 1</span></div>
  <div id="combobox1_ddl">
    <input type="checkbox" id="combobox1_$1" />
    <label for="combobox1_$1">Item 1</label>
    <br />
    <input type="checkbox" id="combobox1_$2" />
    <label for="combobox1_$2">Item 2</label>
    <br />
    <input type="checkbox" id="combobox1_$3" />
    <label for="combobox1_$3">Item 3</label>
    <br />
    <input type="checkbox" id="combobox1_$4" />
    <label for="combobox1_$4">Item 4</label>
    <br />
    <input type="checkbox" id="combobox1_$5" />
    <label for="combobox1_$5">Item 5</label>
    <br />
  </div>
</div>

此控件附带的 javascript 文件具有以下类(仅用于重现问题的最少代码):

ComboBox = function(cb) {
  var pnlContainer = document.getElementById(cb);
  var pnlComboBox = document.getElementById(cb + '_text');
  var pnlDropdownList = document.getElementById(cb + '_ddl');
  var isCollapsed = true;

  var collapseDropdown = function() {
    if (!isCollapsed) {
      isCollapsed = true;
      pnlDropdownList.style.display = 'none';
      //-- some more custom handling code follows here --
    }
  };
  pnlComboBox.onclick = function() {
    isCollapsed = !isCollapsed;
    pnlDropdownList.style.display = (isCollapsed) ? 'none' : 'block';
  };
  pnlContainer.onclick = function(event) {
    event.stopPropagation();
  };
  document.addEventListener('click', function() {
    collapseDropdown();
  }, false);
}

最后,在我的页面上,我创建了一个这样的类的实例:

cb1 = new ComboBox('combobox1');

所有这些都可以正常工作,直到只有一个该控件的实例。只要单击控件之外的任何内容或任何位置,它就会正确折叠,正如预期的那样。

问题:

当页面上有多个此控件的实例时会出现问题。如果其中一个组合框打开,并且用户单击我的组合框的另一个实例,则前一个组合框不会折叠。

可以在此处找到用于重现问题的最少代码的 JsFiddle:

https://jsfiddle.net/x8qjo79f/

我知道这是因为event.stopPropagation() 来电,但不知道该怎么办。

【问题讨论】:

    标签: javascript asp.net combobox user-controls


    【解决方案1】:

    编辑文档 onclick 事件侦听器以捕获事件(因此它在冒泡阶段之前执行)并在其目标位于组合框之外时折叠。

    ComboBox = function(cb) {
      var pnlContainer = document.getElementById(cb);
      var pnlComboBox = document.getElementById(cb + '_text');
      var pnlDropdownList = document.getElementById(cb + '_ddl');
      var isCollapsed = true;
    
      var collapseDropdown = function() {
        if (!isCollapsed) {
          isCollapsed = true;
          pnlDropdownList.style.display = 'none';
          //-- some more custom handling code follows here --
        }
      };
      pnlComboBox.onclick = function() {
        isCollapsed = !isCollapsed;
        pnlDropdownList.style.display = (isCollapsed) ? 'none' : 'block';
      };
      pnlContainer.onclick = function(event) {
        event.stopPropagation();
      };
    
      // Edit: Capture click event
      document.addEventListener('click', function(event) {
        if (!pnlContainer.contains(event.target)) collapseDropdown();
      }, true);
    }
    
    cb1 = new ComboBox('combobox1');
    cb2 = new ComboBox('combobox2');
    #combobox1,
    #combobox2 {
      border: 1px solid black;
      cursor: default;
      width: 200px;
      font-family: verdana;
      font-size: 10pt;
    }
    
    #combobox1_text,
    #combobox2_text {
      padding: 2px;
    }
    
    #combobox1_ddl,
    #combobox2_ddl {
      border-top: 1px solid black;
      display: none;
    }
    <div id="combobox1">
      <div id="combobox1_text"><span>combobox 1</span></div>
      <div id="combobox1_ddl">
        <input type="checkbox" id="combobox1_$1" />
        <label for="combobox1_$1">Item 1</label>
        <br />
        <input type="checkbox" id="combobox1_$2" />
        <label for="combobox1_$2">Item 2</label>
        <br />
        <input type="checkbox" id="combobox1_$3" />
        <label for="combobox1_$3">Item 3</label>
        <br />
        <input type="checkbox" id="combobox1_$4" />
        <label for="combobox1_$4">Item 4</label>
        <br />
        <input type="checkbox" id="combobox1_$5" />
        <label for="combobox1_$5">Item 5</label>
        <br />
      </div>
    </div>
    <br />
    <input type="text" />
    <br />
    <input type="button" />
    <br />
    <input type="checkbox" />
    <br />
    <span>some random text in the document.. <br />blah. blah.. blah..</span>
    <br />
    <br />
    <br />
    <div id="combobox2">
      <div id="combobox2_text"><span>combobox 2</span></div>
      <div id="combobox2_ddl">
        <input type="checkbox" id="combobox2_$1" />
        <label for="combobox2_$1">Item 1</label>
        <br />
        <input type="checkbox" id="combobox2_$2" />
        <label for="combobox2_$2">Item 2</label>
        <br />
        <input type="checkbox" id="combobox2_$3" />
        <label for="combobox2_$3">Item 3</label>
        <br />
        <input type="checkbox" id="combobox2_$4" />
        <label for="combobox2_$4">Item 4</label>
        <br />
        <input type="checkbox" id="combobox2_$5" />
        <label for="combobox2_$5">Item 5</label>
        <br />
      </div>
    </div>

    【讨论】:

    • 我最初在onblur 事件中出现了下拉列表。问题出在 chrome 浏览器上,只要单击下拉区域中的复选框,它就会折叠下拉列表。我希望它一直打开,直到用户单击组合框外的任何位置,或者通过单击组合框文本区域折叠它。
    • 我修改了答案
    • 非常好。我观察到在此之后我不再需要event.stopPropagation() 调用,并且可以完全摆脱pnlContainer.onclick 事件处理。
    【解决方案2】:

    您可以允许在pnlContainer.onclick 中传播事件,但请记住单击了 ComboBox。在文档点击事件处理程序中,您将测试 ComboBox 是否是被点击的,如果不是,则允许折叠。

    对 Javascript 代码的更改可能如下所示:

    ComboBox = function(cb) {
      var isClicked = false;
      ...
      pnlContainer.onclick = function(event) {
        isClicked = true;
      };
      document.addEventListener('click', function() {
        if (isClicked) {
          isClicked = false;
        }
        else {
          collapseDropdown();
        }
      }, false);
    }
    

    【讨论】:

    • 摆脱event.stopPropagation() 电话的好方法。我可能一直只看一个方向。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-23
    • 2017-12-16
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 2012-08-03
    相关资源
    最近更新 更多