Accordion

by Wesley Oliver

HTML

<script src="https://use.fontawesome.com/02dcf8ce89.js"></script>

<script>

</script>

<style>

div[class~=stackable-group] [class~=heading]
{
  background-color: yellow;
}

div[class~=stackable-group] [class~=stackable-group-preview]
{
  background-color: blue;
}

div.scrollable
{
  overflow:auto;width:100%;height:100%;
}
div.stackable 
{
  position:relative;width:100%;height:100%;background-color:inherit;
}

div.stackable div.stackable-top
{  
  position:absolute;top:0;z-index:1;width:90%;height:auto;background-color:inherit;
}

div.stackable div.stackable-bottom
{
  position:absolute;bottom:0;z-index:1;width:90%;height:auto;background-color:inherit;
}

.collapsible-show
{
  display:none;
}

</style>

<a onclick="alert('heading position' + document.getElementById('scrollable').scrollTop + ':' + + document.getElementById('Heading2').offsetTop);">Show Position</a>

<a onclick="document.getElementById('headingContent').style.display='none';alert('ok');">Display None</a>

<div style="width:200px;height:300px;background-color:#990000">
  <div class="stackable">    
    <div class="scrollable" id="scrollable">  
     <ul>
          <li class="previewItem">No GroupItem1</li>
          <li>No GroupItem2</li> 
          <li>No GroupItem3</li>
          <li>No GroupItem4</li>
          <li>No GroupItem5</li>
          <li>No GroupItem6</li>
           <li>No GroupItem4</li>
          <li>No GroupItem5</li>
          <li>No GroupItem6</li>
           <li>No GroupItem6</li>
           <li>No GroupItem4</li>
          <li>No GroupItem5</li>
          <li>No GroupItem6</li>
          <li>No GroupItem4</li>
          <li>No GroupItem5</li>
          <li>No GroupItem6</li>
           <li>No GroupItem6</li>
           <li>No GroupItem4</li>
          <li>No GroupItem5</li>
          <li>No GroupItem6</li>
        </ul>       
      <div class="stackable-group collapsible">    
        <div class="heading collapsible-toggle">
        <i class="fa fa-plus-square-o...

JavaScript

var stackables = document.getElementsByClassName("stackable");

for(var i = 0; i < stackables.length; i++)
{
	var stackable = stackables[i];  
  
  var scrollable = stackable.getElementsByClassName("scrollable")[0];
  
  scrollable.onscroll = function(){updateStackable(this)};  
  
  updateStackable(scrollable);
}

function updateStackable(scrollable)
{ 
	var stackable = scrollable.parentElement;  
  var stackTop = stackable.getElementsByClassName('stackable-top');  
  
  if(stackTop.length === 0)
  {
  	stackTop = document.createElement('div');
    stackTop.setAttribute('class','stackable-top');
    stackTop.addEventListener('mousewheel', (event)=>
    {
    	scrollable.scrollTop = scrollable.scrollTop - event.wheelDeltaY;
    });
    stackable.insertBefore(stackTop, scrollable);
  }
  else
  	stackTop = stackTop[0];  
  
  var stackBottom = stackable.getElementsByClassName('stackable-bottom');
  
  if(stackBottom.length === 0)
  {
  	stackBottom = document.createElement('div');
    stackBottom.setAttribute('class','stackable-bottom');
    stackBottom.addEventListener('mousewheel', (event)=>
    {
    	scrollable.scrollTop = scrollable.scrollTop - event.wheelDeltaY;
    });
    stackable.appendChild(stackBottom);
  }
  else
  	stackBottom = stackBottom[0];
	
	var groups = scrollable.getElementsByClassName('stackable-group');  
  var stackTopGroups = stackTop.getElementsByClassName('stackable-group');
  var iBefore = 0;
  for(;iBefore < groups.length;iBefore++)
	{
  	var groupItem = groups[iBefore];           
  	var scrollTop = scrollable.scrollTop + stackTop.offsetHeight;  	
    var groupHeader = groupItem.getElementsByClassName('heading')[0];      
    
    if(iBefore < stackTopGroups.length)
    	scrollTop = scrollTop - groupHeader.offsetHeight;
    
    if(scrollTop > groupHeader.offsetTop)
    {    		
        if(iBefore >= stackTopGroups.length)
        {          
          var item = document.createElement('div');         
          
         ...