Select options dynamically

This sample shows how a select element behaves when it options are loaded dynamically (from an ajax request to say something).

by Miguel Roman

HTML

<h1>Select loader as option element</h1>

<p>
Based on <a href="http://stackoverflow.com/a/570651" target="_blank">this stack overflow's thread</a> every browser has a default height for an empty <code>select</code> element, so we should add an specific number of <em>empty</em> <code>option</code> elements to display the maximun possible height (or perform a little research to see if it is possible to define it with css).
</p>

<h2>Select without blank options</h2>

<select id="select-demo-1">
  <option>Select an option</option>
  <option disabled="disabled">loading...</option>
</select>

<h2>Select with blank options</h2>

<select id="select-demo-2">
  <option>Select an option</option>
  <option disabled="disabled">loading...</option>
  <option disabled="disabled"></option>
  <option disabled="disabled"></option>
  <option disabled="disabled"></option>
  <option disabled="disabled"></option>
  <option disabled="disabled"></option>
  <option disabled="disabled"></option>
</select>

<h2>A little different approach</h2>

<select id="select-demo-3" style="width: 118px">
  <option>Select an option</option>
  <option disabled="disabled"></option>
  <option disabled="disabled"></option>
  <option disabled="disabled"></option>
  <option disabled="disabled"></option>
  <option disabled="disabled"></option>
  <option disabled="disabled"></option>
  <option disabled="disabled"></option>
</select>

<blockquote>
<p>
<strong>Important Note:</strong> in the real behavior, the options will be loaded when the user select change the previous (or parent) select, so this is a concern only when the user click on the select and the data isn't ready yet and <strong style="color:red">for some reason in IE the options are not updated until the user close and open again de dropdown</strong>.
</p>  
</blockquote>

JavaScript

var waitMilliseconds = 1000;
var sampleData = [
	{ id: 1, name: "uno" }, 
  { id: 2, name: "dos" },
  { id: 3, name: "tres" },
  { id: 4, name: "cuatro" },
];

(function init(document) {

	
	addEventToSelect("select-demo-1");
  addEventToSelect("select-demo-2");
  addEventToSelect("select-demo-3");

	function addEventToSelect(selectId) {
  	document.getElementById(selectId).addEventListener("click", selectClick)
  }

  function selectClick(event) {
  	var target = event.target;
    target.removeEventListener("click", selectClick);
    if (target.id === "select-demo-3") demo3(target);
    setTimeout(renderData.bind(this, target, sampleData), waitMilliseconds);
  }
  
  function demo3(target) {
  	target.firstElementChild.innerText = "loading..."
  }

  function renderData(selectControl, data) {
		removeLoader(selectControl);
    for (var i = 0; i < data.length; i++) {
    	selectControl.appendChild(createOption(data[i]));
    }
    selectControl.firstElementChild.innerText = "Select an option"
  }
  
  function createOption(item) {
  	var option = document.createElement("option");
    option.value = item.id;
    option.innerText = item.name;
    return option;
  }

  function removeLoader(selectControl) {
      var elementsToRemove = selectControl.querySelectorAll("[disabled]");
      if (!elementsToRemove) return;
      for (var i = 0; i < elementsToRemove.length; i++) {
      	selectControl.removeChild(elementsToRemove[i]);
      }
  }

})(document);