[英]Instances conflicting on events
So I am trying to make a dropdown. 所以我想尝试下拉。 It works fine except for when I click on one to expand and then click on the other, then when I make a selection on one of them both close. 它工作正常,除了我点击一个展开然后点击另一个,然后当我选择其中一个都关闭。 What is the work around this as well as well as what is the best practice/approach for this situations. 围绕此问题的工作是什么以及针对这种情况的最佳实践/方法是什么。
var extend = function(){ if(!arguments.length) return {}; else if (arguments.length == 1) return arguments[0]; var primary = arguments[0]; for(var v = 1; v < arguments.length; ++v){ for(prop in arguments[v]){ primary[prop] = arguments[v][prop]; } } return primary; }; var Dropdown = (function(){ self = undefined; Dropdown.instances = []; function Dropdown(element, options){ self = this; this.settings = extend(this.defaults, options); console.log(this.settings); this.element = this.getElement(element); this.trigger = this.getElement(options.trigger); if(!this.element) throw new Error('No element found.'); if(!this.trigger) throw new Error('No trigger found.'); if(!this.settings.optionSelector) throw new Error('Option Selector Not Defined.'); if(this.element.dropdown) throw new Error('Dropdown already exists.'); this.element.dropdown = this; Dropdown.instances.push(this); this.attachTriggerListener = function(event, trigger, dropdown){ trigger.addEventListener(event, function(e){ e.stopPropagation(); dropdown.classList.remove('hidden'); dropdown.classList.add('visible'); }, false); document.addEventListener('click', function(e){ dropdown.classList.remove('visible'); dropdown.classList.add('hidden'); trigger.innerHTML = e.target.innerHTML; }, false); }; this.init(); } Dropdown.prototype.defaults = { css: '', optionSelector: undefined, trigger: undefined, triggersOn: 'click', onShow: function(){}, onClose: function(){}, }; Dropdown.prototype.init = function(){ this.element.classList.add('g-dropdown'); this.element.classList.add('hidden'); this.attachTriggerListener(this.settings.triggersOn, this.trigger, this.element); }; Dropdown.prototype.getElement = function(object){ if(typeof object == 'object' && object instanceof HTMLElement) return object; else if(typeof object == 'string') return document.querySelector(object); }; return Dropdown; }()); var dropdown = new Dropdown('#select', { optionSelector: 'li', trigger: '#trigger' }); var dropdown = new Dropdown('#select2', { optionSelector: 'li', trigger: '#trigger2' });
.g-dropdown{ max-height: 100px; max-width: 75px; overflow: scroll; -webkit-transition: visibility 0.50s, height 0.50s; -moz-transition: visibility 0.50s, height 0.50s; transition: visibility 0.50s, height 0.50s; } .g-dropdown.visible{ visibility: visible; height: 100px; } .g-dropdown.hidden{ visibility: hidden; height: 0px; }
<button id='trigger'>Click Me</button> <ul id='select' style='padding: 0; margin: 0;'> <li>One-one</li> <li>Two-two</li> <li>Three-three</li> <li>Four-four</li> <li>Five-five</li> </ul> <br/><br/><br/> <button id='trigger2'>Click Me</button> <ul id='select2' style='padding: 0; margin: 0;'> <li>One-one</li> <li>Two-two</li> <li>Three-three</li> <li>Four-four</li> <li>Five-five</li> </ul>
So how would I have to modify it so it also closes the dropdown on clicking outside the dropdown? 那么我将如何修改它以便在下拉列表外单击时关闭下拉列表?
Try checking e.target.parentElement.nodeName
, this.element.nodeName
at if
condition within document.addEventListener
handler , adding , removing class
of dropdown
if parent element is ul
, else adjusting class
of clicked li
parent element ul
请检查e.target.parentElement.nodeName
, this.element.nodeName
在if
内条件document.addEventListener
处理程序,添加,删除class
的dropdown
,如果父元素是ul
,否则调整class
点击的li
父元素ul
document.addEventListener('click', function(e){
if (e.target.parentElement.nodeName !== this.element.nodeName) {
dropdown.classList.remove('visible');
dropdown.classList.add('hidden');
} else {
e.target.parentElement.classList.remove('visible');
e.target.parentElement.classList.add('hidden');
}
self.settings.onClose(e.target);
}.bind(this), false);
var extend = function(){ if(!arguments.length) return {}; else if (arguments.length == 1) return arguments[0]; var primary = arguments[0]; for(var v = 1; v < arguments.length; ++v){ for(prop in arguments[v]){ primary[prop] = arguments[v][prop]; } } return primary; }; var Dropdown = (function(){ self = undefined; Dropdown.instances = []; function Dropdown(element, options){ self = this; this.settings = extend(this.defaults, options); console.log(this.settings); this.element = this.getElement(element); this.trigger = this.getElement(options.trigger); if(!this.element) throw new Error('No element found.'); if(!this.trigger) throw new Error('No trigger found.'); /* if(!this.settings.optionSelector) throw new Error('Option Selector Not Defined.'); */ if(this.element.dropdown) throw new Error('Dropdown already exists.'); this.element.dropdown = this; Dropdown.instances.push(this); this.attachTriggerListener = function(event, trigger, dropdown){ trigger.addEventListener(event, function(e){ e.stopPropagation(); dropdown.classList.remove('hidden'); dropdown.classList.add('visible'); }, false); document.addEventListener('click', function(e){ if (e.target.parentElement.nodeName !== this.element.nodeName) { dropdown.classList.remove('visible'); dropdown.classList.add('hidden'); } else { e.target.parentElement.classList.remove('visible'); e.target.parentElement.classList.add('hidden'); } self.settings.onClose(e.target); }.bind(this), false); }; this.init(); } Dropdown.prototype.defaults = { css: '', optionSelector: undefined, trigger: undefined, triggersOn: 'click', onShow: function(){}, onClose: function(){}, }; Dropdown.prototype.init = function(){ this.element.classList.add('g-dropdown'); this.element.classList.add('hidden'); this.attachTriggerListener(this.settings.triggersOn, this.trigger, this.element); }; Dropdown.prototype.getElement = function(object){ if(typeof object == 'object' && object instanceof HTMLElement) return object; else if(typeof object == 'string') return document.querySelector(object); }; return Dropdown; }()); var dropdown1 = new Dropdown('#select', { optionSe1lector: 'li', trigger: '#trigger' }); var dropdown2 = new Dropdown('#select2', { optionSe2lector: 'li', trigger: '#trigger2' });
.g-dropdown{ max-height: 100px; max-width: 75px; overflow: scroll; -webkit-transition: visibility 0.50s, height 0.50s; -moz-transition: visibility 0.50s, height 0.50s; transition: visibility 0.50s, height 0.50s; } .g-dropdown.visible{ visibility: visible; height: 100px; } .g-dropdown.hidden{ visibility: hidden; height: 0px; }
<button id='trigger'>Click Me</button> <ul id='select' style='padding: 0; margin: 0;'> <li>One-one</li> <li>Two-two</li> <li>Three-three</li> <li>Four-four</li> <li>Five-five</li> </ul> <br/><br/><br/> <button id='trigger2'>Click Me</button> <ul id='select2' style='padding: 0; margin: 0;'> <li>One-one</li> <li>Two-two</li> <li>Three-three</li> <li>Four-four</li> <li>Five-five</li> </ul>
You could use event.currentTarget
to know which element triggers the event and so find the element you need this target to show, that way your code will shorter and simpler 您可以使用event.currentTarget
来了解触发事件的元素,从而找到您需要此目标显示的元素,这样您的代码将更短更简单
Try something like this: 尝试这样的事情:
var btn1 = document.getElementById('btn-1'); var btn2 = document.getElementById('btn-2'); function toggle(event) { var nextNode = event.currentTarget.nextElementSibling; nextNode.classList.toggle('disable'); nextNode.classList.toggle('enable'); } btn1.addEventListener('click', toggle, false); btn2.addEventListener('click', toggle, false);
.disable { max-height: 0px; overflow: hidden } .enable { max-height: initial; overflow: initial }
<div class="first-container"> <button id="btn-1">Click Me</button> <ul id="list-1" class="disable"> <li>item-1</li> <li>item-2</li> <li>item-3</li> <li>item-4</li> <li>item-5</li> </ul> </div> <div class="second-container"> <button id="btn-2">Click Me</button> <ul id="list-2" class="disable"> <li>item-1</li> <li>item-2</li> <li>item-3</li> <li>item-4</li> <li>item-5</li> </ul> </div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.