Show/Hide Combobox Dropdown with pure Javascript

Show/Hide Combobox Dropdown with pure Javascript

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

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

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

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);
}

最后,在我的页面上,我创建了一个 class 的实例,如下所示:

cb1 = new ComboBox('combobox1');

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

问题:

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

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

https://jsfiddle.net/x8qjo79f/

我知道这是因为 event.stopPropagation() 调用,但不知道该怎么做。

您可以在 pnlContainer.onclick 中允许事件传播,但请记住组合框已被单击。在文档单击事件处理程序中,您将测试 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);
}

编辑文档 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_" />
    <label for="combobox1_">Item 1</label>
    <br />
    <input type="checkbox" id="combobox1_" />
    <label for="combobox1_">Item 2</label>
    <br />
    <input type="checkbox" id="combobox1_" />
    <label for="combobox1_">Item 3</label>
    <br />
    <input type="checkbox" id="combobox1_" />
    <label for="combobox1_">Item 4</label>
    <br />
    <input type="checkbox" id="combobox1_" />
    <label for="combobox1_">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_" />
    <label for="combobox2_">Item 1</label>
    <br />
    <input type="checkbox" id="combobox2_" />
    <label for="combobox2_">Item 2</label>
    <br />
    <input type="checkbox" id="combobox2_" />
    <label for="combobox2_">Item 3</label>
    <br />
    <input type="checkbox" id="combobox2_" />
    <label for="combobox2_">Item 4</label>
    <br />
    <input type="checkbox" id="combobox2_" />
    <label for="combobox2_">Item 5</label>
    <br />
  </div>
</div>