JS - COLLAPSER COMPONENT

by Rodwyn Moreno

HTML

<div class="collapser" data-step="1">
  <div class="collapser-list">
    <div class="collapser-item">A</div>
    <div class="collapser-item">B</div>
    <div class="collapser-item">C</div>
    <div class="collapser-item">D</div>
    <div class="collapser-item">E</div>
    <div class="collapser-item">F</div>
  </div>
</div>

<div class="collapser" data-step="2">
  <div class="collapser-list">
    <div class="collapser-item">A</div>
    <div class="collapser-item">B</div>
    <div class="collapser-item">C</div>
    <div class="collapser-item">D</div>
    <div class="collapser-item">E</div>
    <div class="collapser-item">F</div>
    <div class="collapser-item">G</div>
    <div class="collapser-item">H</div>
    <div class="collapser-item">I</div>
    <div class="collapser-item">J</div>
    <div class="collapser-item">K</div>
    <div class="collapser-item">L</div>
  </div>
</div>

CSS

.collapser {
  border: red solid thin;
}

.collapser-list {
  overflow: hidden;
  transition: height 0.15s ease-out;
}

.collapser-control {
  background-color: rgb(232,230,232);
  box-shadow: 0 -2px 0 0 rgba(235,232,235,0.75);
  text-align: center;
  font-size: 12px;
}

.collapser-handler {
  cursor: pointer;
}

JavaScript

class Collapser {
	constructor(element) {
  	this.element = element;
    this.setCollapserHeight = this.setCollapserHeight.bind(this);
    this.renderCollapserControl = this.renderCollapserControl.bind(this);
    this.removeCollapserControl = this.removeCollapserControl.bind(this);
    this.init = this.init.bind(this);
    this.currentItem = 0;
    this.init();
  }
  
  init() {
  	this.renderCollapserControl();
    this.setCollapserHeight();
  }
  
  removeCollapserControl() {
  	let collapserControl = this.element.querySelector('.collapser-control');
    
    if (collapserControl.parentNode) {
      collapserControl.parentNode.removeChild(collapserControl);
    }
  }
  
  setCollapserHeight() {
  	let collapserList = this.element.querySelector('.collapser-list');
    let collapserItems = this.element.querySelectorAll('.collapser-item');
    let collapserHeight = 0;
    
    this.currentItem += parseInt(this.element.dataset.step);
    
    collapserItems.forEach((item, index) => {
    	if (index+1 <= this.currentItem) {
      	collapserHeight += parseInt(item.offsetHeight);
      } else {
      	this.removeCollapserControl();
      }
    });
    
    collapserList.style.height = `${collapserHeight}px`;
  }
  
  renderCollapserControl() {
  	let collapserControl = document.createElement('div');
    let collapserHandler = document.createElement('div');
    
    collapserControl.className = 'collapser-control';
    collapserHandler.className = 'collapser-handler';
    collapserHandler.innerText = 'clik';
    
    collapserControl.appendChild(collapserHandler);
    this.element.appendChild(collapserControl);
    collapserHandler.addEventListener('click', this.setCollapserHeight);
  }
}

let collapserList = document.querySelectorAll('.collapser');

collapserList.forEach(collapser => {
	new Collapser(collapser);
});