javascript - Handle dropdown's focus state -
i making dropdown component in pure javascript. when user click on dropdown toggle, content gain focus , content being displayed. when user click outside of it, content loses focus , gets hidden.
so far, works great. however, encountering 2 problems.
the first 1 when element inside dropdown clicked (eg: anchor tags), dropdown loses focus, shouldn't.
the second 1 when dropdown toggle clicked while dropdown content being displayed, dropdown should close instead of closing re-opening due click registered on dropdown toggle.
html:
<div class="dropdown"> <a href="#" class="dropdown-toggle">dropdown toggle</a> <div class="dropdown-content" tabindex="0"> <ul> <li> <a href="http://example.com">my profile</a> </li> <li> <a href="http://example.com">log out</a> </li> </ul> </div> </div>
css:
.dropdown { position: relative; } .dropdown.is-open .dropdown-content { display: block; } .dropdown-content { display: none; position: absolute; top: 100%; width: 100%; padding: 0.5rem 0; background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5); }
js:
class dropdown { constructor(element) { this.element = element; this.toggle = this.element.queryselector('.dropdown-toggle'); this.content = this.element.queryselector('.dropdown-content'); this.bindings(); } bindings() { this.toggle.addeventlistener('click', this.open.bind(this)); this.content.addeventlistener('keydown', this.handlekeydown.bind(this)); this.content.addeventlistener('focusout', this.close.bind(this)); } open(e) { e.preventdefault(); this.element.classlist.add('is-open'); this.content.focus(); } close(e) { this.element.classlist.remove('is-open'); } handlekeydown(e) { if (e.keycode === 27) { this.close(e); } } } document.queryselectorall('.dropdown').foreach(dropdown => new dropdown(dropdown));
i have been trying head around on how solve these issues without luck. idea on how solve these issues?
after testing found solution works. try code below
class dropdown { constructor(element) { this.element = element; this.toggle = this.element.queryselector('.dropdown-toggle'); this.content = this.element.queryselector('.dropdown-content'); this.bindings(); } bindings() { this.toggle.addeventlistener('click', this.open.bind(this)); this.content.addeventlistener('keydown', this.handlekeydown.bind(this)); this.element.addeventlistener('focusout', this.onfocusout.bind(this),true); } onfocusout(e) { if (!this.element.contains(e.relatedtarget)) { this.close(e) } } open(e) { e.preventdefault(); this.element.classlist.toggle('is-open'); this.content.focus(); } close(e) { e.preventdefault(); this.element.classlist.remove('is-open'); } handlekeydown(e) { if (e.keycode === 27) { this.close(e); } } }
Comments
Post a Comment