How can I improve this component with using event delegation rather than doing a lookup using parentNode
so that I can change the markup around without having to update the JavaScript?
HTML
<div class="drop-down-wrapper">
<div class="drop-down-btn-wrapper">
<div class="drop-down-open"><img src="http://placehold.it/175x35" /></div>
<div class="drop-down-closed"><img src="http://placehold.it/150x35" /></div>
</div>
<div class="drop-down-content js-drop-down">
<div class="content-wrapper">
<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit
</p>
</div>
</div>
</div>
JavaScript
(function(){
var dropDownClosed = 'js-drop-down',
dropDownButtonList = document.querySelectorAll('.drop-down-btn-wrapper');
function init() {
for(var i=0; i<dropDownButtonList.length; i++) {
dropDownButtonList[i].addEventListener('click', initDropdown, false);
}
}
function initDropdown(e) {
var event = e.target;
var contentWrapper = event.parentNode.parentNode.parentNode.childNodes[3];
var content = event.parentNode.parentNode.parentNode.childNodes[3].childNodes[1];
var closedButton = event.parentNode.parentNode.parentNode.childNodes[1].childNodes[3];
var contentHeight = content.offsetHeight;
if(hasClass(contentWrapper, dropDownClosed)) {
removeClass(contentWrapper, dropDownClosed);
contentWrapper.style.height = contentHeight+'px';
closedButton.style.opacity = '0.0';
} else {
addClass(contentWrapper, dropDownClosed);
contentWrapper.style.height = 0+'px';
closedButton.style.opacity = '1.0';
}
}
function hasClass(ele, cls) {
return ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
}
function addClass(ele, cls) {
if (!hasClass(ele, cls)) ele.className += " " + cls;
}
function removeClass(ele, cls) {
if (hasClass(ele, cls)) {
var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
ele.className = ele.className.replace(reg, '');
}
}
init();
}());
CSS
.drop-down-wrapper {
position:relative;
border: 2px black solid;
margin-bottom:20px;
padding:20px 0;
}
.content-wrapper {
padding:15px;
margin:30px 0;
}
.drop-down-open {
position:absolute;
top:0;
border: thin red solid;
}
.drop-down-closed {
position:absolute;
top:0;
border: 2px solid green;
}
.drop-down-content {
background-color:#fff;
overflow:hidden;
height:0;
}